<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Power Apps on LinkeD365 Blog</title><link>https://linked365.blog/tags/power-apps/</link><description>Recent content in Power Apps on LinkeD365 Blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Mon, 17 Aug 2020 00:00:00 +0000</lastBuildDate><atom:link href="https://linked365.blog/tags/power-apps/index.xml" rel="self" type="application/rss+xml"/><item><title>PL-100 - Microsoft Power Platform App Maker</title><link>https://linked365.blog/2020/08/17/pl-100-microsoft-power-platform-app-maker/</link><pubDate>Mon, 17 Aug 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/08/17/pl-100-microsoft-power-platform-app-maker/</guid><description>&lt;img src="https://linked365.blog/images/2020/08-microsoft-certified-associate-badge.png" alt="Featured image of post PL-100 - Microsoft Power Platform App Maker" />&lt;p>One of the newest exams on the block is &lt;a class="link" href="https://docs.microsoft.com/en-us/learn/certifications/exams/pl-100" target="_blank" rel="noopener"
>PL-100 Power Platform App Maker&lt;/a>. This exam is targeted at individuals who are currently making apps for their company and want to certify their talents. I saw this exam similar to the &lt;a class="link" href="https://docs.microsoft.com/learn/certifications/exams/mb-200?WT.mc_id=techcom_learn-blog-wwl" target="_blank" rel="noopener"
>MB-200&lt;/a> exam, which is soon to be replaced with &lt;a class="link" href="https://docs.microsoft.com/en-us/learn/certifications/exams/pl-200" target="_blank" rel="noopener"
>PL-200&lt;/a>, but I was wrong.&lt;/p>
&lt;p>The qualification associated with this exam is &lt;a class="link" href="https://docs.microsoft.com/en-us/learn/certifications/power-platform-app-maker" target="_blank" rel="noopener"
>Power Platform App Maker Associate&lt;/a>. The exam is still in beta, so hopefully I will add this qualification to my list when it comes out of beta.&lt;/p>
&lt;p>PL-100 is really an exam for the citizen developer, a doer. It delves deep into several areas, beyond a functional consultant role and more into the nitty-gritty of developing across the Power Platform. It is still CDS (or whatever it is called today) heavy, with no mention of SharePoint apart from in one of the scenarios.&lt;/p>
&lt;p>It also covers everything, unlike &lt;a class="link" href="https://thecrm.ninja/pl-100-microsoft-power-platform-app-maker-exam/" target="_blank" rel="noopener"
>EY&lt;/a> when he took it with only a few questions on the topic, I got several Power BI questions. This is definitely not in my comfort zone, so I am glad I did some research on it before I took the exam.&lt;/p>
&lt;p>One thing it didn&amp;rsquo;t really cover, even though it says in the &lt;a class="link" href="https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE4wo07" target="_blank" rel="noopener"
>Skills Outline&lt;/a> that it is 10-15% of the exam was the soft skills. Nothing really on high-level design, components, or functional skills. May have been the random set of questions I got. Like EY didn&amp;rsquo;t get Power BI, maybe I was &amp;ldquo;lucky&amp;rdquo; not to get questions on these.&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2019/09/16/ms-certifications-sharing-my-mind-maps/" target="_blank" rel="noopener"
>Like the rest of my exams&lt;/a>, I did a Mind Map to help me ensure I have covered all the basis for the exam, driven by the skills outline. The Mind Map for PL-100 is &lt;a class="link" href="https://onedrive.live.com/?authkey=%21AOj6ZOZlQiv9XhA&amp;amp;id=546A3A4C1B5A8DE7%21288972&amp;amp;cid=546A3A4C1B5A8DE7" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>&lt;img src="https://docs.microsoft.com/en-us/media/learn/certification/badges/microsoft-certified-associate-badge.svg"
loading="lazy"
>&lt;/p></description></item><item><title>User Admin - Published App</title><link>https://linked365.blog/2019/07/19/user-admin-published-app/</link><pubDate>Fri, 19 Jul 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/07/19/user-admin-published-app/</guid><description>&lt;img src="https://linked365.blog/images/2019/07-image-33.png" alt="Featured image of post User Admin - Published App" />&lt;p>After being asked on LinkedIn to publish both the apps that I built for the User Security Admin walk-through I have done so on Dynamics Communities &lt;a class="link" href="https://dynamics365society.uk/pab-directory/" target="_blank" rel="noopener"
>Power Platform Bank&lt;/a>&lt;/p>
&lt;h2 id="stand-alone-security--user-app">Stand-Alone Security / User App&lt;/h2>
&lt;p>The first one, which if you remember is a stand-alone application detailed &lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >here&lt;/a> can be downloaded here&lt;/p>
&lt;p>&lt;a class="link" href="https://dynamics365society.uk/powerappsbanklist/dynamics-ce-security-user-profile-powerapp/" target="_blank" rel="noopener"
>https://dynamics365society.uk/powerappsbanklist/dynamics-ce-security-user-profile-powerapp/&lt;/a>&lt;/p>
&lt;h2 id="embedded-security-app">Embedded Security App&lt;/h2>
&lt;p>The second app was the one after I converted the original to a embedded form in the User record, detailed &lt;a class="link" href="https://linked365.blog/2019/07/07/user-admin-powerapp-part-4/" >here&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="https://dynamics365society.uk/powerappsbanklist/dynamics-ce-embedded-security-powerapp/" target="_blank" rel="noopener"
>https://dynamics365society.uk/powerappsbanklist/dynamics-ce-embedded-security-powerapp/&lt;/a>&lt;/p>
&lt;p>Both apps require the custom connector to read and update teams and role, which are included in the package.&lt;/p>
&lt;p>Please let me know if it works for you via &lt;a class="link" href="https://twitter.com/linked365" target="_blank" rel="noopener"
>Twitter&lt;/a> or &lt;a class="link" href="https://www.linkedin.com/in/carlcookson/" target="_blank" rel="noopener"
>LinkedIn&lt;/a>&lt;/p>
&lt;p>Thanks goes to &lt;a class="link" href="https://twitter.com/WeAreTDG" target="_blank" rel="noopener"
>Those Dynamics Guys&lt;/a> for the great Dynamics Community &amp;amp; the PPB as well as &lt;a class="link" href="https://www.linkedin.com/in/schladot/" target="_blank" rel="noopener"
>Joergen Schladot&lt;/a> to giving me the kick up the arse to get it done.&lt;/p></description></item><item><title>User Admin PowerApp (Part 4)</title><link>https://linked365.blog/2019/07/07/user-admin-powerapp-part-4/</link><pubDate>Sun, 07 Jul 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/07/07/user-admin-powerapp-part-4/</guid><description>&lt;img src="https://linked365.blog/images/2019/07-image-33.png" alt="Featured image of post User Admin PowerApp (Part 4)" />&lt;p>As putting a canvas app on a model driven form is now out of &lt;a class="link" href="https://docs.microsoft.com/en-us/business-applications-release-notes/April19/microsoft-powerapps/embedding-canvas-apps-model-driven-forms-generally-enhanced" target="_blank" rel="noopener"
>preview&lt;/a> I thought that my &lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >PowerApp to add security roles&lt;/a> and teams might be a suitable candidate to be migrated to an embedded canvas app.&lt;/p>
&lt;h2 id="not-going-to-repeat">Not going to repeat&lt;/h2>
&lt;p>There are lots of &lt;a class="link" href="https://www.youtube.com/watch?v=ivvh49bsH0M" target="_blank" rel="noopener"
>videos&lt;/a> and blog &lt;a class="link" href="https://the365hero.com/blog/2018/12/24/embedded-canvas-apps-for-dynamics-365/" target="_blank" rel="noopener"
>posts&lt;/a> out there which detail how to embed a canvas app into model, so there is no point repeating that, just stand on their shoulders.&lt;/p>
&lt;p>Needless to say, there are a few gotchas. I will walk through how I addressed each one.&lt;/p>
&lt;h2 id="the-connection-isnt-there-straight-away">The connection isn&amp;rsquo;t there straight away&lt;/h2>
&lt;p>Rather than displaying the first user selection screen, the embedded app goes straight to the display of user roles and teams. The user selected should come from the record the end user is on. In the original code, I used the selected record, which is available as the user clicked on it.&lt;/p>
&lt;p>From the embedded app, there is a connection to the underlying record, using the ModelDrivenFormIntegrationData property. I found that this was not populated straight away, prior to form visible anyway. To get around this, and I think &lt;a class="link" href="https://twitter.com/ScottDurow" target="_blank" rel="noopener"
>Scott Durrow&lt;/a> demoed this in a &lt;a class="link" href="https://twitter.com/d365uguk" target="_blank" rel="noopener"
>D365 User Group&lt;/a> meeting, you need a wait screen.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-29.png"
loading="lazy"
>&lt;/p>
&lt;p>The Timer has configured to have a duration of 2000ms, with Auto start enabled. On Timer End Event is a simple navigation to the actual start screen.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-30.png"
loading="lazy"
>&lt;/p>
&lt;p>I found that this was more than enough to get the data available in my application, so that the On Visible on the main screen could do all the things it needed to do.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-loadscreen.gif"
loading="lazy"
>&lt;/p>
&lt;h2 id="dont-forget-to-publish">Don&amp;rsquo;t forget to publish&lt;/h2>
&lt;p>The only way you can really see what is going on in your app is to run it within the D365 form. The debugging of the application is a little contrived when using the embedded app, so I used a liberal amount of labels with string values in there to understand what is being set and which value is being used.&lt;/p>
&lt;p>Fundamentally, you need to publish everytime you need to see the application in your environment. Without the publish, the previous version is shown.&lt;/p>
&lt;h2 id="screen-size-wows">Screen size wows&lt;/h2>
&lt;p>This app is now configured with landscape mode, with Scale to fit, locked aspect ration and locked orientation. This seems to work more effectively for higher resolution screens on Windows machines. The screen scales with its size, which is great, but I would like to see the option for better use of the real estate.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-32.png"
loading="lazy"
>&lt;/p>
&lt;p>As you can see, when the screen is large, the buttons and text in the PowerApp gets very big, over the top for mouse users.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-screensizing.gif"
loading="lazy"
>&lt;/p>
&lt;p>If you change the screen properties to remove scale to fit, and alter some of the properties to ensure proper positioning as the screen moves, you get a more appropriate display for large screens, but are limited on tablets etc. Know your audience I guess.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-screensizing2.gif"
loading="lazy"
>&lt;/p>
&lt;h2 id="back-to-the-code">Back to the code&lt;/h2>
&lt;p>The first part is to create a variable with the user data in it. ModelDriverFormIntegration will always be a table, all be it with only row in our case. Using a variable, this single record is available elsewhere. Just a method of not having to repeat that long property line throughout the application.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">userdata&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">First&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ModelDrivenFormIntegration&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The next step, was copy and paste from the other version, replacing where the app is expecting a selection of a user with the user id taken from the userdata. Firstly, creating a FetchXML string to derive the teams for the user, then passing this into the flow connector to retrieve the teams.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamstring&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">team&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">isdefault&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemmanaged&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teammembership&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">from&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teamid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">to&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teamid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">intersect&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&amp;#34; &amp;amp; userdata.SystemUserId &amp;amp; &amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Stick it in a collection for display on the form
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">ClearCollect&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teams&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">GetTeams&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">teamstring&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The format of the application has changed, to a landscape view. I made both the teams and roles grid visible, with a search field at the top. The Teams grids items is set to the collection, with filtering and sorting applied&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-31.png"
loading="lazy"
>&lt;/p>
&lt;p>Next in the on visible event, the FetchXML is built to help in adding teams to the user. Firstly, create a table with the snippets in for the existing teams filters, then creating the actual FetchXML&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span> &lt;span class="nf">ForAll&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teams&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;condition attribute=&amp;#34;&amp;#34;teamid&amp;#34;&amp;#34; operator=&amp;#34;&amp;#34;neq&amp;#34;&amp;#34; value=&amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">teamid&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&amp;#34; /&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// create the fetchXML to restrict the teams to those that user has not already got
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamsNotGot&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">team&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">isdefault&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemmanaged&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; Concat(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The process above is also done for the roles. The one gotcha around roles is that there is a business Id field user, but that gives you the name of the BU. If you use the BusinessUnitIdName field, that actually holds the GUID of the BU. Seems counter intuitive to me.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesNotGot&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; Concat(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">businessunitid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; userdata.BusinessUnitIdName &amp;amp; &amp;#34;&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="o">/&amp;gt;&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The final app I think is a much better interface to manage roles and teams for a user. It works well in this context and allows managers to quickly change the roles for who they are concerned with.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-33.png"
loading="lazy"
>&lt;/p></description></item><item><title>User Admin PowerApp (Part 3)</title><link>https://linked365.blog/2019/06/23/user-admin-powerapp-part-3/</link><pubDate>Sun, 23 Jun 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/06/23/user-admin-powerapp-part-3/</guid><description>&lt;img src="https://linked365.blog/images/2019/06-image-22.png" alt="Featured image of post User Admin PowerApp (Part 3)" />&lt;p>The user has been notified that they have a new report, the manager has updated some fields on their user record, they now want to add some roles and teams to allow them to start work.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario (&lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1//" >Part 1&lt;/a>)&lt;/li>
&lt;li>Notifying the manager of a new Employee (&lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>PowerApp to display and update User Data (&lt;a class="link" href="https://linked365.blog/2019/06/18/user-admin-powerapp-part-2/" >Part 2&lt;/a>)&lt;/li>
&lt;li>Update Roles and Teams (This Part)&lt;/li>
&lt;/ul>
&lt;h2 id="listing-roles-that-user-hasnt-got">Listing Roles that user hasn&amp;rsquo;t got&lt;/h2>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-21.png"
loading="lazy"
>&lt;/p>
&lt;p>The grid at the bottom of the user screen shows the roles that the user has. If we want to add a role to that list, firstly lets display the roles available to them.&lt;/p>
&lt;p>On the form visible event, there is a lot going on. I have already discussed defining the XML to get the list of roles and teams for the user. In this code I also create XML to retrieve the roles the user hasn&amp;rsquo;t got. Again, &lt;a class="link" href="https://jonasr.app/fxb/" target="_blank" rel="noopener"
>FetchXML Builder&lt;/a> is your friend.&lt;/p>
&lt;p>A looping concatenation isn&amp;rsquo;t available (well not this week) in PowerApps, so you have to get around this by populating a table with one or more strings then concatenating the output of the table.Using the Set command, create a variable and populate it with a string like below using the ForAll command to repeat the string build for each of the roles the user has got.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span> &lt;span class="nf">ForAll&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">secGroups&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;condition attribute=&amp;#34;&amp;#34;roleid&amp;#34;&amp;#34; operator=&amp;#34;&amp;#34;neq&amp;#34;&amp;#34; value=&amp;#39;&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">role2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="err">&amp;#39;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;#39; /&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This, when you then use the ConCat command creates one string with these as many parts in in as roles the user has.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;neq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;0699ab9b-984c-4896-9c8a-38352fdc3c93&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;neq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;d77e2e20-4eac-4fbf-b1a8-5bec6f853ebf&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The final string combines this string with the other bits that I am interested in, selecting the attributes that is required as well as filtering the roles return to only those in the users BU. If this condition is not put in, all the roles that are associated with all the BUs will be returned. In D365, a role is duplicated for each BU you create, and you need to associate the user with the right role for their BU.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesNotGot&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; Concat(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">businessunitid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; MyReports.Selected.&amp;#39;Business Unit&amp;#39;.businessunitid &amp;amp; &amp;#34;&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="o">/&amp;gt;&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This produces an XML that looks like the below.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;fetch&lt;/span> &lt;span class="na">top=&lt;/span>&lt;span class="s">&amp;#34;50&amp;#34;&lt;/span> &lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;role&amp;#34;&lt;/span> &lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;name&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;filter&lt;/span> &lt;span class="na">type=&lt;/span>&lt;span class="s">&amp;#34;and&amp;#34;&lt;/span> &lt;span class="nt">&amp;gt;&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;neq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;0699ab9b-984c-4896-9c8a-38352fdc3c93&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;neq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;d77e2e20-4eac-4fbf-b1a8-5bec6f853ebf&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;businessunitid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;eq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;ec0e9d51-0e91-e911-a822-000d3a34e879&amp;#39;&lt;/span>&lt;span class="nt">/&amp;gt;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/fetch&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>On selecting the plus button at the top of the grid for Roles, another collection is populated using the custom connector, passing the XML to the Roles definition.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Collect&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">groupsandteams&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">GetAllRoles&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rolesNotGot&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="add-role-screen">Add Role screen&lt;/h2>
&lt;p>The final screen is a simple gallery, with the name of the role displayed.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-22.png"
loading="lazy"
>&lt;/p>
&lt;p>All the work is done on the + icon. This calls another custom connector, adding the role to the user. Postman is your friend here. My Postman to insert a role for a user is shown below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-23.png"
loading="lazy"
>&lt;/p>
&lt;p>Basically, this is posting a body containing a systemuserroles_asscociation to the the webapi, which creates a new one. The user reference is in the URL and the roleId is in the body.&lt;/p>
&lt;p>Now, I confess I am not the most offay on the best way to use the Web API. This is one of the reasons I am writing a blog, learning. See that little highlighted $ref? I spent hours trying to get this working and only found that this is required at the end. If you omit the $ref, it returns a positive result. Same if you try to add a role that belongs to a BU that the user doesn&amp;rsquo;t. Someone tell me where this is logged so next time I can do some troubleshooting rather than trial &amp;amp; error?&lt;/p>
&lt;p>The D365 &lt;a class="link" href="https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/webapi/associate-disassociate-entities-using-web-api#associate-entities-on-update-using-collection-valued-navigation-property" target="_blank" rel="noopener"
>document&lt;/a> does mention it, but it is simply missed and it is part of the OData standard for &lt;a class="link" href="http://docs.oasis-open.org/odata/odata/v4.0/cs01/part2-url-conventions/odata-v4.0-cs01-part2-url-conventions.html#_Toc365046422" target="_blank" rel="noopener"
>addressing references between entities&lt;/a>. As I say, learn everyday.&lt;/p>
&lt;p>To convert this to a custom connector definition the GUID of the user account in the URL needs to be replaced with a parameter, note the curly brackets and looks like the below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-25.png"
loading="lazy"
>&lt;/p>
&lt;p>In PowerApps, after refreshing the connector, there is a new method on our connector. On click of the + in the Add role screen, this is called.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">AddRole&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MyReports&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Selected&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;https://urlofyourcrm.crm.dynamics.com&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;/api/data/v9.0/roles(&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">roleid&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Even though the second parameter has been hidden and given a default value in the connector, it still prompts to be entered. Not sure why.&lt;/p>
&lt;p>The Teams addition is the same logic, but a different connecting entity. The postman for this is below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-26.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="deleting-a-role">Deleting a Role&lt;/h2>
&lt;p>To complete the circle, a manager should be able to delete a role or team that the user belongs to. This is again done via a custom connector, the postman is below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-27.png"
loading="lazy"
>&lt;/p>
&lt;p>As with the create definition, the 2 guids in the url need to be swapped out so the definition is created like this&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-28.png"
loading="lazy"
>&lt;/p>
&lt;p>Once refreshed in PowerApps, this is connected to the remove button on the Roles grid.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">DeleteRole&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MyReports&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Selected&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">role2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>After this call, the grids are refreshed to show the action has taken effect.&lt;/p>
&lt;p>Teams works in the same way, using the url like this&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-29.png"
loading="lazy"
>&lt;/p>
&lt;p>And that is it! This app works well to bridge the gap for onboarding users in a busy enterprise, especially as a PowerApp, it is available to users on the go.&lt;/p>
&lt;p>Custom Connectors really bring the availability of all the standard Customer Engagement functionality to the &amp;ldquo;citizen developer&amp;rdquo;. As enterprise level organisations get on board with PowerApps, small apps that make the employee experience easier will become necessary. This is only an example of how this could be done. Reach out if you would like me to share the app with you.&lt;/p></description></item><item><title>User Admin PowerApp (Part 2)</title><link>https://linked365.blog/2019/06/18/user-admin-powerapp-part-2/</link><pubDate>Tue, 18 Jun 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/06/18/user-admin-powerapp-part-2/</guid><description>&lt;img src="https://linked365.blog/images/2019/06-image-3.png" alt="Featured image of post User Admin PowerApp (Part 2)" />&lt;p>So, after notifying the user that there is a new employee in their team, the manager needs to be able to update the data.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario (&lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>Notifying the manager of a new Employee (&lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>PowerApp to display and update User Data (This Part)&lt;/li>
&lt;li>Update Roles and Teams&lt;/li>
&lt;/ul>
&lt;h2 id="my-reports">My Reports&lt;/h2>
&lt;p>I am not going to go through how to create a PowerApp, there are numerous blogs and pages that step you through this, may I recommend the Microsoft &lt;a class="link" href="https://powerapps.microsoft.com/en-us/blog/microsoft-powerapps-learning-resources/" target="_blank" rel="noopener"
>page&lt;/a> with it all on?&lt;/p>
&lt;p>My PowerApp is pretty straight forward at the start. The first screen is to retrieve all the users that the current logged in user manages, connected to a User data source in the CDS.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>Start with a new List form, connect it to your CDS User data set and select a few fields. With the List form, there are several parts that you need to configure, to make the buttons at the top of the screen to work correctly.&lt;/p>
&lt;p>Firstly, the Items property needs to be configured to correctly display and filter the data according to the search the user has selected and the sort.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">SortByColumns&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Search&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Filter&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Users&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Manager&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">internalemailaddress&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">User&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">Email&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">TextSearchBox2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Text&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;fullname&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;fullname&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">If&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SortDescending&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SortOrder&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Descending&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SortOrder&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Ascending&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The core to this is the Filter, where the Users (the data source) is filtered to only show those where the email address of the manager of the user is the current users email address.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Filter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Users&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Manager&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">internalemailaddress&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">User&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">Email&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Wrapped around this is functionality to sort and search this grid.&lt;/p>
&lt;p>BTW, the picture is the &amp;lsquo;Entity Image&amp;rsquo; field in the data set, the picture that a user can upload into D365 against their user account.&lt;/p>
&lt;h2 id="user-details">User Details&lt;/h2>
&lt;p>The next screen is a standard edit form, navigated to via the little arrow with this logic&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Parent&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Navigate&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Employee&lt;/span> &lt;span class="n">Edit&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ScreenTransition&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">CoverRight&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>The form again connects to the User data set, with the item in the edit portion being the significant bit&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-6.png"
loading="lazy"
>&lt;/p>
&lt;p>I have just selected some random fields to display here, where I think it would be appropriate to manage. The Business Unit is a key field for a user, and is a selection and needs a little help to display the right data and update the record appropriately.&lt;/p>
&lt;p>Start by adding the field. If you select the datacardvalue control (the drop down itself in the form), notice that a couple of things are wrong.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-8.png"
loading="lazy"
>&lt;/p>
&lt;p>Business Unit is a parent of User, a relationship Lookup, and PowerApps has decided (not sure why, the default for lookups surely should be the name field, which is how D365 works) to select the Address1_City field to display to the user when they are selecting. Change this to &amp;ldquo;name&amp;rdquo;. Change the search as well to match.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-9.png"
loading="lazy"
>&lt;/p>
&lt;p>Now, the form will display the BU of the user as well as allowing an update of this field.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-10.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="displaying-security-roles">Displaying Security Roles&lt;/h2>
&lt;p>At the bottom of the edit form are 2 grids to display the users security roles and their teams. Both operate in the same way.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-11.png"
loading="lazy"
>&lt;/p>
&lt;p>To get at the roles for a user, you have to use a bit of FetchXML. There is a hidden link table, or a collection value navigation, systemuserroles_association, which links a role with a user.&lt;/p>
&lt;p>If you are using any sort of FetchXML, &lt;a class="link" href="https://jonasr.app/fxb/" target="_blank" rel="noopener"
>&lt;/a>&lt;a class="link" href="https://jonasr.app/fxb/" target="_blank" rel="noopener"
>FetchXML Builder&lt;/a> (FXB) by &lt;a class="link" href="https://twitter.com/rappen" target="_blank" rel="noopener"
>Jonas Rapp&lt;/a> is essential. It allows a developer to define the exact fields, the connections and filters to form a query for data by looking at the data model. Start with a blank query, select the systemuser entity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-12.png"
loading="lazy"
>&lt;/p>
&lt;p>In our scenario, the query should return the roles for one user, the one that has been selected by the manager. Add a filter, then a condition, select the systemuserroles entity, and the systemuserid attribute (field). The operator is equals and the value is the GUID of the user account.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-14.png"
loading="lazy"
>&lt;/p>
&lt;p>To test the query, paste in the GUID of the user. Another great tool is the Chrome Addon, &lt;a class="link" href="https://chrome.google.com/webstore/detail/level-up-for-dynamics-365/bjnkkhimoaclnddigpphpgkfgeggokam" target="_blank" rel="noopener"
>Level Up for Dynamics&lt;/a> by &lt;a class="link" href="https://twitter.com/RajYRaman/" target="_blank" rel="noopener"
>Natraj Yegnaraman&lt;/a> allows you to quickly get to the GUID of any record, as well as some other useful tools (please don&amp;rsquo;t tell an end user about God Mode). The query should retrieve all the fields on the User entity for the chosen user.&lt;/p>
&lt;p>Next, select a link-entity, namely the many to many systemuserroles.systemuserid -&amp;gt; systemuserid.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-13.png"
loading="lazy"
>&lt;/p>
&lt;p>Executing this query will result in a lot of fields been returned, most of no interest to our query, so add some attributes, which limits the fields returned. Only interested in the roleId and the name.&lt;/p>
&lt;p>Hit execute this time and this will display the roles that are associated with the user selected.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-18.png"
loading="lazy"
>&lt;/p>
&lt;p>This is all well and good, but how is this data getting into the PowerApp? A custom connector of course. I have used custom connectors a lot to get at the bits the standard CDS connector can&amp;rsquo;t in my other posts. I won&amp;rsquo;t discuss how to create the connector, my post on &lt;a class="link" href="https://linked365.blog/2019/04/03/connecting-luis-d365-part-4-custom-connector/" target="_blank" rel="noopener"
>LUIS&lt;/a> covers that. I expand on it fixing the &lt;a class="link" href="https://linked365.blog/2019/05/11/creating-attachments-in-d365/" target="_blank" rel="noopener"
>bug on creating attachments in D365&lt;/a>.&lt;/p>
&lt;h2 id="creating-the-connector-definition">Creating the Connector Definition&lt;/h2>
&lt;p>Again, Postman is your friend here. Each of the main entities will accept FetchXML as a parameter, as in this is what is created in Postman&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">{{WebAPIUrl}}/systemusers?fetchXml=&lt;span class="nt">&amp;lt;fetch&lt;/span> &lt;span class="na">mapping=&lt;/span>&lt;span class="s">&amp;#34;logical&amp;#34;&lt;/span> &lt;span class="na">count=&lt;/span>&lt;span class="s">&amp;#34;50&amp;#34;&lt;/span> &lt;span class="na">version=&lt;/span>&lt;span class="s">&amp;#34;1.0&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;systemuser&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;fullname&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&amp;lt;filter&lt;/span> &lt;span class="na">type=&lt;/span>&lt;span class="s">&amp;#39;and&amp;#39;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#39;systemuserid&amp;#39;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#39;eq&amp;#39;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;EBD3707B-6C88-E911-A83E-000D3A323D10&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;link-entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;systemuserroles&amp;#34;&lt;/span> &lt;span class="na">from=&lt;/span>&lt;span class="s">&amp;#34;systemuserid&amp;#34;&lt;/span> &lt;span class="na">to=&lt;/span>&lt;span class="s">&amp;#34;systemuserid&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;link-entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;role&amp;#34;&lt;/span> &lt;span class="na">from=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">to=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="nt">/&amp;gt;&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span>&lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/link-entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/link-entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/fetch&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Paste this into a new connector action and PowerApps will convert the fetchXML as a new parameter for the action.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-15.png"
loading="lazy"
>&lt;/p>
&lt;p>Test this action with a copy and paste of the XML that you generated in FetchXML Builder and the action will return a bit of XML itself&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-17.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="using-the-connector-in-the-app">Using the Connector in the app&lt;/h2>
&lt;p>Add the custom connector as a Data source in the App.&lt;/p>
&lt;p>To call the connector, on the OnVisible of the Employee Edit form, generate the XML first. Set a variable to the XML generated from FXB, substituing the current selected user id as appropriate&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">secString&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch mapping=&amp;#34;&amp;#34;logical&amp;#34;&amp;#34; count=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; version=&amp;#34;&amp;#34;1.0&amp;#34;&amp;#34;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuser&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">fullname&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="err">&amp;#39;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="err">&amp;#39;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; MyReports.Selected.User &amp;amp; &amp;#34;&lt;/span>&lt;span class="err">&amp;#39;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserroles&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">from&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">to&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">from&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">to&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>MyReports is the list on the first screen, Selected is the user that the manager has selected. PowerApps converts the User to the GUID of the user (handy). Be careful with the quotes here, I found when pasting, curly versions of the straight quotes came in ( “ rather than &amp;ldquo;) which took me a while to resolve. Also, ensure all the double quotes are present. FXB provides single quotes and hence you need to double up for PowerApps to infer an actual quote rather than the end of the string.&lt;/p>
&lt;p>Update: Thanks to &lt;a class="link" href="https://twitter.com/rappen" target="_blank" rel="noopener"
>Jonas Rapp&lt;/a> for reaching out on Twitter to put me right. In FXB there is a setting to use single quotes rather than double in the rendered XML&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-30.png"
loading="lazy"
>&lt;/p>
&lt;p>This then allows a straight copy / paste into your PowerApp&lt;/p>
&lt;p>Set(
secString,&amp;quot;&lt;fetch top='50' >
&lt;entity name='systemuser' >
&lt;filter type='and' >
&lt;condition attribute='systemuserid' operator='eq' value='" &amp; MyReports.Selected.User &amp; "' />
&lt;/filter>
&lt;link-entity name='systemuserroles' from='systemuserid' to='systemuserid' intersect='true' >
&lt;link-entity name='role' from='roleid' to='roleid' >
&lt;attribute name='name' />
&lt;attribute name='roleid' />
&lt;/link-entity>
&lt;/link-entity>
&lt;/entity>
&lt;/fetch>&amp;rdquo;&lt;/p>
&lt;p>After the string is created, pass this to the custom connector, inserting the return into a collection. This is the collection that is shown in the grid.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Get the groups for the selected user
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nf">ClearCollect&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">secGroups&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">GetSecGroups&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">secString&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Put a gallery on the form, and use this collection as its items list, and sorted by the role just for usability.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-19.png"
loading="lazy"
>&lt;/p>
&lt;p>The Teams grid is populated very much the same. The connector is based around the teams entity rather than the system user (in hindsight, I should have based the roles one of roles, rather than user, but achieves the same result, and it is all about learning isn&amp;rsquo;t it?). The XML looks like this.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamstring&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">team&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">isdefault&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemmanaged&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teammembership&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">from&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teamid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">to&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teamid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">intersect&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&amp;#34; &amp;amp; MyReports.Selected.User &amp;amp; &amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>teammembership is the connecting table.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-20.png"
loading="lazy"
>&lt;/p>
&lt;p>So, that is enough for now, the app displays users that report to me, I can see their teams and roles. Next post will show how the teams and roles are updated.&lt;/p></description></item><item><title>User Admin PowerApp (Part 1)</title><link>https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/</link><pubDate>Mon, 10 Jun 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/</guid><description>&lt;img src="https://linked365.blog/images/2019/06-image-3.png" alt="Featured image of post User Admin PowerApp (Part 1)" />&lt;p>Sorry it has been a while since my last blog post, this scenario has taken a while to get it to the state where I was happy to show it off. Mainly due to my own lack of understanding of the intricacies of the D365 API, but also been busy external to the blog, you know real life.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario (This part)&lt;/li>
&lt;li>Notifying the manager of a new Employee (This Part)&lt;/li>
&lt;li>PowerApp to display and update User Data&lt;/li>
&lt;li>Update Roles and Teams&lt;/li>
&lt;/ul>
&lt;h2 id="the-scenario">The Scenario&lt;/h2>
&lt;p>Big Energy Co is going from strength to strength, presumably because of the innovative solutions using &lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365-part-1/" >LUIS&lt;/a>, &lt;a class="link" href="https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/" >Alexa&lt;/a> and &lt;a class="link" href="https://linked365.blog/2019/05/04/ifttt-flow-d365/" >IFTTT&lt;/a>.&lt;/p>
&lt;p>The HR department is ramping up recruitment and new teams are being shaped to support all the growth.&lt;/p>
&lt;p>One of the criticisms from the managers is that it takes a while for the IT / D365 administrators to get users in the correct teams and security roles so they can be effective in D365.&lt;/p>
&lt;p>A clever chap in the management team suggested that they be given an app that would allow a manager to update the roles and teams (and other relevant parts of a user) without resorting to logging into D365 administration. Something they can use wherever they have WiFi or a data connection.&lt;/p>
&lt;p>It would also be good to get a notification when they have a new employee, or someone is added to their reports.&lt;/p>
&lt;h2 id="the-flow">The Flow&lt;/h2>
&lt;p>This flow is quite simple, trigger an email when a user has the Manager field (parentsystemuserid) field updated. O365 will create the user for us (assuming you are in the cloud) and an administrator will still have to update the users manager.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image.png"
loading="lazy"
>&lt;/p>
&lt;p>Here, the attribute I am interested on is parentsystemuserid.&lt;/p>
&lt;p>Next, just check to see if the manager is actually populated. In a lot of businesses, removing their manager is part of the process on off-boarding an employee, to tidy up selection lists etc.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-1.png"
loading="lazy"
>&lt;/p>
&lt;p>Then, get the manager user record from D365 so that the email can be sent to it.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-2.png"
loading="lazy"
>&lt;/p>
&lt;p>Told you it was simple. I am sure that this can have more logic - Do we need an approval step before assigning this user? Do we have to wait for HR to do some work and only activate the user once all the checks are done?&lt;/p>
&lt;p>Next, I&amp;rsquo;ll step through the PowerApps set up to retrieve data from my reports.&lt;/p></description></item></channel></rss>