Quantcast
Channel: USD – Configuration – Microsoft Dynamics 365 and Unified Service Desk
Viewing all 109 articles
Browse latest View live

USD – Multi Entity Search

$
0
0

This morning I made a quick change to my USD interface to include a multi entity search capability, here is how I did it.

I already had a search menu that looked like this ….

So I could search for Accounts, contacts and leads already. Plus, I had added an advanced find search for when all else fails! Selecting any of these options already opened a search tab and when I click on a contact, lead or account a session opens.

Tip: You can see how I created the advanced find search here.

But I wanted more! So I added a multi entity search option. As shown below ….

Selecting my new option would open the search tab but this time navigate to the CRM multi entity search option.

Note: As I had already created hosted controls, actions and window navigation rules needed to open accounts, contacts or leads from my search tab all of that continued to work without any change! If you haven’t already got these, you will need to create them!

Tip:
In my interface I will create sessions if account, contact or lead is clicked. But if anyone selected another entity this will open within the search tab. For me this worked fine! As I already had browser style navigation on my search tab. So the operator is allowed to view records other than contact, lead and account. And afterwards will press the back or home buttons to return to the initial search.

The steps involved were as follows;

  1. Create a webresource for my menu icon.
  2. Create an action.
  3. Create a toolbar button.

Step One – Create a webresource for my menu icon.

I wanted an icon in my toolbar menu so I found an icon I liked. (I got mine from the CRM 2016 SDK, you may find one you prefer elsewhere!)

Next I simply created it as a webresource in the customizations area of CRM. Calling it “new_SearchWidgetViews_16”

Step Two – Create an Action

Next I needed an action to load the multi entity search in my search tab. My action is shown below;

Field Description
Name Search – Navigate (MultiEntity)
Hosted Control Search
Action Navigate
Data url=/multientityquickfind/multientityquickfind.aspx?sitemappath=Settings%7cSystem_Setting%7cnav_administration&text=

This url was used to display the multi entity search in my search tab.

Step Three – Create a toolbar button.

Finally, I needed to create a toolbar button that would use my new webresource and action. I simply added a new button to my already existing search toolbar. The button looked like this.

Field Description
Name Search – Multi Entity Search
Image New_SearchWidgetView_16
Button Text Multi Entity Search
Order 50
Tooltip Search across multiple entities in CRM
Show Tab Search
ACTIONS Having saved the toolbar button I added the action I had created earlier.

Hopefully you will see that this is a really simply change that you can adapt for your own purposes. Enjoy. J


Filed under: USD - Configuration Tagged: crm2016, Microsoft Dynamics CRM, Unified Service Desk, USD

USD – Interactive Service Hub URLs

$
0
0

Recently it became possible to access the Interactive Service Hub using a new hosted control type in Unified Service Desk (USD) for Microsoft Dynamics CRM 2016 (Update 1). (Interactive Service Hub Page)

I have been asked a few questions about this. Specifically, what URLs should can included in navigate actions to access dashboards, views and entities. In this post I will address this question and hopefully provide some useful information to anyone planning on integrating USD with the Interactive Service Hub.

Load Dashboard

I have already published a post about displaying dashboards within the Interactive Service hub, in that I described how to construct that url. Below you can see an example navigate event which would load a dashboard within the Interactive Service Hub.

For the knowledge base dashboard use …..

url=&pagetype=interactioncentricdashboard&id=a104b835-9f3b-e511-80d1-00155db10d2b

For the tier one dashboard user ….

url=&pagetype=interactioncentricdashboard&id=D201A642-6283-4F1D-81B7-DA4B1685E698

if you see my previous post I describe how to work out the id for any dashboard, including custom dashboards.

Tip: You can address Interactive Service Hub pages using URLs outside of USD. For that you will need to prefix your url with <<YOUR SERVER>>/nga/engagementhub.aspx?org=<<YOUR ORGANISATON>>

Display Views for Accounts, Cases etc

You might want to have a search option that displays the list view for accounts etc. You have two options for this! The simplest approach is to use a find action as shown below. Simply select a hosted control that has a component type of “Interactive Service Hub Page” and use the find action. Then in the data field enter the schema name of the entity you wish to display in a view. So account, incident etc.

Alternatively you could use a navigate action with the url looking like the one below. You simply set “etn” to the entity you would like to display the list view for.

url=&pagetype=view&etn=incident&cmdbar=false

Associated Views

It is also possible to show associated views. The url for this is slightly more complicated! Some examples are shown below. Notice that these examples do insert the ID of the parent record using a replacement parameter.

To navigate to associated cases for an incident

url=userdefined/areas.aspx?formid=8448b78f-8f42-454e-8e2a-f8196b0419af&inlineEdit=1&navItemName=Cases&oId=[[incident.Id]u]&oType=112&pagemode=iframe&rof=true&security=852023&tabSet=areaService&theme=Outlook15White&cmdbar=false

To navigate to associated Cases for a contact

url=userdefined/areas.aspx?formid=8448b78f-8f42-454e-8e2a-f8196b0419af&inlineEdit=1&navItemName=Cases&oId=[[contact.Id]u]&oType=1&pagemode=iframe&rof=true&security=852023&tabSet=areaService&theme=Outlook15White&cmdbar=false

To navigate to associated Contacts for an account

url=/userdefined/areas.aspx?formid=8448b78f-8f42-454e-8e2a-f8196b0419af&inlineEdit=1&navItemName=Contacts&oId=[[account.Id]u]&oType=1&pagemode=iframe&rof=true&security=852023&tabSet=areaContacts&theme=Outlook15White&cmdbar=false

If you need other associated views hopefully these examples will serve as a demonstration of how to construct the url.

I hope this post has answered the question I was asked about how to construct URLs within the Interactive Service Hub. If not I am sure someone will ask me more questions and I will update as required.
J


Filed under: USD - Configuration Tagged: crm2016, Microsoft Dynamics CRM, Unified Service Desk

USD – Load associated view (As session starts)

$
0
0

If you read my blog I hope you know that I love answering questions about Unified Service Desk (USD) for Microsoft Dynamics CRM. Today I was asked a great question about how to open an associated view whilst creating a session.

I thought this was a great question as it might be a common requirement to open tabs containing associated views of cases or opportunities as an account loads. (Or any associated view for that matter.) Commonly I see these views being opened in tabs when users click on toolbar buttons, why not save that click and open the tab automatically?

The scenarios for my example is this, you open an account from a search screen or maybe from a dashboard. Selecting the account will create a session and open the account tab in the session. But you’d also like to open another tab at the same time containing an associated view of cases.

I am going make an assumption here that you are already able to open an account in a new session. But you need to alter its window navigation to open the associated view.

The steps involved are as follows;

  1. Create a hosted control
  2. Create an action to display associated view.
  3. Create an ExecuteOnDataAvailable action.
  4. Add an action to your window navigation rule.

Step One – Create a hosted control

If you haven’t got one already you will need a hosted control to hold your associated view. Mine looked like this;

Field Description
Name Associated Cases
Display Name Cases
USD Component Type CRM Page
Allow Multiple Pages No
Hosting Type IE Process
Application is Global Unselected.

This field is not selected as I want my associated view to be part of the session.

I have been asked how to show the associated view as a global tab, that is as simple as selecting this option!

Display Group It made sense for me to display the associated view in my left panel. So I selected “LeftPanelFill”.

You could alternatively use MainPanel or even FloatingPanel.

Step Two – Create an action to display associated view

Again, if you haven’t got one already you will need an action to display the associated view. In my example I have gone with cases for an account. Hopefully you can see how to adapt this action for other entities. (Such as opportunities from a contact etc.) My action looked like this;

Field Description
Name Associated Cases – Asscociated View (From Account)
Hosted Control Associated Cases

The hosted control we created in step one!

Action AssociatedView
Data navItemName=incident

Id=[[account.Id]]

tabset=incident_customer_accounts

type=1

Step Three – Create an ExecuteOnDataAvailable action.

Next you will need an ExecuteOnDataAvailable action! Why???? The reason is that as the navigation rule runs to create your session the account details might not yet have loaded into the replacement parameters. And if you try to run your action to view the associated actions before that has happened it will fail.

I got round that issue with an ExecuteOnDataAvailable action that will pause processing until the required replacement parameter is available.

My ExecuteOnDataAvailable action look like this;

Field Description
Name CRM Global Manager – ExecuteOnDataAvailable (Account.Id)
Order 50 (As I wanted this action to run last when I create my session! You might be abel to leave this blank!)
Hosted Control CRM Global Manager
Action ExecuteOnDataAvailable

TIP: If this action doesn’t exist simply create a new uii action on your CRM Global Manager!

Data [[Account.Id]]

As this is the replacement parameter I wanted to wait for before continuing.

Having saved my ExecuteOnDataAvailable action I added my action to display the associated view as a sub action. As shown below.

You access the sub actions from the navigation ribbon the ExecuteOnDataAvailable action. All we are doing here is saying which action(s) to run when the data is available.

Step Four – Add an action to your window navigation rule.

Finally, we need to edit our window navigation rule that creates the session. My existing navigation rule looked like the one below. It is simply opening a session when the account is selected.

If you need help on how to create a session I have blogged on this before here.

What I needed to do next was alter the actions that run when my session starts. As shown below I simply added the action I previously created.

Now when I open an account an extra tab shows in my left panel. Clicking on that panel will show the cases associated to the account.

Hopefully this post will have been useful if you want to open associated views as sessions are created. J


Filed under: USD - Configuration Tagged: crm2016, Microsoft Dynamics CRM, Unified Service Desk

USD – Phone Call From Toolbar

$
0
0

On several occasions I have been asked how to create an inbound phone call activity directly from a toolbar button in Unified Service Desk (USD) for Microsoft Dynamics CRM, in this post I will address this question.

Firstly, let me say, this isn’t my personal preference on how to start a session in USD! I much prefer to search for the contact / account first and then start a session in the context of the selected record. It has always seemed logical (to me) to first find the person or company calling and start from that point. But I agree there are cases when you want to open the phone call and start recording details before you have established who you are talking to. Meaning that in some circumstances it might be logical to start the session in context of a “blank” phone call.

In this example I will show how to create a toolbar button, that when clicked will open a session containing a partially completed inbound phone call record.

I am going to assume you already understand the basics of how to create hosted controls, actions and start sessions in USD. But I will try to still explain the detail as I progress.

The steps involved are;

  1. Create hosted control. (Phonecall)
  2. Create Session Lines.
  3. Create a “CreateEntity” action.
  4. Create a UII Action on your toolbar.
  5. Create an action to open phone call.
  6. Create a tool bar button.
  7. Create a window navigation rule.

Step One – Create hosted control. (Phonecall)

As with most things USD related, I am going to start by creating a hosted control. This time I simply need a hosted control that will be my phone call tab. Mine looked like this;

The most important details are as follows;

Field Description
Name Phonecall
Display Name Phone call([[phonecall.subject]])

I decided to show the subject of the phone call as my tab name. You could, of course, name the tab differently.

USD Component Type CRM Page
Allow Multiple Pages No
Hosting Type IE Process

I always use IE Process!

Application is Global Not selected as this is going to be a session tab.
Display Group MainPanel

Step Two – Create Session Lines.

Depending on your requirement you may need to create a session overview and session name in the session lines section of USD.

In this example I will keep things simple and just create a session name, this will define the tab name for my session.

Creating a session name is pretty simple, I just navigated to Session Lines in USD and created a new one. In my simple example I just set the type to “Session Name” and “Display” was set to the same approach I’d taken with the hosted control name. (Phone call([[phonecall.subject]])

Step Three – Create a “CreateEntity” action.

Next I created an action to create my phone call. Later I would open it, this action simply creates the phone call in the CRM database. Now normally when we create a phone call I would want to populate all of the mandatory fields but in this case I will leave the “from” field blank. The user will need to enter the details of the contact or account later.

Field Description
Name CRM Global Manager – Create Entity (Inbound Phone call)
Order 10

This is important! The order will make sense in a second. But I have selected 10 as this will be the first of two actions I want to execute.

Hosted Control CRM Global Manager
Action CreateEntity
Data LogicalName=phonecall
directioncode=Boolean(false)

subject=Inbound Phonecall to [[$User.fullname]]

to=PartyList(er[“systemuser”,[[$User.systemuserid]+g]])

To explain ….

LogicalName is the schema name of the entity I want to create.

directioncode is a Boolean value on phone call. Which needs to be false for an inbound phone call. (You could set to “true” if you wanted to create an outbound call in this manner.)

subject, this is the subject of the phone call. Notice I have added the name of the agent to the subject.

to, the phone call is obviously “to” the current user. But the “to” field is a party list and therefor has some special logic to set it.

Step Four – Create a UII Action on your toolbar.

Next I needed to create a new action. Let me explain why …. We will need to fire an action to open the phone call created by the action we defined in the previous step. This will be done by using an Open_CRM_Page action. Normally we would run these from the CRM Global Manager. However, in my example I wanted to explicitly know when the phone call had been opened from the toolbar button. (As only then would I want to create a session.)

To create the new UII Action, open your toolbar container hosted control and navigate to the UII actions. (Note: I am assuming you already have a main toolbar!)

Assuming you don’t already have an “Open_CRM_Page” action, click “ADD NEW UII ACTION” and simply add one called “Open_CRM_Page”. Mine is shown below.

Step Five – Create an action to open phone call.

Next we will want to create an action call that will use our new Open_CRM_Page UII action. My action looked like this;

Field Description
Name Toolbar Container – Open CRM Page (Inbound Phone call)
Order 20

This is important! The order will make sense in a second. But I have selected 20 as this will be the second of two actions I want to execute.

Hosted Control Toolbar Container
Action Open_CRM_Page
Data LogicalName=phonecall
id=[[$Return.CRM Global Manager – Create Entity (Inbound Phone call)]]

To explain ….

LogicalName is the schema name of the entity I want to open.

id is the GUD of the record you want to open. In our case we want to open the return created with the pervious CrateEntity action. For which, the GUID is returned to us in a replacement parameter which has the same name as the action that created the record.

Step Six – Create a toolbar button.

Now we have most of the components we need, so a toolbar button can be created to create and open the phone call. I already had a main toolbar so I simply added a new button. Mine is shown below. (I am assuming you understand the basics of toolbars.)

Field Description
Name Phone call Toolbar Button

You could call your anything!

Image msdyusd_Phone16

This is a standard phone icon image.

Button Text I only wanted an icon, so I left this blank.
Order 50

I picked 50 as I wanted it to be my last button and I already had several. Yopu could use a different order to position your button as required.

Tooltop Create Inbound Phone Call
Showtab Phonecall

As I want the phone call to have focus when it is opened.

Actions Having saved my toolbar button, I added the two actions I had just created. The first creates the phone call and the second opens it.

Hopefully the order now makes sense!

Step Seven – Create a window navigation rule.

One final step is needed. You will need a window navigation rule to tell USD to create a session if a phone call is opened directly from the toolbar button you just created. My rule looked like this;

Field Description
Name Phonecall from Toolbar
Order 1

Note: 1 worked for me! Keep in mind that all of your navigation rules will be evaluated in order. You may need to tweak the order.

From Toolbar Container

As I added the Open_CRM_Page action to my toolbar container the “from” here is that. This is important as this rule will not be triggered if I created a phone call from anywhere else in my USD solution. (In mine, for example, I can also create a phone call from an agent script.)

Entity phonecall

This is the schema name of the entity being loaded. “phonecall” probably already exists but if not you will need to create it.

Route Type The Open_CRM_Page action will trigger a popup, so our route type needs to be “Popup”.
Destination Tab
Action Create Session
Target Tab Phonecall
Show Tab Phonecall
Hide Navigation Bar I set mine to “Yes” as I like to restrict sue navigation. You could use yes or no!

In my USD interface you can see that I now have a phone call icon, clicking this will create a phone call record and open it in a session. As I said at the start this wouldn’t be my preference on how to start a session but sometime it is an approach that might be needed. If you do this in a production environment you might want to think about how the users will interact with the form and how you force them to enter a “from” field etc. (Maybe some validation on your SessionCloseRequested event.)

Hopefully this post has given you some insight in how to create some USD functionality that is commonly requested. J


Filed under: USD - Configuration Tagged: crm2016, Microsoft Dynamics CRM, Unified Service Desk, USD

USD – Email Attachment Question

$
0
0

Hopefully anyone who reads my blog will know I love answering questions about Unified Service Desk (USD) for Microsoft Dynamics CRM. (At least when I know the answers!)

One recent question was how to correctly display windows when adding attachments to emails.

The problem was that having opened an email in a hosted control (tab). Clicking “+” on the attachments sub grid would open the dialog to add an attachment to an email. In the same way as would happen if “just” running CRM in the browser. But when this is done in USD the dialog to add the attachment replaces the currently viewed email and from that point on the navigation is “broken”. You can see below that I have loaded an email in a contact session. And saved the email.

Clicking “+” on attachments opens the attachment in the same tab as my email. Overwriting the email being viewed. Not ideal.

Now in my application I happen to have a back button in my navigation toolbar. So I could use that to get back to the email. But you might not have (or want) this type of navigation. Also it isn’t intuitive for an end user to navigate like this.

The answer (as the person asking the question had correctly realised) would be the addition of a window navigation rule to open the attachment dialog in a separate tab / pop-up. But the navigation rule wasn’t quite as straight forward as you might expect. Here is the rule I created ……

Field Description
Name Attachment from Email

You can call it anything!

Order 1

“1” worked for me but the required order will depend on how your window navigation rules are sequenced. Remember that navigation rules are evaluated in order!

From Email

The hosted control containing my email is called “Email”!

Entity In this case blank.
Url /activities/attachment/edit.aspx

This is the relative url for the dialog for email attachments. The actual full url will also include the server / organisation of your CRM server, plus the GUID of the associated email. (But luckily you don’t need to add those variables to your navigation rule.)

Route Type Popup

As the dialog is going to popup!

Destination Tab
Action Show Outside

I had a couple of options here! One we to create a hosted control then use a route window action. With the target tab and destination tab set to that hosted control.

But I found a simpler approach was to use a “Show Outside” action. Leaving the target and show tab fields blank. Meaning I didn’t need an additional hosted control.

You need to understand what “Show Outside” implies! Show outside loads the tab outside of USD, which means it will exactly emulate the normal IE behaviour. Which was exactly what I wanted. But it will also mean that the dialog opened is outside of any further USD control. This was fine in my application but you may need to be mindful of this in yours!

If I repeat my initial test again, you will see that the attachments dialog now opens in a style which is much more intuitive to the user.

Hopefully this answer has been useful. J


Filed under: USD - Configuration Tagged: crm2016, Microsoft Dynamics CRM, Unified Service Desk, USD

USD – Webpage in a Session

$
0
0

I love answer questions about Unified Service Desk!

The question I was asked today was how to load an external web page from a toolbar button. That is fairly simple and typically done with a global tab. But the twist here was to start a session containing that page.

Here is the answer;

  1. Create a hosted control.
  2. Create an action. (To show webpage)
  3. Create an action. (To Start a Session)
  4. Create a toolbar and toolbar button.
  5. Create a session name.

In my example I created a button called “LOAD PAGE”, this started a session and loaded a webpage into that session. If I am honest, I think I would have done this as a global tab and not made the web page part of a session. But the person asking the question specifically asked about loading a web page into a new session from a toolbar.

Plus, in the end this turned into an interesting example! As I am creating a session WITHOUT using a window navigation rule. Using a CreateSession action. A first for me!

Step One – Create a hosted control.

As with most things USD related I start by creating a hosted control, as I will need a tab to hold a web page. Mine looked like this;

Field Description
Name EXAMPLE WEB PAGE

You could call yours anything!

Display Name TAB NAME!

This is the name that will show above the tab.

USD Component Type Standard Web Application
Hosting Type IE Process

I always use IE Process and so should you!

Application is Global NOT selected.
Display Group MainPanel

Step Two – Create an action. (To show webpage)

The action to show a web page is pretty simple. I just used a navigate action.

Field Description
Name WEB PAGE – Navigate
Order 20

You will see why I 20 in a minute!

Hosted Control The one we just created, “EXAMPLE WEB PAGE”
Action Navigate

What is interesting here is that I am using a navigate action! Interesting as navigate actions do not trigger the window navigation rules, so I needed a non-standard way to start my session.

Data url=http://bbc.co.uk

This could be any webpage you want to display.

Step Three – Create an action. Create an action. (To Start a Session)

Next I needed an action to start my session as I wasn’t going to use a window navigation rule.

Field Description
Name CRM Global Manager – Create Session
Order 10

You will see why 10 in a minute!

Hosted Control CRM Global Manager

You will have a global manager, although it could have a slightly different name!

Action CreateSession
Data Blank

Step Four- Create a toolbar and toolbar button.

Next I added a toolbar button to my main toolbar. And added the two actions I had created. Mine ended up looking like this ….

Hopefully the order now makes sense! As I needed that create session action to have a lower number than the navigate action.

Obviously this is just an example, in a production version you would name the button in a better way!

Step Five – Create a session name.

The final step is to give my session a name. This again was slight non-standard! Typically sessions are started from a CRM entity. Here no entity was involved.

In the session lines section of USD settings I created a session line that looked like this;

Field Description
Order 1
Name DEFAULT SESSION NAME

Could be called anything really!

Selected Entity Blank

This isn’t normal. What is going to happen is whatever session name we pick will be used whenever a session has no entity.

Type Session Name
Display SESSION NAME!

The name I wanted to display in my application.

Hopefully this has been an interesting example and answered the question I was posed. I have found this fun to do as I’d not used a CreateSession action before. Thanks.
J


Filed under: USD - Configuration Tagged: crm2016, Microsoft Dynamics CRM, Unified Service Desk, USD

USD – Prevent Close Window Dialog

$
0
0

I have been repeatedly asked a question about Unified Service Desk (USD) for Microsoft Dynamics CRM, how do we stop the often annoying “webpage you are viewing is trying to close the window” dialog?

In this post I will show you a couple of approaches I have used to solve this problem.

By way of an example I will use a phone call. You can see below that I have started a session containing an inbound phone call. Out of the box if the user clicks “Mark Complete” they will see the annoying dialog.

Below you can see that Internet Explorer has detected that the window is trying to close and this has created an unwanted prompt in Unified Service Desk. You may think seeing this isn’t much of a problem but think again. USD is aimed at contact centre operators, someone in that environment could easily take or make 300 phone calls per day. After clicking “Yes” a few hundred times you may find the operators will start to form a dislike of the developer who provided that feature. J

I have two possible approaches to solving this problem. This first is to simply allow the window to close but to prevent the popup.

The second is allow the phone call to be marked as complete but to leave the tab open. (I will explain this option and why you might want to do this in a second.)

  • Option One – Prevent Dialog
  • Option Two – Prevent Dialog (Keeping tab open)

Option One – Prevent the Dialog.

The steps for option one include ….

  1. Create a RunScript Action.
  2. Add the action to BrowserDocumentComplete Event.

Step One – Create a RunScript Action.

You can use a RunScript action to substitute the normal close window function with one that will close the tab “nicely” in USD. The function will need to look like this;

function closeWindow(focus) {
  window.open("http://close/");
}

My action call for phone call looked like the one below;

Step Two – Add the action to BrowserDocumentComplete Event.

I then simply added this to the “BrowserDocumentComplete” event of my phone call hosted control. As shown below.

Now when you run USD clicking Mark Complete on the phone call will simply complete the phone call and close the tab. Without the annoying dialog.

Option Two – Prevent the Dialog (Keeping tab open).

I have demonstrated how to prevent the dialog, so we are done. Right? Yes and no ….. as sometimes you may need a slightly different approach.

If I start a session for a contact, then phone a phone call in a second tab allowing the user to close that tab is perfectly acceptable. But if I start the session with the phone call as the first tab if the user closes that tab they are left with a session open that contains nothing. And we have another annoyance for the user.

In this circumstance you will want the user to be able to click “MARK COMPLETE” but the tab remain open. Leaving the tab open is easy but the screen won’t have refreshed. Meaning the now completed (read-only) phone call will still appear to be editable. Here is how I solved that challenge ….. the steps involved are;

  1. Create a RunScript Action.
  2. Add RunScript to BrowserDocumentComplete Event.
  3. Create a Refresh Action.
  4. Create an ExecuteOnTimeout Action.
  5. Add ExecuteOnTimeout Action to Saved Event.

Step One – Create a RunScript Action.

Firstly I created a RunScript action as before. But this time the function actually did nothing. Meaning the close didn’t happen.

function closeWindow(focus) {
  // ** THERE IS NOTHING IN HERE!
}

Step Two – Add RunScript to BrowserDocumentComplete Event.

And I added this action call to the BrowserDocumentComplete event on phone call as before.

Step Three – Create a Refresh Action.

Next I need to refresh the phone call tab after it is saved, so I created an action to refresh the phone call page if it had been completed. This is simple enough the hosted control was “Phonecall” and the action was “Refresh”. Notice I also added a condition to the action of “[[phonecall.statecode]]”==Completed
I did this as I only wanted the phone call tab to be refreshed if the phone call had actually been marked as completed.

Step Four – Create an ExecuteOnTimeout Action.

Next I needed to consider when / how to trigger this action. The problem is you can simply add it to the “Saved” event on phone call. But just doing that can trigger yet another different annoying dialog!

To avoid this dialog, we need to ensure the phone call save has completed before we refresh the page. To achieve that I created another action. The timeout action looked like the one below. My hosted control this time was my global manager and the action was “ExecuteOnTimeout”. In the data field I entered “milliseconds=500”, this was going to add a ½ second delay. Now I didn’t want this delay randomly for no reason so I also added the same condition as before. “[[phonecall.statecode]]”==Completed

Having saved my ExecuteOnTimeout action I added the refresh action as a sub action. You will find the sub action calls option in the navigation bar of your “ExecuteOnTimeout” action.

My sub actions eventually looked like this;

Step Five – Add ExecuteOnTimeout Action to Saved Event.

One final step remained to add the ExecuteOnTimeout action to the “Saved” event on phone call. Meaning after a phone call was saved as completed after a ½ second pause the phone call tab will be refreshed. The operator will then be looking at the completed read-only phone call as required. Simples!

I hope you can see this is actually quite a simple thing to achieve.
J


Filed under: USD - Configuration Tagged: CRM, crm2016, Microsoft Dynamics CRM, Unified Service Desk, USD

USD – Show Outside (URL)

$
0
0

I do like to answer questions on Unified Service Desk (USD) for Microsoft Dynamics CRM.

I recently had someone request I create a blog post on how to show a url outside of USD. (Looks like I am taking requests now!! J)

To demonstrate how to show a URL in an Internet Explorer window outside of Unified Service Desk I will explain who to create a useful help feature.

The steps involved are;

  1. Create a popup action.
  2. Add the action to a toolbar button.
  3. Create a window navigation rule.

Step One – Create a popup action

My action is shown below…

Field Description
Name I called mine “CRM Global Manager – Popup (Help)”. You could call yours anything you like.
Order I didn’t need to set an order as my toolbar was only going to call this one action.
Hosted Control CRM Global Manager

I used CRM Global Manager as it would allow me to trigger the popup but not being related to a visible tab nothing would be seen within my USD interface.

Action Popup

It is important that you select a “Popup” action and NOT a navigate action.

Data url=https://neilparkhurst.com/2016/06/20/usd-the-book/

Here I just list the “url” I want to load. In my example I wanted to offer a help on USD button so I simply directed people to my blog. (I didn’t say this was a serious example you should copy!)

Step Two – Add the action to a toolbar button

Next I needed to create a toolbar button and add my action. I opted to show a help feature in my existing about toolbar.

Below you can see I have added a “Help” option to the about toolbar.

My help button is shown below. Notice that I have given the button an image and that importantly I have not entered anything in the show tab field. Once I had saved my button I simply added that action we created in step one. So simple stuff.

Step Three – Create a window navigation rule

If there is a clever bit to this example, then this is it.

What I am trying to achieve in this example is to load a web page in Internet Explorer but NOT to use a USD tab. As I want the page to load outside of USD. Loading “things” outside of USD is often a useful trick but you should keep in mind that once outside USD can have no further interactions with whatever was loaded.

My navigation rule looked like this;

Field Description
Name I called mine “Help – Show Outside” You could call yours anything you like.
Order All navigation rules must have an order as they are evaluated in sequence. In my example “1” worked fine.
From I could have said “CRM Global Manager” as that is the hosted control that popup is coming from. But I left blank to show that in this example that wasn’t essential and this field is optional. Although recommended.
Url neilparkhurst.com

I could have entered the entire url here and sometimes you will. I wanted however to demonstrate that you can enter a partial relative url. This navigation rule will actually load any page from my blog triggered from any hosted control outside of USD. (This is why you might want to specify a from field and a more detail url!)

Route Type Popup

We fired a popup action so it stands to reason that the route type will be popup.

Destination Tab
Action Show Outside

This action will tell USD to load the tab outside of USD.

Target tab and show tab Both blank as we aren’t using a tab. We are not showing the url in a tab we are loading it in IE outside of USD.

Finally, I tested my simple change. You can see that I have a “?” icon in my about toolbar and that clicking this will load a page from my blog. Proving the IE window has loaded outside of USD is simple. If you close USD the IE window will remain. If the page you have opened closes when USD closes you have done something wrong as it isn’t outside.

Hopefully this very simple example has answered the question I was asked. Plus I have also shown that I take requests!!!
J


Filed under: USD - Configuration Tagged: crm2016, Microsoft Dynamics CRM, Unified Service Desk, USD

USD – Save and Restore a Session

$
0
0

Recently I was asked a question about Unified Service Desk for Microsoft Dynamics 365, the requirement was to be able to save a session. Meaning saving details of all the open tabs, so that someone else could re-open it later.

This could be very useful in several scenarios;

  • Say you have opened an account, case, phone call (etc etc.) but you need to park it. It could be lunchtime and you want to save it and pick up your work again after lunch.
  • Or maybe you want to transfer the current “job” over to a more experienced operator or manager. (Possibly whilst the customer is still on the phone!)

WARNING: This is a complicated USD change. My aim is to explain a design pattern that someone who has advanced USD knowledge could adapt / alter. Therefore, in this post I’m going to assume the reader fully understands USD concepts. This might not be a change you can simply lift and use! E.g. You will probably need to tweak the window navigation rules for your purposes.

Before looking at how I created this change, you may wish to view this video which shows this feature in action;

Steps Involved

Part One : Save the Session

  1. Create a hosted control
  2. Create a custom entity
  3. Create a Scriptlet (Challenge One)
  4. Create more some Scriptlets! (Challenge Two)
  5. Create a “CreateEntity” action to populate the custom entity
  6. Create a “CloseSession” action
  7. Create a toolbar, I put mine in the CTI Panel

Part Two : re-open the session

  1. Create a view of Saved Sessions
  2. Open “Saved Session” custom entity
  3. Create a bunch of actions
  4. Add actions to BrowserDocumentComplete
  5. Create some Window Navigation Rules

Step One – Create a Hosted Control

All good USD changes should start with creating a hosted control! J

Firstly, I created a hosted control called “SavedSession”, this will be used later when I’m re-opening a saved sessions.

Field Details
Name SavedSession
USD Component Type CRM Page
Hosting Type IE Process (I only ever use IE Process!)
Application is Global Must be selected.

Note: I am going to “spawn” a session from this tab opening. It is global but it will trigger sessions to open.

Display Group Hidden

The user does not need to see this! But a tip, whilst testing you might want to use MainPanel and only hide the tab when you know your change is performing correctly.

Step Two – Create a Custom Entity

Next I created a custom entity in CRM. This will be used to hold the details of all the tabs you’ll need to re-open. My USD application is actually quite a complicated one! So, I needed multiple fields on this entity. You may find you need far fewer fields!

I called my entity “Saved Session”. Notice that the ownership is “User or Team”. This is important as I will want to know who created each saved session. Later I might also want to consider security role restrictions, such as maybe only the person who owns the saved session or their manager can open it.

Note:
In my demo environment, I didn’t worry about security roles. In a production environment you will need to add this new entity into the roles used by all USD users.

Notice that I didn’t select any of the communication & collaboration options. I don’t need notes, activities etc. So, I didn’t select them!

In my solution, I have quite complex navigation. I use all activity types and most of the system entities available in CRM Dynamics 365. Plus I have multiple standard web pages that could be displayed.

This entity was essentially a list of text fields. All of the ones used for URLs had a type of url. But Initial Entity and Agent Script were just standard text fields.

A “key” field here is “Initial URL”. In this field, I will hold the url of the first tab opened in the session. Important as that will drive the context of the session when we re-open it.

Next I created a field for each of the tabs / entities that could be opened in a USD session. For readability, I grouped them under headings of Entity Tabs, Associated Views, Activities etc.

Finally, I added a section for all of the urls that related to web pages outside of USD. In my application, these included maps, results for Google searches, LinkedIn pages etc. In yours you may also have line of business applications or pages on your local intranet etc.

Obviously, my entity ended up having loads of fields! This entity might look complicated but it is actually really simple as it’s just a load of text fields.

Step Three – Create a Scriptlet (Challenge One)

Whilst creating this solution I hit a couple of challenges that were solved with scriptlets.

My first challenge was that the context does not always contain the url of the initial entity. And I needed to ensure this was captured to be able to open the session correctly.

My “SavedSessionURL_INITIAL” scriptlet simply returns the url of the initial entity. Most of the time this will be “[[$Context.url]+]” but as that replacement parameter isn’t available on activities I added in some if conditions to get those details from other parameters. (Such as “[[task.url]+]” etc.

My code looked like this ….

function SavedSessionURL_INITIAL() {
    // ** To explain ...
    // ** Generally speaking, the context will contain the url of the initially loaded record.
   // ** So most of the time we just need "$Context.url"
   // **   BUT I found that this field doesn't work with activities.
   // **   so when the session starts from an activity I grab the url from another replacement parameter.

    var url = "[[$Context.url]+]";
    var logicalName = "[[$Context.LogicalName]+]";

    if (logicalName == "task") {
        url = "[[task.url]+]";
    }

    if(logicalName == "appointment") {
        url = "[[appointment.url]+]";
   }

    if(logicalName == "email"){
       url = "[[email.url]+]";
    }
    if(logicalName == "phonecall") {
        url = "[[phonecall.url]+]";
    }

    return url;
}
SavedSessionURL_INITIAL();

Step Four – Create more some Scriptlets! (Challenge Two)

My next challenge was a problem with the url field on CRM entities. The screen shot below shows the replacement parameters for a newly created case. You can see that the case’s GUID is in the “Id” field. But when you look closely at the URL you can see that this Id has not been included. If we use this URL as it stands a new case form will be displayed instead of the case we just created.

Note: I will explain how / when these scriptlets are called in just a second!

So again, I turned to Scriptlets for a solution! This time I wrote a small piece of JavaScript that would insert the Id if it was missing.

function SavedSessionURL() {
  var url = "[[incident.url]+]";
  var id = "[[incident.Id]+]";
  var urlSplit = url.split("&id=&");

 if (urlSplit != "" && urlSplit != null) {
    url=urlSplit[0] + "&id=" + id + "&" +urlSplit[1];
  }

  return url
}

SavedSessionURL();

I ended up creating a scriptlet like this for each of the CRM entities that should be created in my interface. Meaning case, opportunity, phone call etc. So quite a few scriptlets were needed but each one was almost identical. ( Copy and paste time! J )

Step Five – Create a “CreateEntity” action to populate the custom entity

Now we come to the fun bit. Having created my custom entity and the scriptlets I needed to format the URLs, I now needed an action to insert a record into my custom entity. So a CreateEntity action. My action was from my CRM Global Manager and looked like this;

My data field looked like this, notice that for the initial entity url field I call the scriptlet that I described in step 3. And for each of the CRM entities I call one of the scriptlets we created in step 4.

Also notice that some urls, like the standard web pages towards the end can have their urls simply set without the need of a scriptlet.

Tip:
My publisher has “crm_” as its prefix. In your application “crm_name” (etc) might be “new_name”. This CreateEntity action is simply a list of name/value pairs. The first part being the schema name from my custom entity the second being the value to insert.

LogicalName=crm_savedsession

crm_name= [[$Context.LogicalName]+]  ([[$Context.Id]+])
crm_initialentity=[[$Context.LogicalName]+]
crm_agentscript=[[Agent Scripting.msdyusd_name]+]
crm_initialurl=[[$Scriptlet.SavedSessionURL_INITIAL]]
crm_accounturl=[[$Scriptlet.SavedSessionURL_Account]]
crm_caseurl=[[$Scriptlet.SavedSessionURL_Case]]
crm_contacturl=[[$Scriptlet.SavedSessionURL_Contact]]
crm_leadurl=[[$Scriptlet.SavedSessionURL_Lead]]
crm_opportunityurl=[[$Scriptlet.SavedSessionURL_Opportunity]]
crm_workorderurl=[[$Scriptlet.SavedSessionURL_Workorder]]
crm_appointmenturl=[[$Scriptlet.SavedSessionURL_Appointment]]
crm_emailurl=[[$Scriptlet.SavedSessionURL_Email]]
crm_phonecallurl=[[$Scriptlet.SavedSessionURL_Phonecall]]
crm_taskurl=[[$Scriptlet.SavedSessionURL_Task]]
crm_associatedcaseurl=[[Associated Cases.url]+]
crm_associatedcontacturl=[[Associated Contacts.url]+]
crm_associatedopportunityurl=[[Associated Opportunities.url]+]
crm_associatedworkorderurl=[[Associated Work Orders.url]+]
crm_googlemapurl=[[Google Maps.url]+]
crm_googleurl=[[Google.url]+]
crm_bingurl=[[Bing.url]+]
crm_bingmapurl=[[Bing Maps.url]+]
crm_accountwebsiteurl=[[Account Website.url]+]
crm_linkedinurl=[[LinkedIn.url]+]

Step Six – Create a Close Session Action

Now I created a very simple action to close the session. As once I have saved the session details to my custom entity I would like to force it to close.

As you can see below this is a simple CloseSession action which is applied to my Session Tabs hosted control.

Notice the order of 5. My CreateEntity action had an order of 1. (Meaning I want to fire the CreateEntity action and then the CloseSession action.)

Step Seven – Create a toolbar, I put mine in the CTI Panel

Next you need a toolbar button that will contain a save session button. In my example I decided to show where the CTI Panel typically goes. (As I wasn’t using it!) You could of course add the button to any toolbar.

First I created a hosted control for my toolbar that looked like this. (Notice my display group is “CTiPanel”)

I then created a toolbar, mine is shown below. (Don’t forget to link the toolbar to the hosted control you created above! Using the hosted control option in the navigation of the toolbar.)

Next I created a toolbar button.

I gave my toolbar button an image that I found in the resources of the CRM 2016 SDK.

Notice that I have an enable and visible condition. “[[$Context.LogicalName]+]”!=”” This simply means that my button won’t show if I don’t have a session open.

And then finally I added the CreateEntity action and CloseSession actions we previously created to my button.

Below you can see a screen shot of my USD interface complete with the SAVE SESSION button in the CTiPanel.

Step Eight – Create a view of Saved Sessions

Next I wanted to have a list of the saves sessions. I’d already got a search toolbar and tab. So I decided to re-use that. You may decide to locate elsewhere in your navigation. Below you can see how my Saved Sessions option was shown in my search toolbar.

The button I created looked like this, notice that the button calls an action to “find” my Saved Session custom entity.

My find action was pretty simple. It was just a find action with the schema name of my custom entity in the data field. As shown below.

My view of saved sessions looked like this. Now at this point I will say I don’t like this view! It is functional but from an end user point of view I do not like the way I have shown the GUID of the initial entity in the name. If / when I create a production ready version of this change I will alter my CreateEntity action to set a more user friendly name to the entity.

Step Nine – Open “Saved Session” custom entity

Next I needed to open my custom entity of Saved Session from the list of sessions I’d shown in my search tab. If you recall, in step one we created a hosted control called “SavedSession”. We are going to load custom entity into that tab. Except the tab is hidden so the user will not see this happen!

To load the tab I used a window navigation rule. As shown below.

Field Description
Name Saved Session from Search
Order 1 (You may need a different order!)
From Search

As I had loaded the list of saved sessions into a tab called “Search”.

Entity crm_savedsession

The schema name of my custom entity.

Route type Popup
Action Route Window

I don’t often use a Route Window action on a global tab! What this going to do is open a global tab from the global search tab. BUT the tab is hidden!

Target tab and show tab SavedSession

The name of the hosted control we created in step one. (As hidden I guess I didn’t really need to set the show tab!)

Step Ten – Create a bunch of actions

First of all I created a popup action that will load the initial url. It is important that a popup action is used as I want this action to trigger my window navigation rules which will start my session.

Also, notice that the order is 10. A low number as I want this to be the first action that is run.

Now I created a navigation action for each of the urls that will be loaded from my custom entity. A navigate action as I want these tabs to load within my session.

The actions were simple enough but I had quite a few as I needed one for each url I had held in my custom entity.

Below you can see I have given an example of the action I used for account. Notice that the hosted control is account and the action is “navigate”. Then in the data field I have set the url to the field from my custom entity. So …. url=[[crm.savedsession.crm_accounturl]g]

I also added a condition to each of these navigate actions, as I only want to do them if I have that particular url. “[[crm_savedsession.crm_accounturl]g]”!=”” etc etc.

In my custom entity I had also stored the name of the agent script that is currently active. So I also created a agent scripting GotoTask to load this. For this one the hosted control was Agent Scripting and my action was GotoTask.

Tip:
Notice that the order is high! I want this action to run after all of my navigation actions.

Finally I created an action to close the SavedSession tab. (Which is hidden!) The main thing to notice is that the order is very high. I need this to be the last action that runs.

Step Eleven – Add actions to BrowserDocumentComplete

Next I added all of the actions I’d just created to the BrowserDocumentComplete event of my SavedSession hosted control. The logic here is;

  1. Do a popup, which will start the session.
  2. Do loads of navigate actions for all the possible tabs.
  3. Go to the agent script.
  4. Close the SavedSession hosted control.

Notice that my agent script and close actions had the highest order and therefore came last.

Step Twelve – Create some Window Navigation Rules

In your solution this step could take some thought! Depending on how you have structured you window navigation rules then you may need some to start the sessions as required. In my case I created a navigation rule for each entity that could be an initial entity.

So I had a list like this;

I opted for an order of 300, as that fitted with the structure I have in my rules. As I said at the start my USD interface is pretty complicated so I needed quite a few navigation rules. In yours you may find a much smaller number is required.

Tip: Each navigation rule also has some associated actions to expand the left panel etc. The exact format of yoru rules will differ depending on your applications functionality.

Obviously, this isn’t a simple change! But I hope you can see that it might be a useful addition to your Unified Service Desk interface.
J


Filed under: USD - Configuration Tagged: Microsoft Dynamics 365, Microsoft Dynamics CRM, Unified Service Desk

USD – Enhanced Debugger

$
0
0

With the latest release of Unified Service Desk (USD) for Dynamics 365 we have some cool new features in the debugger in this post I will highlight these new features.

I’m going to assume you’re already familiar with the existing debugger features! Don’t worry if you aren’y, you can find a summary of the existing features here.

Copy Data

The new copy data facility lets us copy information shown in the action calls tab into the clipboard.

Why is this important???? ….. well often I will be in the debugger and see an issue with a particular action. That information will have useful snippets of information contained within it. Such as the GUID of the offending record. Being able to grab this information means I can paste it into Notepad. And then from there I use the information to help me diagnose issues.

You can also select numerous actions and paste into another application. I am finding this really useful when debugger as I can then use that application to search the results. Below you can see that I have pasted a load of actions into Excel.

Note: Pretty much all of the details from the action tab are transferred to the clipboard, which is nice. However, I have noticed that the date created and duration fields do not show in the output.

So how do we achieve this? …. Well it is as simple as you’d expect! Simply view the action calls, select the row (or rows) you want to copy, right click and away you go.

As I am mentioning copy / paste of debugger information. It might be worth pointing out that we can already copy details from the debug output tab. As shown below.

And when viewing data parameters there is a copy function which copies the name of the currently selected data parameter into the clipboard.

Refresh the Unified Service Desk Client

The next new debugger feature allows to quickly refresh the Unified Service Desk Client to use the latest configuration. Why is this cool? Well as a developer I often make minor tweaks to my Unified Service Desk configuration and want to quickly see the impact of those changes. Sometime I actually make the change on the fly from within the debugger.

Doing the refresh is as simple as selecting the new refresh icon on the action calls tab in the debugger.

Tip: If you don’t know you can actually alter and save an action directly in the debugger. I often use the save icon on the direction action tab to create or edit existing actions.

In my testing of this new feature I found a couple of minor glitches. (Hopefully they will be addressed in later releases.) Some of them maybe be specific to my environment. But regardless of these this is still a really useful feature. The debugger is a developer tool, if you want perfection simply close the application and reload from scratch …. which I suggest is a test you’d ultimately need to do anyway! But this is still a useful way to quickly try things out whilst you are “hacking” around looking for solution.

Below I highlight a couple of the glitches I ‘ve found. Firstly, I use the generic CTI application. On the reload of USD I received an error message that it failed to initialize. This didn’t cause me any great issues. As it wasn’t CTI functionality I was trying to retest.

I also use some “SaveSettings” actions, something that might not be very common! The SaveSetting action writes out user options at runtime. The user options don’t seem to get refreshed when USD re-loads from the debugger. Again, a pretty minor issue that didn’t cause me any concern.

Changes in debugger functionality might not immediately sound like a major benefit but as developer (of sorts) I can say these changes will definitely help me. And anything that helps a developer be more productive has got to be a good thing. J


Filed under: USD - Configuration Tagged: Dynamics 365, Microsoft Dynamics CRM, Unified Service Desk

USD – Notifications

$
0
0

USD 2.2 contains a cool new feature to pop-up notification forms, in this blog post I will explain how this new feature works.

First of all, what is a notification and when might you use them? Think of a notification as a pop-up that can be used to alert the agent to “something”. Then clicking buttons on that notification can trigger actions or events within USD. Microsoft give an example of a notification being used to warn the operator of the maximum number of sessions. Maybe you can think of more inventive uses, such as warning the agent that customers support contract has expired and offering an option to renew.

Below you can see that I have given an example of a notification. A few things to notice …..

  1. I have a timer on my notification, if after 60 seconds the agent hasn’t selected a button the notification will close. (Tip:
    This does trigger an event so you could fire actions if the agent does nothing!)
  2. I have a button called “EVENT”, I have used this to show how to trigger an event from the notification.
  3. I have a button called “ACTION”, I have used this to show how I can call an action from the notification.
  4. In the notification, I am showing the maximum number of sessions. I have done this to show how replacement parameters can be included in the notification.

So, let’s have a look at how to achieve this effect. The steps involved are ….

  1. Create a hosted control.
  2. Create a form.
  3. Create an action.
  4. Trigger the action.

Step One – Create a Hosted Control

Firstly, I created a hosted control using the new component type of “Popup Notification”.

Notice that I have mode my notification global. This is optional as notifications can also be part of the session.

It is also possible to have multiple notification. But if you display them all in the same location you’d see the last one displayed as they would overwrite each other.

Whilst I’m talking about the hosted control let’s have a quick look at the default events. You can trigger the Cancel or Ok events from code we’ll see in a second. Also the “TimeOut” event can be automatically triggered if the user does not respond to the notification within a given time period.

I mention these as when you consider how you might make use of the Popup Notification you may want to think about adding multiple actions to one (or several) of these events.

Step Two – Create a Form

If you aren’t familiar with XAML this will be the clever bit! I’m not a hard-core coder. But I’ve managed to work out enough of the code to get this working. So don’t let this step scare you.

In the forms option of USD settings, I created a new form. My form looked like this.

I created the XAML in the markup field by copying some I found and tweaking it.

Tip:
Any code changes are best done in a XAML editor and then pasted into the markup field once completed.

My entire code looked like this, please copy and tweak. J

<Border xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CCA="clr-namespace:Microsoft.Crm.UnifiedServiceDesk.Dynamics;assembly=Microsoft.Crm.UnifiedServiceDesk.Dynamics"
BorderBrush="Blue" BorderThickness="1">
        <Grid Background="AliceBlue" Height="100" Width="400">
<Grid.Resources>
 <CCA:CRMImageConverter x:Key="CRMImageLoader" />
<Style x:Key="ImageLogo" TargetType="{x:Type Image}">
<Setter Property="Width" Value="16" />
<Setter Property="Height" Value="16" />
<!--<Setter Property="Margin" Value="5" /> -->
</Style>
    </Grid.Resources>
            <Grid.RowDefinitions>
                <RowDefinition Height="75"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
            </Grid.ColumnDefinitions>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="50"/>
                    <ColumnDefinition Width="350"/>
                </Grid.ColumnDefinitions>
<Image Style="{DynamicResource ImageLogo}" Source="{Binding Source=msdyusd_Email16, Converter={StaticResource CRMImageLoader}}" Grid.Column="0" />
                <TextBlock TextWrapping="Wrap" Grid.Column="1" Text="The text for the notification will go here. You can insert replacement parameters! Example .... You can have a maximum of [[$Global.maxNumberOfSessions]+] concurrent sessions open."/>
            </Grid>
            <Grid Background="SkyBlue" Grid.Row="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="200"/>
                    <ColumnDefinition Width="100"/>
     <ColumnDefinition Width="100"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0">
                    <Run Text="The notification closes in " />
                    <Run Text="{Binding TimeoutProperty}" />
                    <Run Text=" seconds"/>
                </TextBlock>
              <Button Name="btn1" Height="20" Width="90" Grid.Column="1" Foreground="Black" Command="CCA:ActionCommands.UIIEvent" CommandParameter="Cancel">EVENT</Button>
              <Button Name="btn2" Height="20" Width="90" Grid.Column="2" Foreground="Black" Command="CCA:ActionCommands.DoActionCommand" CommandParameter="http://uii/CRM Global Manager/DisplayMessage?text=An Action!">ACTION</Button>
            </Grid>
        </Grid>
    </Border>  

To help explain the code let’s look at a few specific elements;
Replacement Parameters

Notice how in the text I have inserted a replacement parameter. In my example I have used [[$Global.maxNumberOfSessions]+] but you could use any replacement parameter.

 <TextBlock TextWrapping="Wrap" Grid.Column="1" Text="The text for the notification will go here. You can insert replacement parameters! Example .... You can have a maximum of [[$Global.maxNumberOfSessions]+] concurrent sessions open."/>

The timer

Later in this post I will show how the action that calls the notification can set a timeout value. Then the code below can be used to show the timer in the notification.

<TextBlock Grid.Column="0">
                    <Run Text="The notification closes in " />
                    <Run Text="{Binding TimeoutProperty}" />
                    <Run Text=" seconds"/>
</TextBlock>

The EVENT Button

In my notification, I had a button that called an event. In my example clicking the button will trigger the “Cancel” event on the notification hosted control. (Which will close the notification!)

In the code below I hope you can see that clicking the button will trigger a command. CCA:ActionCommands.UIIEvent This command will trigger whatever event is referenced in the CommandParameter. In my example the “Cancel” event.

  <Button Name="btn1" Height="20" Width="90" Grid.Column="1" Foreground="Black" Command="CCA:ActionCommands.UIIEvent" CommandParameter="Cancel">EVENT</Button>

Tip:
Don’t forget you aren’t limited to the out of the box events. You could create a custom event if required.

The ACTION Button

In the notification, I included an action button. In my simple example this just triggered a DisplayMessage action but you could trigger any action.

In the code below clicking the button will trigger a command. This time CCA:ActionCommands.DoActionCommand. The command parameter then contains the url needed for the action.
In my example the hosted control is CRM Global Manager, the action is “DisplayMessage” and the data field would contain “test=An Action!”

 <Button Name="btn2" Height="20" Width="90" Grid.Column="2" Foreground="Black" Command="CCA:ActionCommands.DoActionCommand" CommandParameter="http://uii/CRM Global Manager/DisplayMessage?text=An Action!">ACTION</Button>

I hope you can see that you might not be a XAML expert but you can probably take this example an adapt for your requirements.

Step Three – Create an Action

Next, we need an action to display the notification. Mine is shown below.

The hosted control is the popup notification control we created in step one. And the action is Show.

Then in the data field I have defined the name of the form to display, its position and length of the timer. So ….

formname = NotificationForm
top =-86
left = 1
timeout = 60

Tip: Other actions that you might want to use on the notification popup include “Hide” and “Close”.

Step Four – Trigger the Action

You could opt to trigger this action (and load the notification) from multiple different points. In my simple example, I’ve done it when a session opens. But you could add this type of action to the BrowserDocumentComplete of a tab or maybe to an agent script answer etc.

See below that I have added the action to my SessionNew event on my CRM Global Manager.

There we have it, a cool new feature to popup notifications and control what happens next by calling actions or events as required. What do I think? I think it is great. The only downside is that creating the form needs knowledge of WPF / XAML. I’m not a coder! But with a little help from a friend I managed to understand enough to get this feature working. So, you should also be fine.
J


Filed under: USD - Configuration Tagged: Dynamics 365, Microsoft Dynamics CRM, Unified Service Desk

USD – Close All Sessions

$
0
0

I recently answered a question someone raised in the Dynamics Community on how to close all the currently open sessions in Unified Service Desk (USD)  with one click. This is a very simple change to implement, this post explains how.

I am going to assume you already understand how to open sessions!

The steps involved are;

  1. Create some actions.
  2. Create a toolbar button.

Step One – Create some actions.

First of all I created 5 actions. Why 5? Well my maxNumberOfSessions option is set to 5. If yours if higher or lower than you’ll need a different number of actions.

Each action looked something like the one shown below. The hosted control is “Session Tabs” and the action is “CloseSession”.

Notice the Order field. I had this set so that each action would happen one after another.

Step Two – Create a Toolbar Button.

Next I created a toolbar button and added the five actions I’d created to that button. My button looked like this;

Some things to note;

  • I called my button “CTI Toolbar – Close”, as I added this to a toolbar I was showing in my CTI Toolbar. You could obviously add yours to you main toolbar if you’d prefer.
  • I uploaded a suitable image as a webresource. Its name was “crm_CloseQuote_16”. I “borrowed” it from the images that come in the Dynamics 365 SDK! (This step is optional.)
  • I added all my actions, you can see that the order field gave them a logical sequence.
  • I added an enable and visible condition. As I only wanted a close sessions button to show when a session was open. My condition was “[[$Context.LogicalName]+]”!=”” (FYI, other conditions might have worked I just opted to look for the presence of an entity name in my context, as I will always have that when a session is open.)

My button finally looked like this ….

I hope you can see this is a dead simple change but one that might be useful.
J


Filed under: USD - Configuration Tagged: Microsoft Dynamics 365, Microsoft Dynamics CRM, Unified Service Desk

USD – PING/PONG (CloseSession)

$
0
0

I recently published a quick post to describe how to close all sessions from a single button click in Unified Service Desk (USD). You can view that post here. In this post I will describe a more elegant approach.

I take no credit for coming up with this idea. A very good friend of mine suggested this approach having read my original post. His name is Naga Srikanth Alluri. Srikanth is married to another friend of mine called Rashi. It was Srikanth who introduced me to USD and Rashi who taught me how to use it. I owe these guys so much. J

But what is this “PING/PONG” thing I hear you ask ….

In my original post, I simply ran one action after another. It was fine if you restricted the maximum number of open sessions to a fixed number but if you didn’t the approach wasn’t elegant. In this revised approach we will use just two actions.

PING/PONG Action Name Hosted Control Action Condition Sub Action
PING Session Tabs – Close Session (PING) Session Tabs CloseSession [[$Session.Count]g]>0 Session Tabs – Close Session (PONG)
PONG Session Tabs – Close Session (PONG) Session Tabs CloseSession [[$Session.Count]g]>0 Session Tabs – Close Session (PING)

I hope you can see that we create a “kind of” loop, with the first action calling the second. And the second calling the first. Meaning the condition is important to break out of the loop.

Steps Involved are ….

  1. Create PING action
  2. Create PONG action
  3. Set sub-actions on PING and PONG
  4. Add an action to a toolbar.

Step One – Create PING Action

Srikanth’s ping action looked like this. So not forget the condition! You will dive into an endless loop if you miss it!!

Step Two – Create PONG Action

This is going to be exactly the same as my ping. Again, don’t forget the condition!

Step Three – Set sub-actions on PING and PONG

Now you need to access the sub actions on these two actions. The PING will have a sub action of the PONG. And the PONG will have a sub-action of PING.

This process simply involves opening the Sub Action Calls option.

And adding in either PING or PONG!

Step Four – Add an Action to a Toolbar

Finally, we need to add the PING action into a toolbar button.

Below you can see my toolbar button.

I’ve given it am image called CloseQuote_16. I found this in the image resources in the Dynamics 365 SDK. You could use another image or leave blank.

Notice my enable and visible conditions. I added this as I only wanted the button to show when I have 2 or more sessions open. [[$Session.Count]g]>1

My button finally looked like this. Notice I have two sessions open which is why the button is showing.

Thanks again Srikanth. This is a great approach to this problem and shows us how we can have a “loop” in USD.
J


Filed under: USD - Configuration Tagged: Microsoft Dynamics 365, Microsoft Dynamics CRM, Unified Service Desk

USD – SetLanguage Action

$
0
0

In Unified Service Desk (USD) we have an action called “SetLanguage” but what does this action do and when might you use it? When someone first pointed this action out  I could only find very limited information. In this post I hope to give a full explanation of the SetLanguage feature.

The Microsoft website does mention the SetLanguage action but no details are given. The reference below suggests an action exists that will allow us to control the language used to spell check notes. (But gives us no insight into how the action works.)

By way of an example I’ve decided to add the ability to choose a language directly on the notes control in my USD application. See below how I’ve added a toolbar to the notes control that allows language selection. (And that the French language is being used, as Homme isn’t a spelling mistake but the English word “woman” is.)

The steps involved with this change are;

  1. Install some languages
  2. Create a UII Action
  3. Creates some Actions
  4. Create a Toolbar
  5. Create some toolbar buttons

FYI: I am going to assume that you already have a notes control working in USD!

Step One – Install Some Languages

Before you start you are going to need to have installed whatever languages you wish to use. Depending on your install of Windows you may need to install several language packs. Mine only had English installed!

My desktop at home is running Windows 10, so I will give you instructions for that. (I guess the process will differ with other versions of Windows.)

You can see above that I’d already implemented English and French, say I wanted to add German. Before making the changes in Unified Service Desk I will need to load a German language pack. To do this I first go to windows settings and select the “Time & Language” option.

Next I select the Region & Language option.

Below you can see I have English and French installed. And that I next select the Add a language option to add another.

You will now see that there are loads of languages to pick from. Bit of a geography lesson for me, there are languages in here I have never even heard of! J

I selected German and then I selected the variant of German I wanted to install. In my case German (Germany).

Having selected the language I required, I used the “Options” button and selected to download the language pack.

Finally, below you can see that the language pack install begins.

Step Two – Create UII Action

By default the action “SetLanguage” may not exist in your Unified Service Desk configuration. It will probably need to be added. This is a simple process, navigate to your notes hosted control and find the UII Actions option.

Then in here simply add a new uii action called “SetLanguage”. Mine is shown below. Basically I just clicked new and gave the action a name. There is no need to change any of the other fields.

Step Three – Create Some Actions

Next I am going to need an action for each of the languages I want to use. My action for German is shown below. Notice that my hosted control is “Notes” and my action is the one we just added. (SetLanguage)

Also in the data field I enter the “language culture name” for my selected language. English(UK) was en-GB, French was fr-FR etc.

Tip : You might not know the “Language Culture Names” for all languages! The link below will provide you a table for all supported languages.

https://msdn.microsoft.com/en-gb/library/ee825488(v=cs.20).aspx

Step Four – Create a Toolbar

Next I wanted to add a toolbar to my notes control, so in the toolbar option in Unified Service Desk settings I added a new toolbar. Mine is shown below.

Don’t forget to link your toolbar to your notes hosted control using the hosted controls option in the toolbar navigation!

Step Five – Add Some Buttons

Firstly I added one button to my newly created toolbar. This just had “LANGUAGE” as its button text. As shown below.

Next I used the Toolbar Buttons in the navigation of my LANGUAGE button to add a button for each of my selected languages.

My German button looked like this …. Notice that I have also added the action we created earlier. So that selectin the button will trigger our SetLanguage action.

My final list of toolbar buttons looked like this.

I hope this post has explained the SetLanguage action in detail. Auf Wiedersehen!
				J

Filed under: USD - Configuration Tagged: Microsoft Dynamics 365, Microsoft Dynamics CRM, Unified Service Desk

USD – Custom Branding

$
0
0

A new feature with Microsoft’s Unified Service Desk 2.2 is the ability for developers to modify the login and splash screen to apply your own name / branding. In this post I will look at this concept, I work for a company called Crimson. So by way of an example I will show how I’ve altered my USD application to have their branding.

As USD loads my splash screen now looks like this …

On my splash screen I’ve changed the application name, font style and background colour. Using three style keys of SplashAppNameStyle, SplashScreenDefaultFontStyle and SplashGridBgColor.

My login screen looks like this …

On the login screen the new feature allowed me to change the application name field. This is one with a style key of FormAppNameStyle.

Note: I would have liked to have made more changes to the login screen, including changing the picture of the two guys who are obviously not call centre workers. I currently don’t know how to change this image. Any suggestions????

Making these changes was a simple enough process. First, I created some XAML. Mine looked like this…

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:resx1="clr-namespace:Microsoft.Crm.UnifiedServiceDesk.Properties">

  <Style x:Key="FormAppNameStyle" TargetType="TextBlock">
    <Setter Property="Foreground" Value="Red"></Setter>
    <Setter Property="FontFamily" Value="Segoe UI"></Setter>
    <Setter Property="FontSize" Value="40"></Setter>
    <Setter Property="Background" Value="White"></Setter>
    <Setter Property="Text" Value="Crimson"></Setter>
  </Style>
   
    <Style x:Key="SplashAppNameStyle" TargetType="Label">
    <Setter Property="Foreground" Value="Red"></Setter>
    <Setter Property="FontFamily" Value="/UnifiedServiceDesk;component/Fonts/#Segoe UI"></Setter>
    <Setter Property="FontSize" Value="40"></Setter>
    <Setter Property="Content" Value="Crimson"></Setter>
  </Style>

  <Style x:Key="SplashScreenDefaultFontStyle" TargetType="TextBlock">
    <Setter Property="FontSize" Value="14px"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="TextWrapping" Value="Wrap"/>
    <Setter Property="TextTrimming" Value="WordEllipsis"/>
    <Setter Property="FontFamily" Value="Calibri"/>
  </Style>

  <Style x:Key="SplashGridBgColor" TargetType="Grid">
    <Setter Property="Background" Value="Gray"></Setter>
  </Style>

</ResourceDictionary>

Next I saved this XAML with the name “CustomerSplashStyles.XAML”.

Once I’d saved my file I copied it into the program directory of USD. Which for me meant copying my XAML file into “C:/Program Files/Microsoft Dynamics CRM USD/USD”.

Finally, I finished my branding off by changing the application name and also adding Crimson’s logo.

I have described how to change the application name before, you can find that post here.

Changing the logo is dead simple. Simply go into customizations in CRM, find the web resource called “msdyusd_Logo” and change the image. In my example I have used an image that was 160 x 35 pixels.

I hope you enjoy re-branding your application.
J


Filed under: USD - Configuration Tagged: Microsoft Dynamics 365, Microsoft Dynamics CRM, Unified Service Desk

USD – Translate and DetectLanguage Actions

$
0
0

Unified Service Desk (USD) for Dynamics 365 has two actions which until now I hadn’t used. Translate and DetectLanguage. What are these and what do they do?

In this post, I will explain these actions and show you a working example.

The Translate action provides on demand translation of text data using Azure Translation Services. Meaning we can translate a data parameter from any language to any language. Additionally, the DetectLanguage parameter provides the capability to determine the language of any block of text.

Below you will find a video that shows how I have used these actions within my USD solution to translate the body of any from English into another language. Or from English into any language.

Before I explain how this functionality was created, let me explain a little detail about these actions. These details will be based on the information you can find on Microsoft’s site, here. But I will add additional snippets of information that I’ve discovered. (With a little help from my friends!)

Translate Action

Enables you to perform language translations using Microsoft Translator.

The Translate and DetectLanguage actions are UII Actions of Global Manager.

Parameter Description
Value This is the text to translate. This value may be escaped for multi-line support.

Some valid examples:

value=$Escaped(“my string<br>new line\\\”my text\\\””)

value=[[myapp.myparam]^]

value=$Escaped([[myapp.myparam]$])

value=$Multiline([[myapp.myparam]$])

You may find it useful to review how replacement parameters work, see details here or here.

fromlanguage Name of the language to translate from.

If this is blank, the system will attempt to detect the language of the specified value to be translated before translating.

For a list of valid language values, see Translator Language Codes.

tolanguage Name of the language to translate to.

For a list of valid language values, see Translator Language Codes.

clientId A client ID obtained from Microsoft Azure for translation services.

If this option is blank that USD will look for an option called Azure_ClientId

For information about registering with Azure, https://datamarket.azure.com/developer/applications/

Note:
You can create a free trial which will work for development purposes. But this has limited functionality. For production use you will require an Azure subscription.

clientSecret A client secret obtained from Microsoft Azure for translation services.

If this option is blank that USD will look for an option called Azure_ClientSecret

For information about registering with Azure, https://datamarket.azure.com/developer/applications/

The translated value is displayed under the $Return replacement parameter.

DetactLanguage Action

Enables you to return the language of a block of text using Microsoft Translator.

Parameter Description
Value This is the text to inspect. This value may be escaped for multi-line support.

Some valid examples:

value=$Escaped(“my string<br>new line\\\”my text\\\””)

value=[[myapp.myparam]^]

value=$Escaped([[myapp.myparam]$])

value=$Multiline([[myapp.myparam]$])

You may find it useful to review how replacement parameters work, see details here or here.

clientId A client ID obtained from Microsoft Azure for translation services.

If this option is blank that USD will look for an option called Azure_ClientId

For information about registering with Azure, https://datamarket.azure.com/developer/applications/

Note:
You can create a free trial which will work for development purposes. But this has limited functionality. For production use you will require an Azure subscription.

clientSecret A client secret obtained from Microsoft Azure for translation services.

If this option is blank that USD will look for an option called Azure_ClientSecret

For information about registering with Azure, https://datamarket.azure.com/developer/applications/

The language value is displayed under the $Return replacement parameter.

Setup

Before you can use these actions some setup will be required.

Firstly, you will need to obtain a client ID and client secret for Microsoft Azure translation services. Using this link …. https://datamarket.azure.com/developer/applications/

Warning:
You can obtain an Azure trial that will “work” for development purposes. But it will have a limitation that you can only complete one translation every 10 minutes. I have been told that this restriction is removed with a fully paid Azure subscription. I haven’t tested that! It would be great if the first person who tries these actions with a paid subscription could comment on this post to confirm this is correct.

Next you will need to make an alteration to one of USDs configuration files. UnifiedServiceDesk.exe.config

You will find this in the program directory of our Unified Service Desk client. Typically, this will be “Program Files/Microsoft Dynamics CRM USD/USD”

To edit this XML configuration file, you may need to copy to your desktop and open using any editor. (NotePad will do!)

You will need to insert a service binding to connect with Microsoft Translation Service. The code for this is below;

    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_LanguageService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                    <security mode="None">
                        <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                        <message clientCredentialType="UserName" algorithmSuite="Default"/>
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://api.microsofttranslator.com/V2/soap.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_LanguageService" contract="MicrosoftTranslationService.LanguageService" name="BasicHttpBinding_LanguageService"/>
        </client>
    </system.serviceModel>

Below you can see that I have added this code into my config file.

Capture.PNG

Example Solution

In the following notes I will describe the steps I took to create the solution shown in my video.

I am going to assume that you can already open a CRM entity in a session and you have some functionality to open an email.

The steps involved are;

  1. Create options
  2. Create Translate action
  3. Create DetectLanguage action
  4. Create “RunXRMCommand” action
  5. Create “Copy To Context” actions
  6. Create a toolbar and add actions

Step One – Create options

You should have a Client ID and Client Secret for the Azure translation service, now you could enter these on each of your Translate or DetectLanguage actions. However, I felt creating them as options was a more elegant approach. So in Unified Service Desk settings I opened the “Options” option and create two new ones.

I’ve shown my options below. You’ll need to create “Azure_ClientId” and “Azure_ClientSecret”. And enter appropriate values.

Step Two – Create Translate action

Next we need an action that will actually do our translation.

Some things to note ….

Field Details
Name CRM Global Manager – Translate (Email Description)
Order 10

This will be significant when we add this action into the toolbar!

Hosted Control CRM Global Manager
Action Translate
Data value=$Escaped([[email.description]$])

fromlanguage=[[$Context.TranslateFromLanguage]]

tolanguage=[[$Context.TranslateToLanguage]]

In particular, notice the approach I have taken to value, I found this method of using $Escaped coped with any formatting I added into the email. Including the formatting used on my email signature.

You will also notice that I have used a couple of values from my context for the from and to languages. We will see how these get set in a second!

Step Three – Create DetectLanguage action

The next action I needed was a DetectLanguage action. In my example I use this when converting an email from any “unknown” language into English. I am essentially automatically detecting the from language.

To be honest I have used this action just for demonstration purposes! As it is valid to omit from fromlanguage value from your Translate action.

Field Details
Name CRM Global Manager – Detect Language
Order 1

This will be significant when we add this action into the toolbar!

Hosted Control CRM Global Manager
Action DetectLanguage
Data value=$Multiline([[email.description]v])

Notice that I have used different syntax for my value field. Again I have simply done this to show a variation on how to set the value to be examined / translated.

Notice that I have no other parameters! I don’t need to set a clientID or clientSecret.

Step Four – Create “RunXrmCommand” action

Next we have a RunXrmCommand! Why?

Well I use this command to take the translated test and update the body of the email. So I am injecting a single line of JavaScript into the email form to set a value.

Field Details
Name Email – RunXrmCommand (Set Email Description)
Order 20

This will be significant when we add this action into the toolbar!

Hosted Control Email

The name of the CRM Page hosted control that holds my email activity.

Action RunXrmCommand

This action simply injects JavaScript into your CRM form at runtime.

Data Xrm.Page.getAttribute(“description”).setValue(“[[$Return.CRM Global Manager – Translate (Email Description)]$]”);

This is a simple Xrm.Page command to set a value. But notice the $Return replacement parameter. This will be taking the results from our translate action and inserting them into the JavaScript.

Pay attention to the “]$]” in my replacement parameter. I found the $ was needed and the translation didn’t correctly apply if missed!

Step Five – Create “Copy To Context” actions

Next I created several actions to copy “from” AND “to” languages into my context. Essentially I always need two values in the context. One if “TranslateFromLanguage” and “TranslateToLanguage”.

Field Details
Name CRM Global Manager – Copy To Context (From English)

And

CRM Global Manager – Copy To Context (To French)

CRM Global Manager – Copy To Context (To German)

CRM Global Manager – Copy To Context (To English)

Order 5

This will be significant when we add this action into the toolbar!

Hosted Control CRM Global Manager
Action CopyToContext
Data TranslateFromLanguage=en

And

TranslateToLanguage=fr

TranslateToLanguage=de

TranslateToLanguage=en

Next I created one final Copy To Context action, this one was for my detected from language.

Field Details
Name CRM Global Manager – Copy To Context (Detected Language)
Order 5

This will be significant when we add this action into the toolbar!

Hosted Control CRM Global Manager
Action CopyToContext
Data TranslateFromLanguage=[[$Return.CRM Global Manager – Detect Language]]

So this time I am copying the results in $Return from my DetectLanguage action.

Step Six – Create a toolbar and add actions

Ok, so now we have all the building blocks for this solution. They come together on a toolbar.

I’d already got a navigation toolbar on my email tab, so I simply added my translate button. My button looked like this.

Field Details
Name Email – Translate
Image I found in image in the Dynamics 365 SDK which I uploaded as the icon on my toolbar. You can find it if you search the SDK for ico_16_4216
Button Text Blank, if you don’t use an image then you could simply set this text field to TRANSLATE
Order 5

In my example this simply made the button the last one.

Tooltip Optional!
Enabled condition and visible condition “[[email.description]]”!=””

This condition will hide the button until the email has been saved, as the email description will not be in the context until the email is saved.

FYI: A refinement to my approach would be to get the contents of the email description using a RunXrmCommand. As then you could skip having to save the email.

Next I used the toolbar buttons option available in the navigation.

My buttons were as follows;

Let’s look at the Email – Translate Other first. The button is simple enough, as shown below.

Now I created two more toolbar buttons. (Again, using the toolbar button in navigation.) One button was for translating into French and one for German.

They were almost identical, so let’s just look at the French one. As you can see below I simply gave the toolbar button a name and then added the actions we created earlier. For this button I added

  • CRM Global Manager – Copy To Context (To French) …. Copies “fr” into the context as the to language.
  • CRM Global Manager – Copy To Context (From English) …. Copies “en” into the context as the from language.
  • CRM Global Manager – Translate (Email Description) …. Translates from “en” to “fr”.
  • Email – RunXrmCommand (Set Email Description) …. Updates the email description with the translated text.

Obviously from German button was about the same except I used the “CRM Global Manager – Copy To Context (To German)” action instead.

Finally, I created my button to translate an email from any language into English. Again it was simple. I just gave it a button text of “To English” and added some actions.

  • CRM Global Manager – Detect Language …. This runs my DetectLanguage action to work out the language.
  • CRM Global Manager – Copy To Context (Detected Language) … now we copy the detected language to the context as my from language.
  • CRM Global Manager – Copy To Context (To English) …. Copies “en” into the context as the to language.
  • CRM Global Manager – Translate (Email Description) …. Translates from “detected language” to “en”.
  • Email – RunXrmCommand (Set Email Description) …. Updates the email description with the translated text.

I hope this post has been useful, I think this is really cook feature. I look forward to hearing how people get on with this and keen to hear from someone who tries this with a paid Azure subscription. (Unlike me!)
J


Filed under: USD - Configuration Tagged: Dynamics 365, Unified Service Desk

USD – Workon / LookupQueteItem Actions

$
0
0

Unified Service Desk (USD) for Dynamics 365 can be used in my many circumstances. One might be answering service requests from your customers, this will commonly involve agents “working” a queue of cases. In this post I will look at a couple of actions that can help in this scenario.

Imagine you are in a service scenario, an agent may select a case from a CRM queue or alternatively may open it directly from a case view. In either scenario, if the case is in a queue we would want to show the current operator as working on that case. So that someone else doesn’t also commence work on the same job. When they complete the case it will be removed from the queue but if they exit the case without resolving it we’d want it to automatically available again in the queue.

There are a couple of USD actions that can help in this situation. WorkOn and LookupQueueItem.

LookupQueueItem allows us to find details of the queue item for the entity opened that has been opened. WorkOn lets us show the current operator as working on that queue item. (We can also use this same action to release the queue item.)

To illustrate how these actions might be used let’s look at an example, first of all a quick video.

The steps involved were ….

I already had the ability to select and open cases from a queue view or simply a case view. Both of these approaches to opening a case were actually from the same hosted control that I’d called “My Work”. To add the queue management functionality I have shown I followed these steps;

  1. Create a LookupQueueItem action.
  2. Create a WorkOn action.
  3. Create a WorkOn action to release the queue item.
  4. Alter my window navigation rule, to how I am working on the case.
  5. Alter my SessionClose event, to release the queue item.

Step One – Create a LookupQueueItem action

The first step was to create an action that would look up the Id of the queue item. In my example I only had cases in my queue but obviously a queue can contain many different types of entity. So I wanted to create an action tha would work with any entity type, assuming I might want to queue other items as some point.

The result of this action is to create replacement parameters for the details of the queue item. You can then use these later. I have shown the results of running this action in the debugger below. In my example I was trying to get the Id of the queue item. So [[queueitem.Id]].

The action I created is shown below;

Field Details
Name CRM Global Manager – LookupQueueItem
Order 10

The order was significant as later I want to ensure this action executes before my WorkOn action.

Hosted Control CRM Global Manager
Action LookupQueueItem
Data Id=[[$Context.Id]]

Type=[[$Context.LogicalName]]

Basically I am setting the pararmeter Id to the Id of the entity I want to locate in the queue. And type to its type. Such as incident, phonecall etc.

I used $Context as then my change was not linked to a specific entity type.

Step Two – Create a WorkOn action

Now I wanted to use the queue item ID to show that I was working on that item. I have given an example of this below.

Field Details
Name CRM Global Manager – WorkOn
Order 20

The order was significant as later I want to ensure this action executes after my LookupQueueItem action

Hosted Control CRM Global Manager
Action WorkOn
Data Id=[[queueitem.Id]]
Condition “[[queueitem.Id]]”!=””

I added this condition as it will be possible for me to open a case that isn’t in a queue. Having this condition will ensure that situation does not cause a problem.

Step Three – Create a WorkOn action to release the queue item

A further action was required to release the queue item, this will happen if I close the session and the queue item has not been resolved.

Field Details
Name CRM Global Manager – WorkOn (Remove)
Order I didn’t care about the order this time!
Hosted Control CRM Global Manager
Action WorkOn
Data Id=[[queueitem.Id]]

Action=Remove

Condition “[[queueitem.Id]]”!=””

I added this condition as it will be possible for me to open a case that isn’t in a queue. Having this condition will ensure that situation does not cause a problem.

Step Four – Alter my window navigation rule, to how I am working on the case.

I already had a window navigation rule that will open cases from a tab I’d created called “My Work”. This same tab could include a view of the queue(s) that I work with or a list of cases.

Tip: I had similar navigation rules for other entity type that could be opened from my queue item view. Meaning I plan to include those later!

I opened my window navigation rule and opened the “Actions” view from the navigation bar. It was then simply a case of adding the actions we created in step one and two. (Notice their order forces a logical sequence!)

Step Five – Alter my SessionClosed event, to release the queue item.

The final part of my jigsaw was to release the queue item if not resolved. It is is resolved the queue item will get removed, so I didn’t need to worry about that. But I did want to release the queue item if the session was closed and the case hadn’t been resolved.

On Global Manager, we have an event that is triggered every time a session is closed. So I simple needed to alter that to release the queue item. You can see below that I have added my WorkOn (Remove) action to the SessionClosed event.

Hopefully you’ll agree this is a simple configuration and one you can hopefully adapt to how queues are used in your environment.
J


Filed under: USD - Configuration Tagged: Dynamics 365, Unified Service Desk

USD – Show Buttons Based on Security Role

$
0
0

I was recently asked a question about showing toolbar buttons in Unified Service Desk (USD) for Dynamics 365, the question was “Is it possible to hide / show buttons based on a user’s security role?“. In this post I will attempt to answer this question.

By way of an example, imagine this scenario, say you want to hide the debug toolbar button to all user except anyone with the system administrator or system customizer roles.

The steps involved are;

  1. Create a Search
  2. Create a DoSearch action
  3. Create two SaveSetting actions
  4. Add actions to DeskTopReady
  5. Add conditions to the toolbar buttons

Note: I am assuming you already have a toolbar button that loads the debugger!

Step One – Create a Search

First of all I needed to run a search to see if the current user had either the system customizer or system administrator roles. For this I used the “Entity Searches” option in USD.

I created an entity search that looked like this ….

My entity search contained the following fetch XML.

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="role">
<attribute name="name"/>
<attribute name="businessunitid"/>
<attribute name="roleid"/>
<order descending="false" attribute="name"/>
<filter type="and">
<filter type="or">
<condition attribute="name" value="system administrator" operator="eq"/>
<condition attribute="name" value="system customizer" operator="eq"/>
</filter>
</filter>
<link-entity name="systemuserroles" intersect="true" visible="false" to="roleid" from="roleid">
<link-entity name="systemuser" to="systemuserid" from="systemuserid" alias="al">
<filter type="and">
<condition attribute="systemuserid" operator="eq-userid"/>
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>

Tip: If you wish to adapt this, an easy way to generate the fetch XML is to create an advanced find and then use the “Download Fetch XML” button.


Field Details
Name SecurityRole
Entity role

This is is schema name of the entity that hold system roles, you will need to add this as an entity to be USD by USD!

Fetch XML You could just cut and paste the XML I have shown above!

Step Two – Create a DoSearch Action

Having created my search, I needed a DoSearch action. As shown below;

Field Details
Name CRM Global Manager – Do Search (SecurityRole)
Order 7

You could use a different order number! But it will need to be lower than the SaveSetting actions we’ll create in the next step.

Hosted Control CRM Global Manager
Action DoSearch
Data name=SecurityRole

global=true

maxcount=1

Step Three – Create Two SaveSetting actions

It would have been possible for me to reference the results of the DoSearch in all my conditions. But I felt a more elegant approach would be to save a setting that will contain “True” or “False”. For this I created two actions, one for the false and one to the true. My actions looked like this;

For the False option I created ….

For the True option I created …

Field Details
Name CRM Global Manager – Save Setting (SystemAdmin True)

And

CRM Global Manager – Save Setting (SystemAdmin True)

Order 8

You could use a different order number! But it will need to be higher than the DoSearch action we created in step two.

Hosted Control CRM Global Manager
Action SaveSetting
Data name=SystemAdmin

value=True

Or

name=SystemAdmin

value=False

Condition “[[$Return.CRM Global Manager – Do Search (Security Role)]g]”!=”0″

Or

“[[$Return.CRM Global Manager – Do Search (Security Role)]g]”==”0”

Here I am basically triggering the true action if the DoSeach returned data or the false action if the user doesn’t have the required role.

Step Four – Add Actions to DeskTopReady

I now need to trigger my search and save of setting when USD loads, so for this I add the actions to the DeskTopReady event of Global Manager. Below you can see that I have added the three actions to the DeskTopReady event of my global manager.

Before I show the conditions we need to add, let’s have a quick look what is happening inside USD. Once USD loads we will do a search and save a setting. That setting is available as a replacement parameter. You can see below that I have a SystemAdmin parameter in my data parameters. I can then reference this parameter in conditions using [[$Settings.SystemAdmin]].

Step Five- Add condition to the Toolbar Button

Now we have the setting stored it can be used anywhere that I want to restrict access to anyone but the system administrators. For example, I have added an enable condition to my toolbar button used to access the debugger.

The enabled condition of “[[$Settings.SystemAdmin]]”==”True” will ensure the button is only enabled if the current user has the system administrator or system customizer role.

I hope you can see that this approach could be adapted for other roles / buttons within your application. Enjoy.
J


Filed under: USD - Configuration Tagged: Dynamics 365, Unified Service Desk

USD – Configuration Option

$
0
0

In this post, I will describe “Configurations” in Unified Service Desk (USD) for Dynamics 365 and when you would want to use them. And importantly when not to use them!

A configuration in Unified Service Desk is a set of hosted controls, actions, events etc. Each set of these USD assets is called a configuration. You can then assign a configuration to a user.

Let’s imagine our contact centre is made up of two distinct teams. One team looks after incoming calls from existing customers. This first team would need functionality to manage customer service requests. The second team might make cold calls to leads to try to sell our latest and greatest product. These two groups of users may require significantly different functionality (and agent scripting) within USD. The Configuration option gives us a construct capable of handling this situation.

The first important point to understand is that using configurations in Unified Service Desk is optional, you don’t have to use them! In fact, I would avoid them unless you have a clear requirement to maintain multiple configurations. Why? Well, the upside is I can have differing functionality by user. The downside creating multiple configurations is we’ll increase the ongoing testing and maintenance overhead.

In some scenarios, you may simply want to hide / show a few options to certain users. For example, a supervisor many need access to a few extra buttons or maybe only your administrators should have access to the debug option. In these situations, I would look to use user options or even query the users CRM role. I describe how to achieve this here.

If, however your requirements are more varied / complex then configurations come into play.

Each configuration can be made up of a number of assets, including;

  • Hosted Controls
  • Events
  • Action Calls
  • Toolbars
  • Window Navigation Rules
  • Entity Searches
  • Session Lines
  • Agent Scripts
  • Scriptlets
  • Customizations files
  • Forms
  • Options

Configuration Example

I personally think understanding how something works is often best achieved by looking at a working example! I will therefore create two simple configurations.

Configuration One

User will be given a search toolbar that will show active accounts. Opening an account will start an account session. On an account if I click a contact the contact will open in a tab within the account session.

Configuration Two

This will be very similar to configuration one but these users will be given a search toolbar that will show contacts. Opening a contact will start a contact session. And if the account has an associated account, clicking on an account will open that as a tab within the contact session.

I hope you can see that these are two simple configurations but will differ in some significant ways.

Note: I am going to assume you already have an advanced understanding of USD. I am not therefore going describe the detail of how my actions, navigation rules etc operate.

Configuration one will be my default configuration. Each user can be assigned to a configuration but if no configuration is defined they will inherit the default.

As I describe how I created each configuration I will point out a few tips along the way!

My first configuration is shown below. Notice that it is selected as my default. The default option is actually set using the set as default button in the toolbar.

Hosted Controls – notice that I have included all of the hosted controls that are required. This includes some “system” / “essential” ones that must always be present, such as Global Manager, Panel Layout and Connection Manager. What you are seeing here is that each configuration must include all of the required assets not just the ones you have customized.

Events – here I have listed all of the events that have specific actions associated with them. In my very simple example I just included DeskTopReady as in both configurations I decided to load the user CRM home page in a tab when USD opens. (Plus, maximize the screen.)

At this point I would like to mention a challenge! When I use the “+” button to add events I can see a list of the possible events to add but this can be confusing. Even my simple configuration contains multiple CRM Pages, each one will have a set of events with the same name. Every CRM Page, for example, will have an ActiveClosed event. Meaning you could very quickly get confused as to which is which. The screen below shows USD’s out of the box behaviour.

To solve this “irritation” I opened the event entity in customizations and made a change to its lookup view.!

You can see below that I have added the hosted application field to the lookup view. After you have done this make sure you select “Publish all”.

Now when I search for events I can see their associated hosted control. Meaning I could tell which events related to which hosted control. Much simpler to use!

Action Calls, next I listed all of the action calls that applied in my configuration. So, I had actions to search for accounts, navigate to the CRM home page etc.

I continued this theme with my first configuration adding toolbars, windows navigations rules, session lines and options. I didn’t add any entity searches, agent scripts or scriptlets. Simply because my example was simple! But I hope you can see that you could continue to add as many assets as required. Having differing agent scripts maybe something you’d commonly want to achieve with configurations.

Cloning my Configuration

Once I had created and tested my default configuration, I realised that my second configuration would have a lot of commonality to my first. So, cloning the first one and then making changes seemed like a good idea. Luckily Microsoft provide us with a clone option!

So, I opened my Configuration One and used the Clone option from the toolbar.

Having cloned my configuration USD created me a new one called “Configuration One – Copy”. I could now start the process of amending this configuration. (My first task was to rename it from “Configuration One – Copy” to “Configuration Two”.

Altering my Configuration

I can now set about changing my newly created configuration. As mentioned much of my configuration will remain the same and I will share many of the assets in configuration one and configuration two.

In my hosted controls and events sections of the configuration, I made no changes. I could reuse all of this. And in actions I simply removed the old search action I had and inserted a new one. As now I’d want to search by contact instead of account.

Next I remove the main toolbar I did have and created a new one that would include a different search button. One that this time would call my action to search for contacts. I found neither of my window navigation rules were appropriate so I removed both of them and added two new ones.

The final change in my simple solution was to remove the session line I’d created to name the account session and insert a new one to name my contact session.

You may recall the “Configuration One” was defined as my default configuration. Meaning all users would get this unless we state otherwise. You can see in the Users sub-grid at the top of my configuration which users have been assigned this configuration. You can add users to the configuration directly from the configuration form. Or by opening the user’s systemuser record and amending the USD configuration lookup.

Finally, I re-loaded UD and tested my new configuration. I could now search for contacts and had all of the alternative behaviour required.

So, what do I think of configurations???? I admit I have some reservations about the complexity they introduce. For example, I would want to try to re-use assets as much as possible. But in doing so, it would create a need to re-test each configuration separately after a change. BUT, if you need significantly different functionality between users they do offer some significant capabilities.

When using configurations, I would advise all changes to be made via the configurations screens. I actually quite seeing all my assets in one place. The reason I say this is if you navigate to the “standard” USD screens you will see all the assets across all the configurations. Imagine looking at a full list of window navigation rules, many could conflict with each other. So, to avoid confusion, you’ll want to view them in the context of a specific configuration.

In summary configurations, in my opinion should be avoided if possible! But when you do need them they are a big bonus.
J


Filed under: USD - Configuration Tagged: Unified Service Desk

USD – Execute Actions from JavaScript

$
0
0

In a previous post, I explained how we could trigger events from JavaScript when using Unified Service Desk (USD) for Microsoft Dynamics 365. In this post, I will show how a similar approach can be applied to actions in USD.

If you’d would like to view that previous post on events, you can find it here.

I always like to explain things by showing an example. In this case my example will be a small feature I have implemented in my USD application.

When viewing an account (or other entity) I can add contacts from a sub grid on the account form. Doing this will open the contact Quick Create form. I wanted to have a note on the account that a contact had been created. Meaning I’d need to trigger a USD on the save of the contact.

I could have achieved this requirement in several different ways! But I decided to use an action called from JavaScript.

This simple example was very easy to achieve!

You can see the end result of my change below. I have added a contact and a note has been created on the account to say who created the contact and when.

I simply created a small amount of JavaScript that was added to the “On Save” event of my CRM Quick Create form. My code looked like this;

function OnSave() {

    // ** When we save a contact, in quick create form.
    // **    then ...
    // **        if in USD then fire an action that will add a note to the account (or other entity)
    // **        the note will show us that a contact has been added.
    // ** Notice that I use %0D%0A, this gives an essential line feed!

    var name = Xrm.Page.getAttribute("firstname").getValue() + " " + Xrm.Page.getAttribute("lastname").getValue();
    if (window.IsUSD == true) {
       var data = "LogicalName=annotation " + "%0D%0A";
        data += "objectid=EntityReference(\"[[$Context.LogicalName]]\",[[$Context.Id]]) " + "%0D%0A";
        data += "notetext=$Escaped(CONTACT ADDED Name is " + name + ")";
        window.open("http://uii/CRM Global Manager/CreateEntity?" + data);
    } // End if
} // End function

 

Hopefully you can see in my window.IsUSD command how I ensure this code only runs whilst inside USD. Also notice the winow.open command that contains the instruction to run the USD action. This is essentially made up of the hosted control name, action name and data parameters.

Tip: My data parameter has several lines, this means I need to add a carriage return / line feed at the end of each line. I do this with %0D%0A!

In my case the hosted control was my global manager and the action was CreateEntity. You can find details of how we can use the CreateEntity action to create notes here.

Hopefully you can see that it is actually pretty easy to adapt this logic to work with any action in USD. J


Filed under: USD - Configuration Tagged: Dynamics 365, Unified Service Desk, USD
Viewing all 109 articles
Browse latest View live