Command Bar Archives - Aric Levin's Digital Transformation Blog https://aric.isite.dev/tag/command-bar/ Microsoft Dynamics 365, Power Platform and Azure Thu, 12 May 2022 03:21:26 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.3 Collaboration enhancements in 2022 Release Plan Wave 1 https://aric.isite.dev/dynamics/post/collaboration-enhancements-2022w1/ Thu, 31 Mar 2022 04:34:00 +0000 https://aric.isite.dev/index.php/2022/03/31/collaboration-enhancements-in-2022-release-plan-wave-1/ Collaboration seems to have been on Microsoft’s roadmap for some time now, and with the updates to the Power Platform in the 2022 Wave 1 Release Plan, there are a few enhancements in this collaboration space for Model Driven apps. In this post, I will go over some of these enhancements and demonstrate how this functionality is used and displayed in your dataverse environment.

The post Collaboration enhancements in 2022 Release Plan Wave 1 appeared first on Aric Levin's Digital Transformation Blog.

]]>
Collaboration seems to have been on Microsoft’s roadmap for some time now, and with the updates to the Power Platform in the 2022 Wave 1 Release Plan, there are a few enhancements in this collaboration space for Model Driven apps. In this post, I will go over some of these enhancements and demonstrate how this functionality is used and displayed in your dataverse environment.

First, let’s go ahead and start by enabling these new features. As with previous functionality that I wrote about, enabling the new collaboration features is done via the Power Platform Admin Center. Navigate to your Power Platform Admin Center, select your environment and Go to Settings and Features. Within Features, you will see a section called Collaboration at the bottom of the page (currently). The Enable preview of the modern link sharing UI, co-presence, online status in model-driven apps is going to be set to Off by default. Change this setting to On in order to enable these features.

You can also set the time of the refresh interval for Co-presence, which is set by default to 60 seconds. Don’t set it to a number that is too small or it might have some performance implications. The screenshot below shows you these settings in the Power Platform Admin Center.

2022 Release Wave 1 - Power Platform Admin Center - Collaboration features

Once we have set this option let’s go ahead and navigate back to our Model Driven app. We will open to browser windows with two different users logged in and accessing the same record. What we will see on the screen is that on the right hand side of the command bar, it will display the initials and presence of the other user or users that are logged into the system accessing that same record. This will allow us to quickly connect and collaborate with these other users. The image(s) below show two users logged on to the same record and being able to see that the other is accessing the record.

2022 Release Wave 1 - Collaboration - Co Presence

2022 Release Wave 1 - Collaboration - Co Presence

When you click on the bubble of the one of the users, you will have a couple of options to start collaboration with them. You will be able to Send the other user an email, Start a Teams chat or open their Contact card and start collaboration from there. See these options in the following screenshot.

2022 Release Wave 1 - Model driven apps - Collaboration Options

The next enhancement that is coming out is how the Owner of the record is presented. With this new release plan, the owner will have the presence bubble next to their name. Hovering over their presence will pop up their presence card contact information and list of recent files, and the ability to expand and see their full ownership information. The screenshot below shows some of that information.

2022 Release Wave 1 - Model driven apps - Owner field profile card

Next, we can see that next to the bubble of the other users accessing the record, we have the Share button. This allows us to share and manage the access to this record with other users.

2022 Release Wave 1 - Model driven apps - Share record

Once we click on the Share button, we will be able to select the users and/or teams that we want to share access to this record with, and provide them with the appropriate Read/Write permissions as required. We can see this in the image below.

2022 Release Wave 1 - Model driven apps - Manage Access/Sharing

There are likely to be additional collaboration changes that will be coming up in the new future to Unified Interface, but for the meantime, I hope you will enjoy the enhancements to this Wave Release.

The post Collaboration enhancements in 2022 Release Plan Wave 1 appeared first on Aric Levin's Digital Transformation Blog.

]]>
Power Platform 2021 Release Wave 2 Maker Portal Updates – Modern Commanding https://aric.isite.dev/dynamics/post/2021-wave2-modern-commanding/ Mon, 11 Oct 2021 05:27:00 +0000 https://aric.isite.dev/index.php/2021/10/11/power-platform-2021-release-wave-2-maker-portal-updates-modern-commanding/ In preparation for our upcoming NYC BizApps event on October 27, 2021, and the Power Platform 2021 Wave 2 release (weekend of October 23/24), I am writing a series of blog posts related to some of the most sought after updates. In this post we will review the new modern commanding using Power FX.

The post Power Platform 2021 Release Wave 2 Maker Portal Updates – Modern Commanding appeared first on Aric Levin's Digital Transformation Blog.

]]>
In preparation for our upcoming NYC BizApps event on October 27, 2021, and the Power Platform 2021 Wave 2 release (weekend of October 23/24), I am writing a series of blog posts related to some of the most sought after updates. In this post we will review the new modern commanding using Power FX.

Command bars are at the core of every model-driven app and appear in many different locations. They are arranged in relation to other commands and are associated with a command bar location. The group of commands associated with a specific location make up a command bar.

One of the biggest deficiencies of the Classic Commands, formerly known as the Ribbon, is that there is no low code solution to customize these commands. Command bars can be difficult to customize and error prone (although life has been simplified with the Ribbon Workbench by Scott Durow).

Modern command bars address some of the gaps and difficulties that we had with the legacy commands, and provide support for both Power FX and JavaScript.

Let’s go ahead and take a look at how we can implement modern commanding within our apps. I will use one of the apps that I previously created for this, and add a command bar button that will use Power FX to show/hide the button as well as a custom function that will execute on the click of the button.

In order to start using the new Command functionality, we first need navigate to the page (table in this case) that we want to work with, and select the Edit command bar (preview) option by clicking on the more options to the right of the table name and selecting that option as shown in the image below. This has to be achieved from the Pages navigation pane.

Power FX Commanding - Edit Command Bar

This will pop up a dialog where we have to select what command bar we would like to customize. There are four available options to select which include the Main grid, Main form, Subgrid view and Associated view. The image below shows these options.

Power FX Commanding - Select Command Bar

Let’s go ahead and select Main form. When the Commands page open, we will see a view that contains all of the existing command bar buttons that are available for the table within the Main form. At this point in time (as this is still in preview, and we don’t know the exact timeline of release), modifying the existing buttons is not currently supported, so any customizations that is needed for this, will have to be done using Ribbon Workbench. The image below shows you the Main form Command Bar before we have added any additional buttons.

Power FX Commanding - Select Command Bar

Now let’s go ahead and create a new command. We will create a simple command that is called Calculate Credit Limit which when clicked will multiple the number of employees in the company by 10,000, and will set it to only be visible when the number of employees contains data.

To start creating a new command, we click on the new Command button on the top of the left navigation pane.

Power FX Commanding - New Command Bar button

Once we click on the new command button, we will see that a has been created. We can move the command (using drag and drop) within the Main form to place it in the appropriate location, however this can only be done for new commands, and not the existing ones. Let’s provide the new command some of the properties, such as the Label, Icon to use and the Tooltip text.

Power FX Commanding - Command Bar button properties

Next, we would like to set the functions for the Action that will be performed when the button is clicked as well as the Visibility of the button. On the right Command Pane, the last two options are Action and Visibility. The Action selection has two options: Run formula and Run JavaScript.

If we use the Run JavaScript option we can provide the name of the library and the name of the function to call when the button is clicked. This is more of a legacy type of action which might be used in the future for enabling the legacy buttons. The Run formula allows us to Run Power FX code when the command is clicked.

We can use the Patch function together with the Self.Selected.Item together in order to update the Credit Limit, and then compare the Number of Employees to Blank to control the visibility of the button. I am still working a few glitches as to what is working and what is not when it comes to Power FX for commanding, but the code below is working properly.

On Select:

Set(TotalCredit, Self.Selected.Item.’Number of Employees’ * 10000);

Patch(Accounts, Self.Selected.Item, {‘Credit Limit’: TotalCredit});

Visible:

Self.Selected.Item.’Number of Employees’ <> Blank()

The following Microsoft Docs pages provide an overview of Modern Commanding, directions on the use of the command designer and how to use Power Fx for modern commands.

Now, let’s look at the end result after adding the button and publishing the app commands.

Power FX Commanding - Calculate Credit Limit Command Bar in use

Additional posts related to the Dynamics 365 and Power Platform 2021 Release Wave 2 will be posted by following the link below:

Power Platform 2021 Wave 2 Release Posts

The post Power Platform 2021 Release Wave 2 Maker Portal Updates – Modern Commanding appeared first on Aric Levin's Digital Transformation Blog.

]]>
Removing your Command Bar Unmanaged Active Layer in Model Driven Apps https://aric.isite.dev/dynamics/post/remove-commandbar-unmanaged-layer/ Wed, 15 Sep 2021 04:16:00 +0000 https://aric.isite.dev/index.php/2021/09/15/removing-your-command-bar-unmanaged-active-layer-in-model-driven-apps/ In the last few months I have been working on upgrading the customer´s unmanaged environments to managed. The customer had been working with unmanaged environments for about 5 years, and after joining, this has been one of the first things that I determined would be needed for this customer.

The post Removing your Command Bar Unmanaged Active Layer in Model Driven Apps appeared first on Aric Levin's Digital Transformation Blog.

]]>
In the last few months I have been working on upgrading the customer´s unmanaged environments to managed. The customer had been working with unmanaged environments for about 5 years, and after joining, this has been one of the first things that I determined would be needed for this customer.

The challenge was not so easy. We are still not fully managed in all the environments, but as a stepping stone, all environments with the exception of production are already managed and as we are working on a large migration, the final deployment is only a few months away.

After reading and watching the Microsoft blog and video on what they had to go through with Success Hub, I felt that my endeavor was not as complex. You can read the blog and see the video by clicking on the links below:

https://powerapps.microsoft.com/en-us/blog/how-a-microsoft-team-transitioned-from-unmanaged-to-managed-power-platform-solutions/

https://docs.microsoft.com/en-us/power-platform/alm/move-from-unmanaged-managed-alm

https://www.youtube.com/watch?v=3Uu5C9zkIjo (PowerCAT Live)

As with many of these special projects, there are sometimes blockers that you need to address with the functionality of your application. Ours was related to command bar customizations not being deployed from our development environment (unmanaged) to our QA environment (managed).
My apologies in advance for all the bluring, but this was the only way to get the screenshots.

The screenshots below show the difference between the functionality in our development and qa environments after the re-deployment of our managed solution to qa.

Command Bar UX - Dev Environment

Command Bar UX - Test Environment

As we saw this difference we wanted to go ahead and compare the Ribbon customization differences between the environments, and just as the UX had the differences, so did the commands themselves. It seemed like there was an enable rule missing in the qa environment that was not missing in the development environment. This was done of course using the Command Checker utility that can be invoked by adding the ribbondebug=true key/value to your query string
(ex: https://dev.crm.dynamics.com/main.aspx?appid=1234&forceUCI=1&ribbondebug=true&pagetype=entityrecord&etn=account&id=1234)

See image below for comparison

Command Bar Check - Dev Environment

Command Bar Checker - Test Environment

As with many of the know issues with managed solutions and customizations that do not get overwritten (we experienced this with cloud flows as well), the issue is usually when there is an Unmanaged Layer on top of a Managed layer, and then the customizations do not get overwritten.

When we clicked on the Command Checker, and selected the command that was not performing as expected (1), chose Command Properties (2) we can see the rules that were supposed to be enabled in this environment.

Command Bar Checker - Get to solution layers

The rule that we were expected was not visible. Clicking on the View command definitions solution layers (3) will display any layers that are being used for the command that we are looking at. The image below shows you the results that we saw when clicking on the link.

Command Bar Checker - Layers

In the Command checker solution layers pane, you can also select two layers and compare them to see the CommandDefinition code of the RibbonDiffXml.

Once we saw that there was an Unmanaged Layer (Active Layer) on top of our managed solution layer, the solution was pretty easy, but we required to do this in a few places.

The first thing is we created a new solution in our qa environment. We called this solution Command Bar Fixes, and added the table were we had to fix the customizations. When we added the table, we only selected Include table metadata from the options, and did not select any components. Image below:

Command Bar - Add Table to Solution (Table Metadata Only)

Our solution contained a single table with only the table metadata as shown below.

Command Bar - Export Table Metadata Solution

We then Export the solution. There should not really be a need to publish customizations before (as we have previously seen the results in the Command Checker), but if you are accustomed to this practice, do not change your ways…

Once we export the solution, we navigate to our downloads folder and extract the Command Bar Fixes solution. We open the newly created folder, and within the folder we open the customizations.xml file using an editor of our choice. The customizations.xml file should contain the table specific information as well as the Ribbon Diff Xml and other information about the table. The image below shows this file before we fix it.

Command Bar - Import Export Xml (Before Changes)

I collapsed the RibbonDiffXml containing all the commands, as these are not really relevant. We will go ahead and remove all of the inner Xml of the RibbonDiffXml section, and only leave the <RibbonDiffXml /> tag so that it looks like the image below.

Command Bar - Import Export Xml (After RibbonDiffXml removal)

We then save the changes, and select all the files that are in the extracted folder. Right click and select Send To, and Compressed Folder. We will reimport the newly created zip file.

Navigate back to the Maker portal, click on solutions and select import. In the browse panel, select the zip file that you just created containing the customizations.xml, solutions.xml and [Content_Types].xml.

Import the file and publish your changes. After this navigate back to the table were you experienced the issue and validate that the active layer is now gone and you only have the managed layer.

Hope this was helpful. It was painful for us to get the resolution, so maybe it will help some of you.

The post Removing your Command Bar Unmanaged Active Layer in Model Driven Apps appeared first on Aric Levin's Digital Transformation Blog.

]]>
Custom Page and Command Bars in Model-driven Apps https://aric.isite.dev/powerapps/post/powerapps-custom-pages-powerfx-commanding/ Thu, 29 Jul 2021 08:41:00 +0000 https://aric.isite.dev/index.php/2021/07/29/custom-page-and-command-bars-in-model-driven-apps/ In the last few days, Microsoft made some big announcements related to new features that are not available in public preview. These are the Public Preview of Custom Pages for converging mode-driven apps and canvas apps as well as the command designer for model-driven apps with Power FX (which is still in preview).

The post Custom Page and Command Bars in Model-driven Apps appeared first on Aric Levin's Digital Transformation Blog.

]]>
In the last few days, Microsoft made some big announcements related to new features that are not available in public preview. These are the Public Preview of Custom Pages for converging mode-driven apps and canvas apps as well as the command designer for model-driven apps with Power FX (which is still in preview).

You can read about these two announcements in the Microsoft Power Apps blogs or by clicking on the links below:

https://powerapps.microsoft.com/en-us/blog/custom-pages-for-converging-model-driven-apps-and-canvas-apps/

https://powerapps.microsoft.com/en-us/blog/announcing-command-designer-with-power-fx-preview/

Now, let’s go ahead and review each one of these separately.

Custom Pages:

Let’s start with Custom pages. Custom pages can be used within our model-driven apps anywhere where all pages are supported. This means the main area of the application, dialogs or the new app side pane. It allows the ability to have functionality that is not achievable using the standard features of model-driven apps, but can be achieved using canvas apps.

Custom pages can be opened from the site map for ease of access or from existing model-driven app logic using the Client Api. Custom pages can also open other custom pages or model-driven app pages. They give us the ability to author pages that are too complex to achieve within the existing model pages.

When we create a new app we can now easily add custom pages and take advantage of Canvas Authoring.

There are a few ways to start with custom pages, but let’s go ahead and start by creating a new app.

First thing, let’s navigate to the maker portal, so that we can start creating the new app. As of the time of writing this blog post, we would need to access this by going to the preview maker portal at https://make.preview.powerapps.com.

To start creating the new app, click on the “+ New app” command bar button and select Model-driven from the drop down menu.

PowerApps Converged Apps - New Model Driven App

This will pop up the create model driven app from blank window, where we can select to use the Modern app designer (preview) or the Classic app designer. To start with the Modern app designer, select that choice, and click Create.

PowerApps Converged Apps - Select Design Experience

Next we will need to give the app a name, and an optional description, and click on the Create button.

PowerApps Converged Apps - Enter Name and Description

After a few seconds the new app will be created, and we can start adding pages. There are three different types of pages that can be created, these are table based view and form, dashboard and custom (which is currently in preview). The animated image below shows you the three options.

PowerApps Converged Apps - Select Page Type

We will start by selecting the table type, once selected you will have the option to select the appropriate table or tables that you want to add to your app, and with an option to add these pages to your site map as well.

When you click on the add button, you will be able to see a preview of your app directly from the designer window, basically a preview of what you app would look like. The image below shows you the preview window. You will notice that the center area is the preview, and on the left hand side we see the tables that were added to the app.

The preview area, not only shows you the way the app looks, but allows you to change the layout so that you see how the app will look in responsive design for different devices.

You will also notice the section to the left that is expanded to show the data tables, which contains links to the pages and navigation. This first link shows you the tables, dashboards and custom pages that make up your app, while the second link shows you the site map. These were covered in additional detail in a previous blog post.

New Model-Driven App Designer

Let’s go ahead and add a custom page. Under the pages left hand navigation area (or from the command bar), click on Add page, and select the Custom (preview) option. Once selected you will have the option to create a new custom page or use an existing custom page that was previously created. In our case, since we don’t have an existing custom page, we will Create a new custom page and give it a name.

PowerApps Converged Apps - New Custom Page

Once we enter a name, this will open a new designer, and we can start working on the new app. I have added to the app a couple of galleries and commands so that we can see how this looks and works in our model-driven app. The image below shows the app that we created. Once you are satisfied with the app, click on the Save button and then publish it.

Close the custom page, and then go ahead and Save and Publish the Model-driven app that you created. The animated image below shows the end result of the custom page inside the model-driven app.

PowerApps Converged Apps - Custom Page in Model Driven App

To learn how to navigate between your Canvas app and the model-driven app, you can read more about it in the following Microsoft Docs page : https://docs.microsoft.com/en-us/powerapps/maker/model-driven-apps/page-powerfx-in-model-app

Custom pages can also be available by calling them from JavaScript within the Model Driven App by using the Xrm.Navigation.navigateTo function and providing a page type “custom”, and providing the name of the custom page (canvas app). You can then open the custom page inline or as a centered dialog. The following Microsoft Docs page includes samples on how to open this page: https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/navigate-to-custom-page-examples

Command Bars using Power FX:

Next, we will take a look at using Command Bars. We will use the same app that we already created, and add a command bar button that will use Power FX to show/hide the button as well as a custom function that will execute on the click of the button.

In order to start using the new Command functionality, we first need navigate to the page (table in this case) that we want to work with, and select the Edit command bar (preview) option by clicking on the more options to the right of the table name and selecting that option as shown in the image below. This has to be achieved from the Pages navigation pane.

Power FX Commanding - Edit Command Bar

This will pop up a dialog where we have to select what command bar we would like to customize. There are four available options to select which include the Main grid, Main form, Subgrid view and Associated view. The image below shows these options.

Power FX Commanding - Select Command Bar

Let’s go ahead and select Main form. When the Commands page open, we will see a view that contains all of the existing command bar buttons that are available for the table within the Main form. At this point in time (as this is still in preview, and we don’t know the exact timeline of release), modifying the existing buttons is not currently supported, so any customizations that is needed for this, will have to be done using Ribbon Workbench. The image below shows you the Main form Command Bar before we have added any additional buttons.

Power FX Commanding - Select Command Bar

Now let’s go ahead and create a new command. We will create a simple command that is called Calculate Credit Limit which when clicked will multiple the number of employees in the company by 10,000, and will set it to only be visible when the number of employees contains data.

To start creating a new command, we click on the new Command button on the top of the left navigation pane.

Power FX Commanding - New Command Bar button

Once we click on the new command button, we will see that a has been created. We can move the command (using drag and drop) within the Main form to place it in the appropriate location, however this can only be done for new commands, and not the existing ones. Let’s provide the new command some of the properties, such as the Label, Icon to use and the Tooltip text.

Power FX Commanding - Command Bar button properties

Next, we would like to set the functions for the Action that will be performed when the button is clicked as well as the Visibility of the button. On the right Command Pane, the last two options are Action and Visibility. The Action selection has two options: Run formula and Run JavaScript.

If we use the Run JavaScript option we can provide the name of the library and the name of the function to call when the button is clicked. This is more of a legacy type of action which might be used in the future for enabling the legacy buttons. The Run formula allows us to Run Power FX code when the command is clicked.

We can use the Patch function together with the Self.Selected.Item together in order to update the Credit Limit, and then compare the Number of Employees to Blank to control the visibility of the button. I am still working a few glitches as to what is working and what is not when it comes to Power FX for commanding, but the code below is working properly.

On Select:

Set(TotalCredit, Self.Selected.Item.’Number of Employees’ * 10000);

Patch(Accounts, Self.Selected.Item, {‘Credit Limit’: TotalCredit});

Visible:

Self.Selected.Item.’Number of Employees’ <> Blank()

The following Microsoft Docs page provides some samples on using Power Fx for commands in the Model driven apps: https://docs.microsoft.com/en-us/powerapps/maker/model-driven-apps/commanding-use-powerfx

Now, let’s look at the end result after adding the button and publishing the app commands.

Power FX Commanding - Calculate Credit Limit Command Bar in use

I hope that this blog post/article provided you with some insights as to what is coming in the new future.

The post Custom Page and Command Bars in Model-driven Apps appeared first on Aric Levin's Digital Transformation Blog.

]]>
June 2020 Updates to Solution Experience https://aric.isite.dev/powerapps/post/https-www-ariclevin-com-powerapps-post-june-2020-updates-solution-experience/ Sun, 28 Jun 2020 22:22:00 +0000 https://aric.isite.dev/index.php/2020/06/28/june-2020-updates-to-solution-experience/ As I was going through one of my solutions in the last few days, I noticed that there are a few changes that were made to the Solution experience, and wanted to share this with everyone. Usually we see a change appear here and there, but it seems like Microsoft is trying hard to simplify the experience and add the missing pieces that are available in classic and not yet available in the Modern experience.

The post June 2020 Updates to Solution Experience appeared first on Aric Levin's Digital Transformation Blog.

]]>
As I was going through one of my solutions in the last few days, I noticed that there are a few changes that were made to the Solution experience, and wanted to share this with everyone. Usually we see a change appear here and there, but it seems like Microsoft is trying hard to simplify the experience and add the missing pieces that are available in classic and not yet available in the Modern experience.

The first change that I saw, that is not really related to the solution experience, but only the ability to navigate between the different parts of the platform are links to Chatbots where you can create new chatbots or list the chatbots that you have already created for your environments. The image below shows the new links that are available in the Maker Portal.

Power Apps Maker Portal June 2020 Updates - Chatbots

The next part is a few additional to the solution experience. While navigating to a solution and opening a particular entity for example, you will see a few buttons added to the command bar in your maker experience. The new buttons are Add subcomponents, Edit data in Excel, Export data, Export to data lake and AI Builder.

The Export to data lake and AI Builder are already available in the left navigation, so I won’t really discuss these.

Power Apps Maker Portal June 2020 Updates - Entity Command Bar

The Add subcomponents, something that is available in the Classic solution explorer allows the addition of entity components to your entity, without having to go back to the list of components and then adding from there. This was something that has been desired for a while.

The Edit data in Excel will download an Excel file with all the columns in your entity. You will need to connect to the environment by signing in Microsoft PowerApps Office Add-in pane. You will be able to make changes to your data and then publish it so that it writes it back to your entity records.

The Export data will download a zip file containing a csv with the data from your entity. This can be used for later migrating data to other environments, backup or other transformation requirements.

The final change that I saw in the solution experience was in the Forms tab of the entity component. A new button called Form Settings has been added, again to bring closer parity to the experience that we have in our Classic interface.

Power Apps Maker Portal June 2020 Updates - Form Settings

This button allows us to change form settings which include the Form Order, Fallback forms and Security roles. The interface is cleaner and provides drag and drop functionality to set the form order. It seems though that Security roles are not yet available, but hopefully sometime in the near future.

Power Apps Maker Portal June 2020 Updates - Form Settings Popup

I hope that Microsoft continues to sync the classic explorer and the modern explorer so that we will all eventually have to only work with a single interface.

The post June 2020 Updates to Solution Experience appeared first on Aric Levin's Digital Transformation Blog.

]]>
Changing record statuses in UCI and 2020 Wave 1 release https://aric.isite.dev/dynamics/post/change-status-2020-wave-1/ Wed, 13 May 2020 09:00:00 +0000 https://aric.isite.dev/index.php/2020/05/13/changing-record-statuses-in-uci-and-2020-wave-1-release/ When working with model driven apps, we have the ability to navigate through the flow of the record using the Business Process Flow. The BPF is a great way to navigate through the different stages of the record, but what if that is just not enough. What if in order to complete the record I have to go through 10 or maybe more stages.

The post Changing record statuses in UCI and 2020 Wave 1 release appeared first on Aric Levin's Digital Transformation Blog.

]]>
When working with model driven apps, we have the ability to navigate through the flow of the record using the Business Process Flow. The BPF is a great way to navigate through the different stages of the record, but what if that is just not enough. What if in order to complete the record I have to go through 10 or maybe more stages.

In previous work that I did, we implement logic that allowed us to navigate by displaying a popup window on the form (using alert.js), and we called the logic inside an HTML eb resource. A lot of these options are being deprecated and we will be prevented from calling webapi calls using HTML web resources.

With the 2020 Wave 1 Release we can now incorporate the Xrm.Navigation.navigateTo command as well as the Xrm.Utility.lookupObjects to provide us similar functionality.

Our use case will be as follows. When a CDS user works on a record and wants to change the status of the record, they will be able to change the status only to statuses that are available (not to all statuses), and the system will log the history of status changes. There are various ways of implanting this, and I chose in this particular case the one that most fits our business model.

Let’s first start by creating the data elements that we need. We will use three entities, called Statuses, Status Mappings and Status History.

The Status entity will just contain a list of statuses with no particular logic, and will contain a single field called Status name as shown in the image below. I set the Ownership of this entity to Organization.

Dynamics CRM 2020 Wave 1 - Change Status

The Status Mapping entity will contain the mappings of the entity, and the abilities to navigate from one Status to another. This means that I will have the current status and the next status so that I can query this entity. Since I used this for applications, I also have an application type record. This entity can be set to have either type of ownership. If there are no security restrictions, then we can set to be organization owned, and if you need to implement Security or Sharing, you can set this to be User/Team owned. The image below shows the required fields for this entity.

Dynamics CRM 2020 Wave 1 - Status Mapping Entity

The last entity is the Status History. We also have an application entity which we will discuss later, but, that can be any entity that you desire. The Status Mapping entity will contain a history of your statuses as you move from one Status to another. This entity will contain a lookup to the parent entity (in our case Application), and a lookup to the Status entity. The ownership for this entity will be User/Team. The image below will show the basic fields for this entity.

Dynamics CRM 2020 Wave 1 - Status History Entity

In our application entity, we will also create a lookup to the Status entity, so that we can store the current status. This field will be read only so that users cannot make any changes to it directly, but only by going through the Change Status process.

The next thing that we will do is on the parent entity, in our case the Application entity, we will add a ribbon button called Change Status that will call a function in JavaScript to start the execution of this process. The image below shows the Change Status button in our Command bar on the application entity.

Dynamics CRM 2020 Wave 1 - Change Status Command Bar

Using Ribbon Workbench, we create the button, add a Command that will use a Custom Javascript Action passing the Crm Parameter PrimaryControl, which will allow us to get the execution context for the function. We set the Display Rule as a Form State Rule to show everywhere except on Create.

The image below shows the configuration that we set in Ribbon Workbench. Thank your Scott Durow.

Dynamics CRM 2020 Wave 1 - Change Status Ribbon Workbench

Next we will start working on the Change Status Javascript function in the application entity. This function is straight forward, but it took a little bit of trial and error to get the exact results that I was looking for.

Within the function I retrieve the current status and the application type and call the Xrm.Navigation.navigateTo function to pop up a new record window when the button is clicked, passing the application id, application type and current status as parameters.

The code below shows the change status function

 function changeStatus(context)  
 {  
   var entityId = context.data.entity.getId();  
   
   var currentStatus = context.getAttribute("bac_applicationstatusid").getValue();  
   var currentStatusId = currentStatus[0].id;  
   
   var applicationType = context.getAttribute("bac_applicationtypeid").getValue();  
   var applicationTypeId = applicationType[0].id;  
   
   var entityFormOptions = {};  
   entityFormOptions["entityName"] = "bac_statushistory";  
   entityFormOptions["useQuickCreateForm"] = true;  
     
   // Set default values for the Contact form  
   var formParameters = {};  
   formParameters["bac_applicationid"] = entityId;  
   formParameters["bac_applicationidname"] = entityName;  
   formParameters["bac_applicationidtype"] = "bac_application";  
   formParameters["bac_name"] = applicationTypeId + ":" + currentStatusId;  
   
   Xrm.Navigation.navigateTo({  
       pageType: "entityrecord",   
       entityName: "bac_statushistory",  
       data: formParameters  
     },   
     {  
       target: 2, //2 - to open record in modal dialog  
       position: 2, //1 - dialog in center, 2 - side panel  
       width: {  
         value: 30,   
         unit:"%"  
       }  
   }).then(function(result) {  
     var reference = result.savedEntityReference;  
   });  
 }  

Within the Status History form I add three functions, an onLoad function, a statusOnChange function and the setLookupOptions function.

The OnLoad function disables the name and status fields on the form, as these should not be modified by the user directly because we want to limit the available options that the user can select from. It verifies that this is a create form, and then calls the statusOnChange function.

 function onFormLoad(executionContext) {  
   var formContext = executionContext.getFormContext();  
   var formType = formContext.ui.getFormType();  
   
   formContext.getControl("bac_status").setDisabled(true);  
   formContext.getControl("bac_name").setDisabled(true);  
   
   if (formType == 1)  
     statusOnChange(executionContext);  
 }  

The statusOnChange function gets the Application Type and the Status from the parameters that were passed to the form (and temporarily placed in the name attribute control), and uses the Xrm.WebApi.retrieveMultipleRecords function to get all of the available “next” statuses for that type of application and that current status, and puts them in a Statuses array as key/value pair elements.

Once all elements have been added to the Statuses array, the function will call the setLookupOptions function.

 function statusOnChange(executionContext)  
 {  
   var formContext = executionContext.getFormContext();  
   var nameControl = formContext.getControl("bac_name");  
   
   var name = nameControl.getAttribute().getValue();  
   nameControl.getAttribute().setValue("");  
   var inputParams = name.split(":");  
   var currentTypeId = inputParams[0];  
   var currentStatusId = inputParams[1];  
   
   // Call Web Api to get   
   var statuses = [];  
   var filter = "_bac_applicationtypeid_value eq " + currentTypeId + " and _bac_currentstatusid_value eq " + currentStatusId + " or _bac_currentstatusid_value eq null and statecode eq 0";  
   Xrm.WebApi.retrieveMultipleRecords("bac_statusmapping", "?$select=bac_name,_bac_nextstatusid_value&$filter=" + filter).then(  
     function success(result) {  
       for (var i = 0; i < result.entities.length; i++) {  
         var statusId = result.entities[i]["_bac_nextstatusid_value"];  
         var statusName = result.entities[i]["_bac_nextstatusid_value@OData.Community.Display.V1.FormattedValue"];  
         statuses.push({id: statusId,name: statusName});  
       }            
       // perform additional operations on retrieved records  
       setLookupOptions(formContext, statuses);  
     },  
     function (error) {  
       console.log(error.message);  
       // handle error conditions  
     }  
   );  
 }  
   

The setLookupOptions function uses Xrm.Utility.lookupObjects to populate in a Lookup window only the statuses that are available for the user to select. We set the lookup options to not allow multiple selections, disable the most recent items, and filter to show the correct statuses. When the user makes a selection that will be populate on the form (displayed in the panel). The user will then have a choice to enter a comment for that status if required.

 function setLookupOptions (formContext, statuses)  
 {  
   var lookupOptions = {};  
   lookupOptions.allowMultiSelect = false;  
   lookupOptions.disableMru = true;  
   lookupOptions.defaultEntityType = "bac_status";  
   lookupOptions.entityTypes = ["bac_status"];  
   
   var fetchXml = "<filter type='or'>"  
   statuses.forEach(function(status) {  
     fetchXml += "<condition attribute='bac_statusname' operator='eq' value='" + status.name + "' />"  
   });  
   fetchXml += "</filter>";  
   
   lookupOptions.filters = [{  
           filterXml: fetchXml,  
           entityLogicalName: "bac_status"  
      }];  
   
   Xrm.Utility.lookupObjects(lookupOptions)  
   .then(function(result)  
   {  
     if (result != undefined && result.length > 0)  
     {  
       var selectedItem = result[0];  
       formContext.getControl("bac_status").setDisabled(false);  
       formContext.getControl("bac_name").setDisabled(false);  
       
       formContext.getAttribute("bac_status").setValue([{ entityType: selectedItem.entityType, id: selectedItem.id, name: selectedItem.name }]);  
       formContext.getAttribute("bac_name").setValue(selectedItem.name);  
   
       formContext.getControl("bac_status").setDisabled(true);  
       formContext.getControl("bac_name").setDisabled(true);  
   
     }  
   }, function(error)  
   {  
     alert(error.message);  
   });  
 }  

After the function is saved, a Flow is executed on the Create record trigger to update the Status field on the parent application record.

The dynamics image below shows the process of how this looks after all the implementation is complete.

Change Status Demonstration

This particular logic can be customized for any business need when the Business Process Flow is not enough, when you need to implement security on who can make changes of statuses to your records, implement logic for field options and more. This is just the tip of the iceberg on how far this logic can be taken if it makes sense for your organization.

The post Changing record statuses in UCI and 2020 Wave 1 release appeared first on Aric Levin's Digital Transformation Blog.

]]>
Creating Web Resource with a Lookup Control https://aric.isite.dev/dynamics/post/creating-web-resource-with-lookup-control/ Sun, 11 Mar 2018 05:45:00 +0000 https://aric.isite.dev/index.php/2018/03/11/creating-web-resource-with-a-lookup-control/ A few years ago we had some requirements where we needed to pop up an html web resource where users could select a value from a related entity (in a manner similar to a lookup control). We originally developed this as a regular drop down and retrieving the values using Rest messages, but later on decided to change this and have the user click on a "lookup" style control inside the web resource to get this working.

The post Creating Web Resource with a Lookup Control appeared first on Aric Levin's Digital Transformation Blog.

]]>
A few years ago we had some requirements where we needed to pop up an html web resource where users could select a value from a related entity (in a manner similar to a lookup control). We originally developed this as a regular drop down and retrieving the values using Rest messages, but later on decided to change this and have the user click on a “lookup” style control inside the web resource to get this working.

In the recent weeks I saw a few posts in the community of people asking how to do this. In this article I will demostrate the logic of implementing this.

The first thing is we are going to need to create an Entity for the purpose of this solution, and add a button to the entity form to popup the message. We created an entity called Area Type and added a button to the entity called Change Owner using Ribbon Workbench. The button itself will call a JavaScript function that is called changeOwner.

Area Type and Change Owner

The Change Owner function contains the code snippet below which calls the dialog and also processes the changes from the callback of the dialog. I am using the Xrm.Internal.openDialog to open the web resource, and yes “I am aware that this is not supported”, but this is still working in Dynamics 365 v9, and you can feel free to modify the calling of the web resource. Once the button is clicked the popup window will open.

function changeOwner()
{
    var DialogOption = new Xrm.DialogOptions;
    DialogOption.width = 600; DialogOption.height = 550;
    Xrm.Internal.openDialog("/WebResources/xrm_dialog.htm", DialogOption, null, null, changeOwnerCallback);
}

function changeOwnerCallback(returnValue) {
    if (returnValue != null) {
		
		// If need to return multiple values;
	    var returnValues = returnValue.split(':');
        var ownerId = returnValues[0];
        var ownerName = returnValues[1];
		// Perform Actions on return values
		setLookup("ownerid", ownerId, ownerName, "systemuser");
    }
}

Since this was used in a previous project that we had, there is a text box for comments and the lookup control that will need to be popped up.

Web Resource/Dialog Window with Lookup Control

When the user clicks on the lookup icon in the dialog window, an additional Lookup Record window will pop up on top of the original dialog window.

function openOther() {

	var imgButton = $("#crmOtherLookup").attr("src");
	if (imgButton == "/_imgs/btn_off_lookup.png") {


		var objectTypeCode = 8;
		var url = "/_controls/lookup/lookupinfo.aspx?AllowFilterOff=0&DefaultType=8&DefaultViewId=%7bE88CA999-0B16-4AE9-B6A9-9EDC840D42D8%7d&DisableQuickFind=0&DisableViewPicker=1&IsInlineMultiLookup=0&LookupStyle=single&ShowNewButton=0&ShowPropButton=0&browse=false&dType=1&mrsh=false&objecttypes=8";

		var DialogOption = new Xrm.DialogOptions;
		DialogOption.width = 500; DialogOption.height = 400;
		Xrm.Internal.openDialog(url, DialogOption, null, null, openOtherCallback);
	}
	else {
		alert("Please select the radio button to the left of Other in order to select a system user.");
	}
}

function openOtherCallback(returnValue) {
	if (returnValue != null)
	{
		if (returnValue.items.length > 0) {
			var guid = returnValue.items[0].id;
			var name = returnValue.items[0].name;
			$("#crmOtherLookup_ledit").val(name); // text 
			$("#crmOtherLookup_lId").val(guid); // hidden                    
		}
	}
}

Select User

Select the User record that you want, and click the Add button to populate the values from the lookup window (as shown below):

Populated Lookup Control

Finally press the OK button to have the data from the lookup returned to the form, and update the original lookup field that is on the form (not required).

function applyChanges() {
	var returnValue = "";

	var message = $("#crmRoutingMessage").val();
	if (message != '') {

		var otherId = $("#crmOtherLookup_lId").val();
		var otherName = $("#crmOtherLookup_ledit").val();
		returnValue = otherId + ':' + otherName; 

		Mscrm.Utilities.setReturnValue(returnValue);
		closeWindow(true);
	}
	else
	{
		alert('Please enter a Routing Message');
	}
}

Final Result

The full source code and a sample solution (containing the test entity, customizations and all web resource files) is available here on github: https://github.com/ariclevin/WebResourceLookup

The post Creating Web Resource with a Lookup Control appeared first on Aric Levin's Digital Transformation Blog.

]]>
Global Cloning functionality for Dynamics 365 https://aric.isite.dev/dynamics/post/global-cloning-for-dynamics-365/ Thu, 15 Feb 2018 05:28:00 +0000 https://aric.isite.dev/index.php/2018/02/15/global-cloning-functionality-for-dynamics-365/ Recently I had a requirement to provide cloning capabilities for one of the projects that I was working on. It wasn't so simple as to just clone an individual record, but also provide the ability to clone the relationships.

The post Global Cloning functionality for Dynamics 365 appeared first on Aric Levin's Digital Transformation Blog.

]]>
Recently I had a requirement to provide cloning capabilities for one of the projects that I was working on. It wasn’t so simple as to just clone an individual record, but also provide the ability to clone the relationships.

This is where it becomes tricky, as some entities cannot be easily cloned due to some of the restrictions, so we wanted to provide this solution the ability to restrict certain actions from happening. For example, the address1_addressid and address2_addressid fields in the Account and Contact entities cannot be cloned as they point to the Customer Address record, so the Guid there has to be unique.

So for the first scenario, we needed to provide the system with the ability to restrict certain fields from being cloned, by providing a status of Active or Inactive, the cloning solution will decide whether or not to clone the record. The screenshot below shows the Clone Settings entity, with the list of attributes that are available for cloning. Notice the highlighted row is marked as Inactive., which means it will not be cloned.

Clone Settings Entity

Next we had to deal with relationships. One of the issue with relationships is that there are probably many relationships that you do not want to be cloned. In the related entities, we provided 3 statuses: Duplicate, Reassociate or Inactive. The Inactive option skips the cloning procedure for the relationship. The Duplicate will make a duplicate of the record Related entity record and the Reassociate will reassociate the related lookup from the source record to the cloned record.

Clone Relationships

We modifies the application ribbon so that the Clone button will appear on every entity (based on a webapi call to check if the entity is enabled for cloning in the Clone Settings), and added a global script library for this purpose on for calling the Clone action. The end result is as follows.

Original and Cloned records

This solution works for our purpose, but I would consider it a Beta Release for anyone who is interested in source code. It’s available on github, so you can make whatever changes that you want. I will add instructions on how to use sometime soon.

The post Global Cloning functionality for Dynamics 365 appeared first on Aric Levin's Digital Transformation Blog.

]]>
Disable Delete icon on subgrid https://aric.isite.dev/dynamics/post/disable-delete-icon-on-subgrid/ Mon, 05 Feb 2018 04:36:00 +0000 https://aric.isite.dev/index.php/2018/02/05/disable-delete-icon-on-subgrid/ We recently had a requirement that users wanted to hide the Delete icon on the subgrid to prevent users from deleting records. Of course it is possible to remove the Delete privilege on the entity in Security Roles, but the requirement was different. When the status of the parent record was Active, the Delete operation should be allowed, however when the parent record was Inactive, the Delete operation should not be allowed.

The post Disable Delete icon on subgrid appeared first on Aric Levin's Digital Transformation Blog.

]]>
We recently had a requirement that users wanted to hide the Delete icon on the subgrid to prevent users from deleting records. Of course it is possible to remove the Delete privilege on the entity in Security Roles, but the requirement was different. When the status of the parent record was Active, the Delete operation should be allowed, however when the parent record was Inactive, the Delete operation should not be allowed.

The first thing that of course we are aware of, is that if a record is inactive, the subgrid Delete functionality is still available, as shown in the image below.

Normal Subgrid Delete button visible on Inactive parent record

We then went ahead and hid the button.

Hide Delete button

This caused the expected result that the Delete button no longer showed up on the subgrid, but of course it did not show up for both enabled or disabled parent records.

Delete button does not show up.

Finally we came up with a resolution, the did not hide the delete button, but allowed us to prevent the Delete action for the disabled records. We went ahead and unhid the Delete button, and then selected the Customize Command option. This populated the Mscrm.DeleteSelectedRecord command under the Command in Ribbon Workbench. We added another Enable rule called RestrictDeleteFromSubgrid, as shown below:

Restrict Delete from Subgrid Command

The result of this action is that the Delete button will still be enabled on the subgrid (and associated grid), but when the Delete button is pressed, if the parent record is Inactive, a message will pop up displaying the you cannot delete a record if the parent record is Inactive.

Delete button clicked on Inactive record

The code on the RestrictDeleteFromSubgrid JavaScript method is very simple. It checks the status of the form and returns true or false whether the record can be deleted.

function RestrictDeleteFromSubgrid() {
    var formType = Xrm.Page.ui.getFormType();
    if (formType == 3 || formType == 4)
    {
        alert('You cannot remove an Inactive record');
        return false;
    } 
    else 
    {
        return true;
    }
}

The post Disable Delete icon on subgrid appeared first on Aric Levin's Digital Transformation Blog.

]]>