Advertisements

Archive

Archive for the ‘Dynamics Portals’ Category

‘Address Suggestions’ in Portals using Esri ArcGIS

September 15, 2019 Leave a comment

In our Dynamics Portals, we got a requirement to show ‘Address Suggestions’ as and when the end user start typing the address.

We implemented the solution by consuming the Esri ArcGIS mapping service, from our Portal’s web page.

ESRI_1

‘Entity Form’ with Address Suggestions

In this article lets see how to implement this at a high level.

What is ESRI ArcGIS?

  • Its a cloud based mapping and analytics platform.

ESRI_3

  • For our ‘Address Suggestions’ requirement, we have consumed ESRI ArcGIS’s World Geocoding Service
  • World Geocoding Service:
    • Its part of ESRI ArcGIS.
    • This Service finds addresses and places in all supported countries from a single endpoint.
    • The service can find point locations of addresses, business names, and so on.

Steps to fetch ‘Address Suggestions’:

  • To fetch the ‘Address Suggestions’, we have used findAddressCandidates operation of ‘World Geocoding Service’.
  • findAddressCandidates operation is REST based and takes ‘Input address’ as parameter.
  • As an example, to fetch the ‘Microsoft Office’ addresses in ‘Redmond’ the REST URL would be as follows:

https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?SingleLine=Microsoft+Redmond&sourceCountry=USA&category=&outFields=*&forStorage=false&f=pjson

ESRI_2

  • In the above URL,
    • ‘findAddressCandidates’ –  Operation name.
    • ‘SingleLine’ – Parameter which you need to pass address you are looking for (i.e., Microsoft+Redmond). Use + symbol to combine the words.
    • ‘sourceCountry’ – Optional parameter. if provide, results will be specific to provided country code.
  • Below is the sample script to call the service from Portal Web Page/Entity Form/ Web Templates.

function GetAddressrecommendations(address) {
var url = https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?SingleLine=”+address+”&category=&outFields=*&forStorage=false&f=pjson;
// To limit the address to ‘United States’ country uncomment below line
// url += “&sourceCountry=USA”;

var xhr = createCORSRequest(“GET”, url);
if (!xhr) {
throw new Error(“CORS not supported”);
}
xhr.onload = function () {
var text = xhr.responseText;
// Success and add logic to Parse the Response.
};
xhr.onerror = function () {
alert(“Unable to fetch addresses.”);
};
xhr.send();
}

function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if (“withCredentials” in xhr) {
xhr.open(method, url, true);
} else if (typeof XDomainRequest != “undefined”) {
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}

How to call the method?

  • Call the GetAddressrecommendations function by passing the address you are looking for
    • GetAddressrecommendations(‘Microsoft+Redmond’)

Notes:

  • Esri ArcGis platform provides both hosted GIS services and a portal with a web UI and APIs for publishing, sharing, and managing content, maps, applications, and users.
  • It has both Free and Paid services. Read the documentation before making the decision.

🙂

Advertisements

Dynamics/ADX Portals – Create Notes using SDK

As part of an integration requirement, we had to create ‘Notes’ (i.e., Annotation) with attachment using SDK.

Key Notes:

  • ‘Subject’ and ‘Notetext’ field values of Portal Notes follows a specific pattern than that of Dynamics.  Values must be set as follows:
    • SubjectNote created on {DateTime.Now.ToString()} by {Portal User Name} [contact:{PortalUserGUID}]
      • If the Portal user name is ‘Rajeev P’ and Portal user GUID(i.e.,Contact record’s GUID) is ‘2510ae27-7289-e911-a958-001dd800d97c’, Subject will be Note created on {DateTime.Now.ToString()} by Rajeev P [contact:2510ae27-7289-e911-a958-001dd800d97c]
    • Notetext*WEB*
  • If you don’t pass Portal User’s GUID in ‘Subject’ field, Portal shows the Notes record created by as User whom the Portal was configured.

Code to create Annotation:

Below is the code snippet

var noteSubject = “Note created on {DateTime.Now.ToString()} by Rajeev P [contact:2510ae27-7289-e911-a958-001dd800d97c]“;

var entAnnotation = new Entity(“annotation”);
entAnnotation[“subject“] = noteSubject;
entAnnotation[“notetext“] = “*WEB*”;
entAnnotation[“filename”] = {File_name}; // Set FileName
entAnnotation[“documentbody”] = {Base64String}; // Pass document body in Base64 format
entAnnotation[“isdocument”] = true;
entAnnotation.Attributes[“objectid”] = new EntityReference({RegardingSchemaName}, {RegardingGuid}); // Set Schema and GUID
entAnnotation.Attributes[“objecttypecode”] = {RegardingSchemaName}; // Set Schema

var noteId = crmService.Create(entAnnotation);

  • Note : Replace values in {} with actual values.

🙂

 

 

Dynamics Portals – Web Templates – ‘$ is not defined’ Error

Other day, I was getting ‘$ is not defined’ script error during my ‘Web Template’ load.

Portal_$_1

From the error, its clear that jQuery file reference was missing in Web Template.

The Web Template has a HTML with Liquid Template and script using jQuery and was rendering with no issues an hour ago and there were no changes made to the Web Template content.

Reason and Fix:

  • ‘Use Website Header and Footer’ field was unchecked in ‘Page Template’ which was causing the issue.

Portal_$_2

  • jQuery file would be implicitly available to the ‘Web Template’ when ‘Use Website Header and Footer’ field is checked on ‘Page Template’.
  • Save the Page Template
  • Clear the portal Cache and issue should be fixed.

🙂

 

 

 

PowerApps Portal – Intro

June 14, 2019 1 comment

Those who are familiar with ADX Portals which later acquired by Microsoft and came up with ‘Dynamics Portals’ SaaS offering, ‘PowerApps’ Portal is the next evolution.

  • With PowerApps Portals, Microsoft merging the capabilities offered by Dynamics 365 Customer Engagement portals in to PowerApps Portals.
  • PowerApps Portals provides the ability to build low-code, responsive websites which allow external users to interact with the data stored in the Common Data Service (CDS).
  • PowerApps Portals will seamlessly integrate with Microsoft services like Power BI embed, Microsoft Flow, Microsoft SharePoint, Azure Blob Storage, Azure AD B2C, and Azure Application Insights to enhance your portal with rich content and provide a personalized experience to your customers.
  • All the components of Dynamics CE portals (i.e., Entity Forms, Web Templates, Web Forms,etc…) will be continued to available in PowerApps Portals.
  • PowerApps portal uses the same ‘Liquid Template’ scripting conventions of Dynamics CE Portals.

How to get started?

  • General availability of PowerApps Portal will from July 2019.
  • A new App type called “Portal” will be available directly from PowerApps.

PowerApps Portal

  • You can subscribe here to be informed about the Public Preview availability.

Whats the upgrade path for existing Dynamics 365 CE Portals?

  • All the existing Dynamics 365 CE portals will auto upgrade to PowerApps portals in coming months.

🙂

 

 

 

 

Dynamics Portals – Using ‘Emojis’ in Entity Form and Entity List

In this article, lets see how to use Emoji’s to capture the data in Portal’s Forms.

Emoji1

It’s very simple to achieve. All you need to do is to set the Dynamics ‘Option Set’ field’s ‘Label’ with ‘Emoji’.

Below is the ‘HOW’ part.

Create an ‘Option Set’ field with ‘Emojis’:

  • In Dynamics, create a new ‘Option Set’ Field with 2 options
  • In the Option’s ‘Label’ paste the Emoji.

Emoji2

  • Place this ‘Option Set’ field on the Dynamics Form and View which are being referred in your portal’s ‘Entity Form’ and ‘Entity List’.

Make ‘Options’ to render side by side in Portal:

  • By default, ‘Option Set’ renders as ‘Drop down’ control in Portal.
  • To show the ‘Options’ as Side by Side, add a new ‘Metadata’ to ‘Entity Form’.

Emoji7

Test the Emojis in Portal:

  • Navigate to Portal and open the ‘Employees’ view. Option Set value would renders as ‘Emoji’

Emoji5

  • Open the record and you should get ‘Emojis’ rendered side by side.

Emoji1

Note:

  • You can ‘Copy’ the Emoji from here . Search the Emoji as per your requirement and click ‘Copy’.

Emoji3

  • The rendering of Emojis will be same in ‘Dynamics Web Application’.

Emoji8

🙂 

 

 

 

[Code Snippet] Dynamics Portals/ADX – Set ‘Field Requirement’ using script

Below is the code snippet to set the requirement level (i.e., Required/Non-Required) of a field using script in portals. This logic handles all kind of field types including Check boxes.

Set Field As Required:

function SetFieldAsRequired(fieldName) {
if (typeof (Page_Validators) == ‘undefined’) return;
if ($(“#” + fieldName) != undefined && $(“#” + fieldName + “_label”) != undefined) {
$(“#” + fieldName).prop(‘required’, true);
$(“#” + fieldName).closest(“.control”).prev().addClass(“required”);

// Create new validator object
var Requiredvalidator = document.createElement(‘span’);
Requiredvalidator.style.display = “none”;
Requiredvalidator.id = fieldName + “Validator”;
Requiredvalidator.controltovalidate = fieldName;
Requiredvalidator.errormessage = “<a href=’#” + fieldName + “_label’>” + $(“#” + fieldName + “_label”).html() + ” is a required field.</a>”;
Requiredvalidator.initialvalue = “”;
Requiredvalidator.evaluationfunction = function () {
var fieldControl = $(“#” + fieldName);
if (fieldControl.is(“span”)) {
var value0 = $(“#” + fieldName + “_0”).prop(“checked”);
var value1 = $(“#” + fieldName + “_1”).prop(“checked”);
if (value0 == false && value1 == false) {
return false;
} else {
return true;
}
}
else {
var value = $(“#” + fieldName).val();
if (value == null || value == “”) {
return false;
} else {
return true;
}
}
};

// Add the new validator to the page validators array
Page_Validators.push(Requiredvalidator);
}
}

Set Field As Non Required:

function SetFieldAsNonRequired(fieldName) {
if (typeof (Page_Validators) == ‘undefined’) return;
if ($(“#” + fieldName) != undefined) {
$(“#” + fieldName).closest(“.control”).prev().removeClass(“required”);
$(“#” + fieldName).prop(‘required’, false);

for (i = 0; i < Page_Validators.length; i++) {
if (Page_Validators[i].id == fieldName + “Validator”) {
// Remove the current field’s ‘Required’ validator from ‘Page_Validators’ array
Page_Validators.splice(i);
}
}
}
}

How to use the functions:

  • Above functions can be called from ‘Custom JavaScript’ tab of Portal’s ‘Entity Form’.
  • Pass the Dynamics field’s schema name as the parameter to both functions.
    • In below example, ’emailaddress1′ is the field name which I want to set the Requirement level.

ADXJ_1

Refer the article for Portal script syntax’s and usage.

🙂

 

Dynamics Portals – Customize OOB ‘Entity List’ grid

I was working on a Portal requirement where I had to customize the ‘Entity List’ grid by adding ‘Check Box’ control in the first column and a ‘Submit’ button, which has the custom logic.

Below is how the OOB ‘Entity List’ grid looks like

ADX-G_7

OOB ‘Entity List’ grid

Now, lets see how to customize the OOB ‘Entity List’ grid by adding additional controls (i.e., Check box and Button).

Below are the list of portal components in the order, to achieve this requirement.

  • Create a new ‘Entity List’

ADX-G_2

  • Create a new ‘Web Template’
    • In the ‘Source’, we will have logic to loop through the ‘Entity List’ records (i.e.,Rows) and add ‘Check Box’ control in the 1st column.
    • In the below image, {% entitylist id:page.adx_entitylist.id %} refers the ‘Entity List’ loaded on the current page.

ADX-G_4

  • Create a new ‘Page Template’ and map the newly created ‘Web Template’

ADX-G_6

  • Create a “Web Page’ and map the ‘Entity List’ and ‘Page Template’

ADX-G_5

  • That’s it. Go to Portal, clear cache and hit the ‘Web Page’ URL. You should see grid with ‘Check Box’ as first column.
ADX-G_1

Customized Grid

Web Template’s ‘Source’ :

<body>

 

{% entitylist id:page.adx_entitylist.id %}
{% entityview id:params.view, search:params.search, order:params.order, page:params.page, pagesize:params.pagesize, metafilter:params.mf %}
<table id=”tblContacts” class=”table table-striped”>
<thead>
<tr class=”row”>
<th class=”col-sm-1″>
&nbsp;
</th>
{% for c in entityview.columns -%}
<th width=”{{ c.width }}” data-logicalname=”{{ c.logical_name }}”>
{{ c.name }}
</th>
{% endfor -%}
<th width=”1″></th>
</tr>
</thead>
<tbody>
{% assign i = 0 %}
{% for e in entityview.records %}
<tr class=”row”>
<td class=”col-sm-1″>
<input type=”checkbox” id=”chk{{i}}” onclick=”” />
</td>
{% for c in entityview.columns %}
{% assign attr = e[c.logical_name] %}
{% assign attr_type = c.attribute_type | downcase %}
<td data-logicalname=”{{ c.logical_name }}”>
{% if attr.is_entity_reference %}
{{ attr.name }}
{% elsif attr_type == ‘datetime’ %}
{% if attr %}
<time datetime=”{{ attr | date_to_iso8601 }}”>
{{ attr }}
</time>
{% endif %}
{% elsif attr_type == ‘picklist’ %}
{{ attr.label }}
{% else %}
{{ attr }}
{% endif %}
</td>
{% endfor %}
<tr>
{% assign i = i | plus:1 %}
{% endfor %}
</tbody>
</table>
{% endentityview %}
{% endentitylist %}
</div>
</div>

</div>
</body>

🙂