October 18, 2019

PCF Gallery - 5 months after

Today (18 October 2019) I added the 100th to PCF Gallery.

All the controls listed inside PCF Gallery can be downloaded, and the source code is available inside their GitHub repository or in the blog post linked inside the page. The majority of the controls is for Model-driven apps, some of them can be added also to Canvas apps and there are also a couple created specifically just for Canvas apps.

There is no doubt the PowerApps Component Framework is one of the most interesting capabilities landed recently inside the Power Platform world, at least for developers!

When I wrote the post announcing the launch of PCF Gallery, I optimistically wished that soon it would list dozen of controls. After few months, thanks to the contributions from more than 40 authors, PCF Gallery is a beautiful showcase of the possibilities offered by the PowerApps Component Framework.

A big thanks to the whole PCF Community!

July 19, 2019

New SDK released with support for new regions (France, US Gov DoD, China)

A week ago thanks to a question on Dynamics Community Forums (link) and to Daniel Cai that spotted the crm12 inside the url, I became aware that a new region for Dynamics 365/PowerApps (located in France) was introduced, however the SDK was not able to connect to this new region as it was not updated yet.

Yesterday the SDK Team released an update to several NuGet packages (link), from the changelog:
Added support for France and New US Geo's

Microsoft didn't update yet the official documentation page but you can check in the next days if you need the exact Discovery Url (especially for the new US region, for the France one you just need to use crm12)

Meanwhile I was testing the new Plugin Registration Tool, I noticed they also introduced a new region in China, strangely the changelog didn't mention this.

Hope it helps!

June 14, 2019

My first PCF Control

After launching PCF Gallery I finally created my first PCF control: Custom Url Control.

The idea behind this control is to display a custom url using record values as parameters.
In my screenshot I implemented a google search using the phone number, but the possibilities are infinite: you can implement a shipment tracking, a link to your reporting engine, open an sms gateway webpage, just one click away!

The control has several settings: It supports up to 3 fields to fetch their values, the url link, the text and some styling options
I didn't want to force the use of a specific placeholder so they are also customizable.
And now the setup example:
  1. First of all I added an additional Phone field (telephone1) to the form and I attached my control to it
  2. The placeholder is the string used inside Url Link and Url Text to replace the value from the Source Field
  3. As I want to display the name inside the Url Link I bounded Source Field 2 to Name (name) field and I used the default placeholder __VALUE2__
  4. For this example I didn't need a third parameter so I left Source Field 3 empty
  5. Inside the Url Link I inserted https://www.google.com/search?q=__VALUE__ in this way __VALUE__ will be replaced with telephone1 value
  6. Inside the Url Text I inserted Search __VALUE2__ Phone Number, in this way __VALUE2__ will be replaced with name value
  7. Url CSS has a default value, to make the links looks similar to Dynamics UI
  8. Inside Font Awesome Icon I inserted the classes required to show a Font Awesome Icon (version 5), I set the search icon, if for example you wanted the UPS one, you need to insert fab fa-ups
  9. Font Awesome Icon Style is to set the style property of the icon, in my case I wanted to change the color
I hope you like this control and find it useful.

May 20, 2019

PCF Gallery website launched!

If you are Dynamics 365 Developer (or I should say Power Platform Developer) you are probably aware of the trending topic of the last weeks: PCF.

What is PCF? PCF stands for PowerApps Component Framework, a new way to create custom controls for model-driven apps (more info at Microsoft Docs).

PowerApps Component Framework (also called in the past CCF Custom Control Framework) is an interesting concept to enhance the UX of our apps, it has been in private preview for a very long time and currently is in public preview.
Despite its preview state, many developers started to create controls and to avoid dispersion I decided to create a website to collect the amazing controls created by the Power Platform community, this website is PCF Gallery (https://pcf.gallery).

I created the site the other day so it's a bit empty right now, but I am sure soon it will list dozen of controls. If you created a control or you found a control and want it to be listed please contact me (by Twitter or email).
PCF Gallery has also an Ideas forum (thanks Nick Doelman for the suggestion) where people can submit their idea for new controls, hopefully developers can use them to build new controls for the community.
What are you waiting for? Click on the logo to get started!

March 28, 2019

Update user’s calendar in Field Service schedule board

Configuring the work hours for a user is straightforward from the Dynamics 365 UI, a couple of clicks and you are done. However in the last years we saw an increase of Field Service projects, hence the necessity to automatize the creation and the update of user's works hours.
C# code to update the calendar entity has been around from CRM 2011, like this one:
Sample code to update user’s calendar programmatically (work hours) in CRM 2011

The code linked above works perfectly when you see the work hours inside the user calendar, however they don't appear inside the Field Service schedule board. How can we make sure the work hours appear everywhere?

Nearly 50 lines of code to create a work hour entry are (at least to me) a bit excessive, but this is the way Dynamics work. I tried to simplify the code by renaming the variables and adding the code necessary for the work hours to appear inside the schedule board.
// we start with the user Id
Guid userId = Guid.Empty; // instead of Guid.Empty here we should have the real user Id

// we retrieve the calendarid from the user entity
Entity user = service.Retrieve("systemuser", userId, new ColumnSet("calendarid"));
Guid userCalendarId = user.GetAttributeValue("calendarid").Id;

// we retrieve the calendar record in order to get the Business Unit and the Calendar Rules
Entity userCalendar = service.Retrieve("calendar", userCalendarId , new ColumnSet("businessunitid"));
Guid calendarBusinessUnitRef = userCalendar.GetAttributeValue("businessunitid");
EntityCollection calendarRules = userCalendar.GetAttributeValue("calendarrules");

// we create a new calendar record (inner)
Entity innerCalendar = new Entity("calendar");
innerCalendar["businessunitid"] = calendarBusinessUnitRef;

// Field Service Schedule Board: we must define the type as Inner Calendar
// https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/types-calendars
innerCalendar["type"] = new OptionSetValue(-1);

Guid innerCalendarId = service.Create(innerCalendar);

// we create a calendar rule for the whole day we want to edit
Entity dayRule = new Entity("calendarrule");
dayRule["duration"] = 1440; // 24 hours in minutes
dayRule["effort"] = 1.0;
dayRule["extentcode"] = 1;
dayRule["pattern"] = "FREQ=DAILY;COUNT=1";
dayRule["rank"] = 0;
dayRule["timezonecode"] = 110; // 110 is (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
// GetAllTimeZonesWithDisplayNameRequest can be used to retrieve all the timezones with their code
dayRule["starttime"] = new DateTime(2019, 3, 28, 0, 0, 0, DateTimeKind.Utc);
dayRule["innercalendarid"] = new EntityReference("calendar", innerCalendarId);

// Field Service Schedule Board: we must also define the calendarid reference to the user calendar
dayRule["calendarid"] = new EntityReference("calendar", userCalendarId);

// we attach it to the Calendar Rules of the user
calendarRules.Entities.Add(dayRule);

// we update the user calendar to refresh the calendar rules collection
Entity updateUserCalendar = new Entity("calendar", userCalendarId);
updateUserCalendar["calendarrules"] = calendarRules;
service.Update(updateUserCalendar);

// we define the calendar rule containing our work hour 
Entity exactCalendarRule = new Entity("calendarrule");
exactCalendarRule["duration"] = 120; // 2 hours in minutes
exactCalendarRule["effort"] = 1.0;
exactCalendarRule["issimple"] = true;
exactCalendarRule["offset"] = 480; // 8 hours in minutes from start time (12:00)
exactCalendarRule["rank"] = 0;
exactCalendarRule["subcode"] = 1;
exactCalendarRule["timecode"] = 0;
exactCalendarRule["timezonecode"] = 110; // same timezone as the day rule
exactCalendarRule["calendarid"] = new EntityReference("calendar", innerCalendarId);

// we add the calendar rule to a collection
EntityCollection innerCalendarRules = new EntityCollection();
innerCalendarRules.EntityName = "calendarrule";
innerCalendarRules.Entities.Add(exactCalendarRule);

// we update the inner calendar with the new calendar rules 
innerCalendar["calendarrules"] = innerCalendarRules;
innerCalendar["calendarid"] = innerCalendarId;
service.Update(innerCalendar);

In the end to changes were necessary to make the work hour visible inside the Field Service schedule board:
  1. We must define the type for the Inner Calendar
  2. We must reference the user calendar inside the calendar rule the the whole day
I didn't discover this by myself but with the help of Microsoft support, hope it helps.

January 14, 2019

getText API behavior changed

Some days ago I was upgrading some JavaScript files to v9 and I noticed one of the scripts was not working correctly.
The specific code was using the getText function in order to retrieve the label of an optionset field. The getText function used to return an empty string in Dynamics instances prior to CRM 2016, but in recent versions it returns null. If you need to handle the label in your code (like showing some alerts) the check should be like this one:
function checkOptionsetLabel(context, fieldName) {
    var selectedLabel = context.getAttribute(fieldName).getText();
    if (selectedLabel != null) {
        // ...
    }
}
Also the official documentation has been updated to highlight the return value. Hope it helps!