<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog - Life on Planet Groove - Adam Toth's Blog</title>
	<atom:link href="https://lifeonplanetgroove.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>https://lifeonplanetgroove.com</link>
	<description></description>
	<lastBuildDate>Wed, 18 Feb 2026 16:15:36 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Copilot Studio&#8217;s Generative Orchestrator Has a Memory Problem</title>
		<link>https://lifeonplanetgroove.com/copilot-studios-generative-orchestrator-has-a-memory-problem/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=copilot-studios-generative-orchestrator-has-a-memory-problem</link>
					<comments>https://lifeonplanetgroove.com/copilot-studios-generative-orchestrator-has-a-memory-problem/#respond</comments>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Tue, 17 Feb 2026 07:06:23 +0000</pubDate>
				<category><![CDATA[Copilot Studio]]></category>
		<category><![CDATA[Power Platform]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">https://lifeonplanetgroove.com/?p=1521</guid>

					<description><![CDATA[<p>If you&#8217;ve spent any time building agents in Microsoft Copilot Studio using the generative orchestrator, you&#8217;ve probably run into a frustrating limitation that doesn&#8217;t get talked about enough: it forgets things mid-conversation. Not after hours, or after dozens of turns. Sometimes after just a handful of exchanges. And the reason for this isn&#8217;t exactly clear, [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/copilot-studios-generative-orchestrator-has-a-memory-problem/">Copilot Studio’s Generative Orchestrator Has a Memory Problem</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>If you&#8217;ve spent any time building agents in Microsoft Copilot Studio using the generative orchestrator, you&#8217;ve probably run into a frustrating limitation that doesn&#8217;t get talked about enough: <strong>it forgets things mid-conversation</strong>.</p>



<p>Not after hours, or after dozens of turns. Sometimes after just a handful of exchanges. And the reason for this isn&#8217;t exactly clear, mainly due to Microsoft&#8217;s lack of transparency around a fundamental question: <strong>how much of the model&#8217;s context window is actually available for your conversation</strong>?.</p>



<h2 class="wp-block-heading">What the Generative Orchestrator Does</h2>



<p>For those unfamiliar, the generative orchestrator is the AI brain behind Copilot Studio&#8217;s conversational agents. When a user sends a message, the orchestrator evaluates the input and decides what to do next. It might answer directly from a configured knowledge source (RAG), redirect the user into a static dialog topic, or invoke a tool like a Power Automate flow, a connector, or MCP server tool. It&#8217;s a powerful routing mechanism &#8211; when it works.</p>



<p>The problem is what happens to conversational context as the orchestrator makes those decisions.</p>


<a class="wp-block-read-more local-link" href="https://lifeonplanetgroove.com/copilot-studios-generative-orchestrator-has-a-memory-problem/" target="_self">Read more<span class="screen-reader-text">: Copilot Studio&#8217;s Generative Orchestrator Has a Memory Problem</span></a>


<h2 class="wp-block-heading">The Memory Loss in Action</h2>



<p>Here&#8217;s a reproducible scenario that illustrates the issue perfectly (using the default ChatGPT 4.1 model).</p>



<p>You start a conversation with your copilot and say: <em>&#8220;My nickname is Mittens.&#8221;</em> The orchestrator responds with something like <em>&#8220;Nice to meet you, Mittens!&#8221;</em> — so far, so good. The orchestrator owns the conversation, is retaining some information, and responding naturally, without having to do any retrieval, redirections to topics, or invoking any Tools or Connectors. </p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="588" height="334" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-6.png" alt="" class="wp-image-1530" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-6.png 588w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-6-300x170.png 300w" sizes="(max-width: 588px) 100vw, 588px" /></figure>



<p>You then say <em>&#8220;My favorite team is the Seahawks.&#8221;</em> Again, it acknowledges this and stores it in its working context.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="579" height="161" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-7.png" alt="" class="wp-image-1531" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-7.png 579w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-7-300x83.png 300w" sizes="(max-width: 579px) 100vw, 579px" /></figure>



<p>Now ask it something it has to think on, like &#8220;<em>What is today?</em>&#8220;. No problem, it answers fine.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="584" height="166" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-8.png" alt="" class="wp-image-1532" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-8.png 584w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-8-300x85.png 300w" sizes="(max-width: 584px) 100vw, 584px" /></figure>



<p>At this point, if you were to ask it to recall your nickname, or favorite team, it should have no problem re-stating those items. But let&#8217;s not ask it to recall just yet. </p>



<p>Now give it a larger request, one that fills up the context window a bit, such as &#8220;<em>Generate 500 words of lorem ipsum text.</em>&#8220;.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="580" height="355" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-9.png" alt="" class="wp-image-1533" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-9.png 580w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-9-300x184.png 300w" sizes="auto, (max-width: 580px) 100vw, 580px" /></figure>



<p>Now that the context window has been stuffed, ask it to recall your favorite team. &#8220;<em>What is my favorite team?</em>&#8220;</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="582" height="362" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-10.png" alt="" class="wp-image-1534" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-10.png 582w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-10-300x187.png 300w" sizes="auto, (max-width: 582px) 100vw, 582px" /></figure>



<p>Failure. &#8220;<em>I could not find any information about your favorite team.</em>&#8220;. Ask it to summarize the conversation so far and it can only recall the most recent exchange for the lorem ipsum text. Everything before that has been silently discarded.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="578" height="160" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-11.png" alt="" class="wp-image-1535" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-11.png 578w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-11-300x83.png 300w" sizes="auto, (max-width: 578px) 100vw, 578px" /></figure>



<p>So what happened? It seems that the model generated a response large enough to consume the available context budget, and the earlier conversation turns fell off the edge.</p>



<h2 class="wp-block-heading">Measuring the Gap</h2>



<p>I tested this systematically with the ChatGPT 4.1 model, which has a 32,000-token context window, in a couple of different tenants. ChatGPT 4.1 in some regions and via the API can even have a window of up to 1 million tokens, and you would think that this is what Microsoft would be using and hosting it in Azure OpenAI service. </p>



<p>I established facts at the start of a conversation, then asked the copilot to generate progressively larger blocks of lorem ipsum text before checking recall. I could get it to fail consistently between 500-800 words of extra filler text, plus my initial testing facts at the beginning.</p>



<p>When changing the model to ChatGPT 5 (chat), the context window expanded considerably. <strong>Still, context was reliably lost after approximately 6,000 words of generated filler text</strong> &#8211; roughly 8,000 tokens.</p>



<p>That&#8217;s only about 25% of ChatGPT 5&#8217;s advertised 32k context window. The other 75% is being consumed by something else before your conversation history even gets a seat at the table.</p>



<p>I have no idea why GPT-4.1 model is significantly worse, and unfortunately for sovereign cloud clients like GCC, it is currently the only model option available.</p>



<p>So what&#8217;s eating the rest of the window? On every turn, the model&#8217;s context has to accommodate the copilot&#8217;s system instructions, descriptions for every configured topic, descriptions for every action and plugin, knowledge source configuration and metadata, and the orchestrator&#8217;s own internal planning prompts and scaffolding. That overhead is substantial, and it&#8217;s invisible to you as a builder. Microsoft provides no tooling to inspect how much of your context window is allocated to conversation history versus platform overhead, and no documentation on what that split looks like.</p>



<p><strong>The model&#8217;s advertised context window is not what you&#8217;re getting.</strong> The effective conversation history budget in Copilot Studio appears to be in the single-digit hundreds (ChatGPT 4.1) or thousands (ChatGPT5) of tokens, regardless of what the underlying model supports. And there&#8217;s no way to see, measure, or control this from within the platform.</p>



<h2 class="wp-block-heading">Is This a Cost Optimization?</h2>



<p>It&#8217;s worth asking why the gap is so large. The orchestrator&#8217;s overhead &#8211; instructions, topic descriptions, action metadata — shouldn&#8217;t consume 75% of a 32k token window. Even a copilot with dozens of topics and actions would struggle to fill 24,000 tokens with descriptions alone.</p>



<p>One plausible explanation is that Microsoft is artificially constraining the conversation history window as a cost optimization. Longer context windows mean more tokens processed per API call, which means higher compute costs per turn. By limiting how much conversation history is carried forward, Microsoft reduces the per-turn cost of running the orchestrator &#8211; at the expense of conversational continuity.</p>



<p>If that&#8217;s what&#8217;s happening, it&#8217;s a reasonable business decision. But it should be a transparent one. Builders need to know what they&#8217;re working with so they can design accordingly, rather than discovering through trial and error that their copilot can&#8217;t remember a user&#8217;s name from five turns ago.</p>



<h2 class="wp-block-heading">A Workaround That Proves the Point</h2>



<p>The good news is that you can build a workaround. The bad news is that it requires reimplementing conversation memory from scratch &#8211; and the fact that it works actually proves something is being left on the table.</p>



<p>The approach involves maintaining a rolling conversation summary in a global variable and injecting it back into the orchestrator&#8217;s instructions on every turn.</p>



<h3 class="wp-block-heading">Building the Transcript</h3>



<p>Copilot Studio doesn&#8217;t expose the orchestrator&#8217;s internal conversation history to topic flows. There&#8217;s no <code>System.ConversationHistory</code> variable, and the Generative Answers node runs in its own isolated LLM session with no access to what the orchestrator has been tracking. So you have to build the transcript yourself, turn by turn.</p>



<p>To do this, first initialize a global variable in the <strong>Conversation Start</strong> system topic, called <strong>ConversationHistory</strong>. You can set it&#8217;s initial value to <strong>Blank()</strong>.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="336" height="489" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-12.png" alt="" class="wp-image-1536" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-12.png 336w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-12-206x300.png 206w" sizes="auto, (max-width: 336px) 100vw, 336px" /></figure>



<p>Create a new custom topic, called StoreInputHistory, and change the trigger to &#8220;<strong>A message is received</strong>&#8220;.</p>



<p>Add a Set variable value node after the trigger. Choose the Global.ConversationHistory variable to set, and use the following PowerFx formula:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
Concatenate(Global.ConversationHistory, &quot; | &quot;, &quot;User: &quot;, System.Activity.Text)
</pre></div>


<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="341" height="531" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-14.png" alt="" class="wp-image-1538" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-14.png 341w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-14-193x300.png 193w" sizes="auto, (max-width: 341px) 100vw, 341px" /></figure>



<p>To capture the bot&#8217;s responses, create another custom topic called StoreOutputHistory, and change the trigger to &#8220;<strong>An AI generated response is about to be sent</strong>&#8220;. Also use the Global.ConversationHistory variable, and the following PowerFx formula:</p>



<p>Concatenate(Global.ConversationHistory, &#8221; | &#8220;, &#8220;Bot: &#8220;, System.Response.FormattedText)</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="340" height="520" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-13.png" alt="" class="wp-image-1537" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-13.png 340w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-13-196x300.png 196w" sizes="auto, (max-width: 340px) 100vw, 340px" /></figure>



<h3 class="wp-block-heading">Injecting the Summary</h3>



<p>The copilot&#8217;s <strong>Instructions</strong> field is evaluated fresh on every turn with current variable values. In the Instructions editor, add text like: <em>&#8220;The following is a rolling summary of this conversation. Use it to maintain continuity and remember facts the user has shared.&#8221;</em> Then type <code>/</code> to bring up the variable picker and select your <code>Global.ConversationHistory</code> variable.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="959" height="230" src="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-15.png" alt="" class="wp-image-1539" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-15.png 959w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-15-300x72.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-15-768x184.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-15-940x225.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2026/02/image-15-640x153.png 640w" sizes="auto, (max-width: 959px) 100vw, 959px" /></figure>



<p>The orchestrator now sees the summary in its instructions on every turn. Even when the raw conversation history gets truncated, the key facts survive.</p>



<h3 class="wp-block-heading">Why This Proves Something Is Wrong</h3>



<p>Here&#8217;s the thing: <strong>this workaround works</strong>. After implementing the rolling summary, the orchestrator retains context across long conversations, through topic transitions, through knowledge retrievals, through large responses. The memory problem goes away.</p>



<p>But the summary is being injected into the Instructions &#8211; the same instructions that are part of the orchestrator&#8217;s overhead. If 75% of the context window were truly needed for the orchestrator&#8217;s internal scaffolding, adding a summary variable to the instructions should make things worse by consuming even more of that overhead budget. Instead, it fixes the problem.</p>



<p>This suggests that the conversation history is being truncated more aggressively than the overhead requires. There&#8217;s headroom in the context window that isn&#8217;t being allocated to conversation history, and a short summary variable is enough to fill the gap. That&#8217;s consistent with an artificial constraint on how much history gets carried forward &#8211; not a genuine space limitation.</p>



<h2 class="wp-block-heading">What Builders Need from Microsoft</h2>



<p>Copilot Studio is a powerful platform. The generative orchestrator&#8217;s ability to blend AI reasoning with structured topics and plugin actions is genuinely impressive. But that power is undermined when the orchestrator can&#8217;t maintain basic conversational continuity, and builders have no visibility into why.</p>



<p>What we need is <strong>transparency</strong>. Publish the effective conversation history budget for each model tier. Expose a system variable with the orchestrator&#8217;s conversation transcript. Give builders a configuration option to control the history-to-overhead ratio, even if it comes with cost implications. And if the constraint is a cost optimization, say so &#8211; let builders make an informed decision about the trade-off between cost and conversational quality.</p>



<p>Users expect that if they tell a bot their nickname at the beginning of a conversation, it still knows that nickname five minutes later. That&#8217;s not a power-user expectation &#8211; it&#8217;s the bare minimum. The frustrating thing is that this feels like a problem Copilot Studio should solve out of the box, without workarounds like the one above.</p>



<p>Until then, if you&#8217;re building anything beyond a simple Q&amp;A bot in Copilot Studio, plan and test for memory management from day one. Your users will thank you — assuming your copilot can remember who they are.</p><p>The post <a href="https://lifeonplanetgroove.com/copilot-studios-generative-orchestrator-has-a-memory-problem/">Copilot Studio’s Generative Orchestrator Has a Memory Problem</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://lifeonplanetgroove.com/copilot-studios-generative-orchestrator-has-a-memory-problem/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Advanced Security in Dataverse For Teams via Record Ownership</title>
		<link>https://lifeonplanetgroove.com/advanced-security-in-dataverse-for-teams-via-record-ownership/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=advanced-security-in-dataverse-for-teams-via-record-ownership</link>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Thu, 29 Sep 2022 14:54:34 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Dataverse]]></category>
		<category><![CDATA[Microsoft Teams]]></category>
		<category><![CDATA[Power Platform]]></category>
		<category><![CDATA[PowerApps]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1456</guid>

					<description><![CDATA[<p>Dataverse for Teams is an exciting development platform that lets you get apps quickly into your user&#8217;s hands, and surfaced directly where they are doing most of their collaboration &#8211; inside the Microsoft Teams client. Dataverse for Teams is a subset of standalone Dataverse in the Power Platform, and while it has many of the [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/advanced-security-in-dataverse-for-teams-via-record-ownership/">Advanced Security in Dataverse For Teams via Record Ownership</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Dataverse for Teams is an exciting development platform that lets you get apps quickly into your user&#8217;s hands, and surfaced directly where they are doing most of their collaboration &#8211; inside the Microsoft Teams client.</p>



<p>Dataverse for Teams is a subset of standalone Dataverse in the Power Platform, and while it has many of the main characteristics of Dataverse, there are some features that are scaled back or simplified, especially with regards to advanced security configurations. The inability to create custom Security Roles, no Record Sharing capability, and the simplified permission sets available (Full Control, Collaborate, Reference, Private, None) make it harder to create custom roles and permission levels that don&#8217;t directly correspond to the Owners/Members/Guests hierarchy. For example, maybe you want to expose table data to your external partners who you invite to your Teams as external Guest users, and you want each partner organization to view their own organization&#8217;s records but not see or edit records from other organizations. The simplified permissions in Dataverse for Teams make it difficult to achieve this, as all the users will be treated as &#8220;Guests&#8221; collectively and assigned the same permission levels that all Guests are assigned to the tables, and you don&#8217;t have a mechanism to further group these users beyond Owners/Members/Guests. This post will show you a creative way to achieve this using record ownership instead of custom security roles.</p>



<p>The quick summary &#8211; you can create custom &#8220;Teams&#8221; in Dataverse for Teams (just like in standalone), and assign record ownership to a Team instead of an individual user, and thereby create another hierarchical layer of permissions. Read on to understand the backstory more, or <a href="#Solution">jump ahead</a> to see how to do it.</p>



<span id="more-1456"></span>



<h3 class="wp-block-heading">Overview of Dataverse Security and Permissions</h3>



<p>Before getting started, take some time to review the official documentation for how security works in Dataverse, I&#8217;ve highlighted some key links below:</p>



<ul class="wp-block-list"><li><a href="https://learn.microsoft.com/en-us/power-platform/admin/wp-security" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Security in Microsoft Dataverse</a></li><li><a href="https://learn.microsoft.com/en-us/power-platform/admin/wp-security-cds" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Security Concepts in Microsoft Dataverse</a></li><li><a href="https://learn.microsoft.com/en-us/power-platform/admin/security-roles-privileges" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Security Roles and Privileges</a></li><li><a href="https://learn.microsoft.com/en-us/power-apps/teams/data-platform-compare" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Compare Dataverse and Dataverse for Teams</a></li></ul>



<p>At the core of standalone Dataverse is a hierarchical role-based permissioning system where you can define named Roles, assign users to those Roles, and then assign specific permissions to Dataverse resources (Tables, Rows in those Tables, and even Columns) to those Roles. These objects are actually stored in Dataverse tables, with many to many relationships between these objects. A crude representation of this is below:</p>



<ul class="wp-block-list"><li>[Users] &lt;-&gt; [Security Roles] &lt;-&gt; [Privileges] &lt;-&gt; [Resource]</li></ul>



<p>There is even a concept of a grouping mechanism, to which you can assign users, and then assign that group to the Security Role. This custom group is called a &#8220;Team&#8221; in Dataverse, and lives in a table called &#8220;Teams&#8221;. So we can update the mapping above to show that you can either assign users directly to roles, or assign them to a Team, and then assign the Team to a role:</p>



<ul class="wp-block-list"><li>[Users] &lt;-&gt; [Security Roles] &lt;-&gt; [Privileges] &lt;-&gt; [Resource]</li><li>[Users] &lt;-&gt; [Teams] &lt;-&gt; [Security Roles] &lt;-&gt; [Privileges] &lt;-&gt; [Resource]</li></ul>



<p>If you are familiar with SharePoint and SharePoint permissions, this ad-hoc group is very similar to a SharePoint Group. You can create these groups (Teams) yourself, and you can either add users individually to them, or link them to Azure AD Security Groups or M365 Groups (these are called &#8220;<a href="https://learn.microsoft.com/en-us/power-platform/admin/manage-group-teams" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Group Teams</a>&#8220;).</p>



<p>Here is where it gets confusing, and where the nomenclature is going to bite me, so I&#8217;ll try and lay out the terminology I&#8217;ll use for the rest of this post to hopefully avoid confusion.</p>



<p><strong>&#8220;Microsoft Teams&#8221; Team</strong> &#8211; This is a Team created in the Microsoft Teams client, that is used for collaboration. It has Owners, Members, and Guests roles, and has channels and tabs for chat and access to Teams related apps. </p>



<p><strong>&#8220;Dataverse&#8221; Team</strong> &#8211; This is a record inside of a Dataverse database table called &#8220;Teams&#8221;. This record represents a custom or built-in group that you can leverage for permissions. Official doc links for this: </p>



<ul class="wp-block-list"><li><a href="https://learn.microsoft.com/en-us/power-platform/admin/wp-security-cds#teams-including-group-teams" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Teams (and Group Teams)</a></li><li><a href="https://learn.microsoft.com/en-us/power-platform/admin/manage-teams" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Microsoft Dataverse Teams Management</a></li></ul>



<p><strong>Dataverse for Teams (DVFT)</strong> &#8211; A dedicated Power Platform environment and Dataverse database for a specific <strong>&#8220;Microsoft Teams&#8221; Team</strong>, in which you can store data, Power Apps, Power Automate workflows, and Power Virtual Agent chatbots. This environment/database is linked to it&#8217;s <strong>&#8220;Microsoft Teams&#8221; Team</strong> lifecycle &#8211; it is created when the first Power Platform asset is created within the <strong>&#8220;Microsoft Teams&#8221; Team</strong>, and deleted when the linked <strong>&#8220;Microsoft Teams&#8221; Team</strong> is deleted.</p>



<h3 class="wp-block-heading">The Problem</h3>



<p>If you look at the <a href="https://learn.microsoft.com/en-us/power-apps/teams/data-platform-compare#security" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">detailed comparison on security between Dataverse for Teams (DVFT) and standalone Dataverse</a>, you&#8217;ll see a number of differences, most importantly:</p>



<ul class="wp-block-list"><li>No Record Sharing</li><li>No hierarchical security</li><li>Cannot create custom User Roles, and are limited to the default Teams Owners/Members/Guests roles (we call this the OMG pattern)</li><li>Are limited to just one Business Unit (means you can&#8217;t create an organizational hierarchy structure for permissioning)</li></ul>



<p>These differences, combined with a limited set of privilege levels makes it very hard to create customized roles and groups within your DVFT applications for more advanced security implementations.</p>



<p>The default privilege levels in DVFT are as follows:</p>



<ul class="wp-block-list"><li><strong>Full access</strong>&nbsp;– Allows end users to see and edit all records in the table.</li><li><strong>Collaborate</strong>&nbsp;– Allows end users to see all records, but they can only edit their own records.</li><li><strong>Reference</strong>&nbsp;– Provides a read-only view of data for end users.</li><li><strong>Private</strong>&nbsp;­– Allows end users to only view and edit their own data.</li></ul>



<p>What a lot of my customers are looking for is a way to create custom groups of users within DVFT, assign users to those groups, and let anyone in a particular group see just the records for that group, and not other groups. With the privilege levels above, Collaborate, Reference, and Private would not work because those would either give read access to all records, or give Read/Edit access to only records directly owned (created) by the individual user. </p>



<p>To accomplish these requirements, it would seem that we need to give all guest users Full Access permissions, and just filter what they see and access in the UI using Filter() formulas and PowerFx logic. But this is certainly error-prone, and if a developer in the future forgets to filter some data properly, then data could be leaked across organizations/roles.</p>



<p>What we need is a way to create custom groups and have the group own the record, so that true security trimming is in place, not just filtering. This is where custom <strong>&#8220;Dataverse&#8221; Teams</strong> and record ownership come in.</p>



<h3 class="wp-block-heading" id="Solution">The Solution &#8211; Custom &#8220;Dataverse&#8221; Teams and Record Ownership</h3>



<p>Now, for what I am going to show you next, there is no pre-built, pretty user interface for managing <strong>&#8220;Dataverse&#8221; Teams</strong> and changing record ownership, but the capabilities are all there to do this from Power Apps or Power Automate workflows that you build in DVFT.</p>



<p>To start with, I&#8217;m going to walk through how to create a custom <strong>&#8220;Dataverse&#8221; Team</strong>. Since these are stored in a table called Teams, I&#8217;m just going to create a new Power App in DVFT, and add the Teams table as a Data Source (Start this screen&#8230; with data).</p>



<p>Here I am creating a new app and naming it:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="492" height="258" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image.png" alt="" class="wp-image-1458" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image.png 492w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-300x157.png 300w" sizes="auto, (max-width: 492px) 100vw, 492px" /><figcaption>Creating a new app</figcaption></figure>



<p>When the app loads up, I&#8217;ll choose the first option to Start this screen &#8230; With data:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="391" height="192" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-1.png" alt="" class="wp-image-1459" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-1.png 391w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-1-300x147.png 300w" sizes="auto, (max-width: 391px) 100vw, 391px" /><figcaption>Choosing Start&#8230; With Data</figcaption></figure>



<p>When asked to Select a data source, I&#8217;ll type Teams in the search box and choose the Teams table:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="350" height="454" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-2.png" alt="" class="wp-image-1460" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-2.png 350w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-2-231x300.png 231w" sizes="auto, (max-width: 350px) 100vw, 350px" /><figcaption>Choosing the Teams table as a data source</figcaption></figure>



<p>Once the screen is created, you&#8217;ll see that you are browsing the records in the Teams table directly. One potentially confusing thing is your Datasource will get named &#8220;Teams_1&#8221; in the app. This is so that it doesn&#8217;t collide with the <a href="https://learn.microsoft.com/en-us/power-apps/teams/use-teams-integration-object" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Teams Integration control</a> that is added to every DVFT Power App which is already named &#8220;Teams&#8221;. In Power Apps every control needs a unique name.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="280" height="296" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-6.png" alt="" class="wp-image-1464"/><figcaption>The Teams Integration control is found on all DVFT Power Apps. Since it is named &#8220;Teams&#8221;, our data source can&#8217;t be named &#8220;Teams&#8221;, so it gets renamed to &#8220;Teams_1&#8221;.</figcaption></figure>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="289" height="280" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-11.png" alt="" class="wp-image-1470"/></figure>



<p>On the newly created screen you&#8217;ll see a few default teams in the gallery there. The one that is named the same as your <strong>&#8220;Microsoft Teams&#8221; Team</strong> is for Collegues with Access when you share your Power App with other collegues. The Team with the orgXYZ prefix is the single Business Unit you are allocated in DVFT (you aren&#8217;t allowed to create additional business units). And you&#8217;ll also see Teams Owners, Teams Members, and Teams Guests. These last 3 are &#8220;Group Teams&#8221;, linked to the Azure AD M365 group that backs your <strong>&#8220;Microsoft Teams&#8221; Team</strong>. </p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="458" height="279" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/Teams-List.png" alt="" class="wp-image-1500" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/Teams-List.png 458w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/Teams-List-300x183.png 300w" sizes="auto, (max-width: 458px) 100vw, 458px" /></figure>



<p>To see some more details about the groups, I will edit the <strong>EditForm </strong>control to show a few additional fields about the selected Team, including &#8220;Team Type&#8221; and &#8220;Membership Type&#8221;:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="693" height="391" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-3.png" alt="" class="wp-image-1461" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-3.png 693w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-3-300x169.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-3-640x361.png 640w" sizes="auto, (max-width: 693px) 100vw, 693px" /></figure>



<p>Now that I&#8217;ve added those fields, we can see the Team Type is AAD Office Group, and the Membership Type is one of either Owners, Members, Guests, or Members and Guests.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="968" height="280" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-4.png" alt="" class="wp-image-1462" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-4.png 968w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-4-300x87.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-4-768x222.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-4-940x272.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-4-640x185.png 640w" sizes="auto, (max-width: 968px) 100vw, 968px" /></figure>



<p>To create a custom team, the only required fields are these three &#8211; Team Name, Team Type, and Membership Type. I&#8217;ll just use the <strong>New record</strong> button to create a new team called Contoso, and another called Fabrikam. For Team Type, you need to choose &#8220;Owner&#8221;, and for Membership Type I am going to choose &#8220;Members and Guests&#8221; (no matter what you set it to, the only option that will save is &#8220;Members and Guests&#8221;). You can see my newly created <strong>&#8220;Dataverse&#8221; Teams</strong> below:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="288" height="455" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-5.png" alt="" class="wp-image-1463" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-5.png 288w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-5-190x300.png 190w" sizes="auto, (max-width: 288px) 100vw, 288px" /></figure>



<p>Now that I have some Teams created, I am going to assign users from the <strong>Users </strong>table to the <strong>Team</strong>. This can easily be done using the <a href="https://learn.microsoft.com/en-us/power-platform/power-fx/reference/function-relate-unrelate" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Relate/Unrelate Power Apps functions</a> (or the <strong>Relate</strong>/<strong>Unrelate </strong>a Record actions in Power Automate). Users to Teams table relationship is Many-To-Many, so you can&#8217;t use <strong>Patch </strong>or <strong>EditForm </strong>to set this. To accomplish this, I am going to add a gallery underneath the current <strong>EditForm </strong>control to display related Users to the selected Team, and then a <strong>ComboBox </strong>and <strong>Button </strong>to select users and <strong>Relate </strong>them to the team. I&#8217;ll also add a Delete button on the gallery to <strong>Unrelate</strong>. The <strong>Items </strong>property of the new gallery will just traverse the relationship from the selected <strong>Team </strong>in the main left gallery:</p>



<pre class="wp-block-code"><code>BrowseGallery1.Selected.Users</code></pre>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="497" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-7-1024x497.png" alt="" class="wp-image-1465" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-7-1024x497.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-7-300x146.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-7-768x373.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-7-940x456.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-7-640x311.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-7.png 1145w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p> For the <strong>ComboBox</strong>, I am going to set the Items property to the <strong>Users </strong>table in Dataverse, and <strong>Allow Searching</strong>:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="528" height="303" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-8.png" alt="" class="wp-image-1466" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-8.png 528w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-8-300x172.png 300w" sizes="auto, (max-width: 528px) 100vw, 528px" /></figure>



<p>For the button, I&#8217;ll use the following formula for <strong>OnSelect</strong>:</p>



<pre class="wp-block-code"><code>Relate(BrowseGallery1.Selected.Users, ComboBox2.Selected)</code></pre>



<p>And lastly, for the delete button in the gallery, I&#8217;ll use the following formula to <strong>Unrelate </strong>the record:</p>



<pre class="wp-block-code"><code>Select(Parent);Unrelate(BrowseGallery1.Selected.Users,ThisItem)</code></pre>



<p>You can see in the picture below the user that has been related to the selected Contoso team:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="970" height="324" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-9.png" alt="" class="wp-image-1467" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-9.png 970w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-9-300x100.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-9-768x257.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-9-940x313.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-9-640x213.png 640w" sizes="auto, (max-width: 970px) 100vw, 970px" /></figure>



<p>You can make this UI more advanced and user friendly, but for now I&#8217;m keeping it simple to demonstrate the concept.</p>



<p>Now that I&#8217;ve created a custom Team and assigned a user to it, there is one final thing that needs to be done before changing record ownership to the Team. In order to assign a <strong>&#8220;Dataverse&#8221; Team</strong> as the owner of a record, it must have Read permissions to the table (it would make no sense to assign an Owner that couldn&#8217;t even read the record). Right now, my newly created group does not have any explicit or implicit permissions to any of the tables in Dataverse. To give it access, I will relate the <strong>&#8220;Dataverse&#8221; Team</strong> to one of the pre-existing Security Roles, namely &#8220;Teams Guest&#8221;. Each DVFT environment comes with several pre-existing Security Roles, including &#8220;Teams Owner&#8221;, &#8220;Teams Member&#8221;, and &#8220;Teams Guest&#8221;. When you assign Table permissions within the DVFT UI, you are actually assigning one of these 3 security roles one of the privilege levels to the table. The UI filters out all the other system-generated roles like sysadmin, system customizer, etc. Those roles are there, but you are not allowed to create additional roles or see these other roles in the UI.</p>



<p>To accomplish this, I will create another screen in my application to browse the <strong>Security Roles</strong>, and a similar Gallery/ComboBox implementation to browse related Teams and relate a team to the role. I&#8217;ll choose to create a <strong>New Screen &gt; Blank Screen &gt; Start with Data</strong> &gt; and choose the <strong>Security Roles</strong> Table.</p>



<p>For my new gallery Items property I will set it to:</p>



<pre class="wp-block-code"><code>BrowseGallery2.Selected.Teams</code></pre>



<p>And for my <strong>ComboBox</strong>, the <strong>Datasource </strong>(<strong>Items </strong>Property) will be set to &#8220;Teams_1&#8221; and I will allow searching. For the <strong>Add Team</strong> button, I will use a similar <strong>Relate </strong>formula:</p>



<pre class="wp-block-code"><code>Relate(BrowseGallery2.Selected.Teams, ComboBox3.Selected)</code></pre>



<p>Here I am showing the newly related Contoso Team:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="836" height="262" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-10.png" alt="" class="wp-image-1468" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-10.png 836w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-10-300x94.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-10-768x241.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-10-640x201.png 640w" sizes="auto, (max-width: 836px) 100vw, 836px" /></figure>



<h3 class="wp-block-heading">Changing Record Ownership</h3>



<p>Now that I have a custom Team record in place, a user associated to the Team, and I&#8217;ve given the Team a security role, I can now assign records to have the Team as an owner instead of the original Created By user. </p>



<p>If you are unfamiliar with record ownership in Dataverse, every table in Dataverse has a column named <strong>Owner</strong>. This column can store a reference to either a User or a Team or even a Business Unit. Usually the <strong>Owner </strong>is set to the original creator of the row (the person listed in the <strong>Created By</strong> column), but it can be changed, and set to a different user, or also to a <strong>&#8220;Dataverse&#8221; Team</strong>.</p>



<p>To set the <strong>Owner </strong>field in Canvas Apps, you need to use a <strong>Patch()</strong> formula (<a href="https://powerapps.microsoft.com/hi-in/blog/owner-customer-and-regarding-for-canvas-apps/" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">see this great article for more details</a>), <s>as the <strong>EditForm </strong>control locks the <strong>Owner </strong>field from editing</s>.</p>



<p><strong>UPDATE 11/2/2022</strong>: Actually, you don&#8217;t have to use the <strong>Patch </strong>formula, you can also set the <strong>Owner </strong>field from an <strong>EditForm </strong>control. Add the field <strong>Owner </strong>to the <strong>EditForm </strong>control. It will add an empty <strong>DataCard </strong>to your form. To update the ownership, set the <strong>Update </strong>property of the DataCard to the &#8220;Dataverse&#8221; Team record that you want to be the owner of the record, for example <strong>Lookup(Teams_1, &#8216;Team Name&#8217;=&#8221;MyTeamName&#8221;)</strong>. In this way, you can change ownership directly to the team at time of record creation (<strong>FormMode.New</strong>) or during update (<strong>FormMode.Edit</strong>). </p>



<p>To demonstrate this, I am going to create another blank screen, and this time start from a new table. I&#8217;ll create a a table called &#8220;<strong>Discount Codes</strong>&#8220;. In this scenario, I am inviting my Resellers to come into my app and create trackable discount codes for use when reselling my products. I only want users to see their own organization&#8217;s discount codes, not any others.</p>



<p>I&#8217;ll create the custom table &#8220;<strong>Discount Codes</strong>&#8221; with two fields, <strong>Name </strong>(Text), and <strong>Expiration Date</strong> (Date). I&#8217;ll also add the Owner column in the default view so that we can see the values there.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="741" height="347" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-13.png" alt="" class="wp-image-1472" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-13.png 741w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-13-300x140.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-13-640x300.png 640w" sizes="auto, (max-width: 741px) 100vw, 741px" /><figcaption>I will also add a couple of rows to start with. Notice the <strong>Owner </strong>field is set to an individual.</figcaption></figure>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="747" height="286" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-14.png" alt="" class="wp-image-1473" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-14.png 747w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-14-300x115.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-14-640x245.png 640w" sizes="auto, (max-width: 747px) 100vw, 747px" /></figure>



<p>Once done editing the table, back on the canvas app screen I&#8217;m also going to change the <strong>EditForm </strong>control so it displays <strong>Owning User</strong>, <strong>Owning Team</strong>, and <strong>Owning Business Unit</strong> values, just so you can see this.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="836" height="179" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-15.png" alt="" class="wp-image-1474" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-15.png 836w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-15-300x64.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-15-768x164.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-15-640x137.png 640w" sizes="auto, (max-width: 836px) 100vw, 836px" /></figure>



<p>For now, just to prove that I can indeed change ownership, I am going to place a ComboBox and Button in order to manually change ownership to my Contoso or Fabrikam team I created earlier.</p>



<p>The <strong>ComboBox Items </strong>will be bound to the <strong>Teams_1</strong> data source (Teams Table), and the Button&#8217;s <strong>OnSelect </strong>will look like this:</p>



<pre class="wp-block-code"><code>Patch('Discount Codes', BrowseGallery3.Selected, {Owner:ComboBox4.Selected})</code></pre>



<p>You can see that after I select Contoso from the ComboBox and click the button, that ownership is reset to the Team instead of the individual user (<strong>Owning Team</strong> is now Contoso, and <strong>Owning User</strong> is empty):</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="826" height="268" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-16.png" alt="" class="wp-image-1475" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-16.png 826w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-16-300x97.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-16-768x249.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-16-640x208.png 640w" sizes="auto, (max-width: 826px) 100vw, 826px" /></figure>



<p>I&#8217;ve gone ahead and assigned one record to Contoso, and the other to Fabrikam. </p>



<p>Now, I&#8217;ll move this screen up to the top of the Tree View so it becomes the Start Screen for the application. Before I log on with an external guest account and verify the permissions, I am going to check the Table permissions on my custom <strong>Discount Codes</strong> table to make sure they are correct. I will save and Publish my app to the <strong>General </strong>channel in the team first, and then go to the <strong>Build </strong>tab of the Power Apps App, and open up my table for editing. You can see that on my table, <strong>Team Members</strong> have <strong>Full access</strong>, and <strong>Guests </strong>have <strong>Private </strong>permissions (which means an external guest should only be able to see and edit their own rows.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="947" height="605" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-17.png" alt="" class="wp-image-1476" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-17.png 947w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-17-300x192.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-17-768x491.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-17-940x601.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-17-640x409.png 640w" sizes="auto, (max-width: 947px) 100vw, 947px" /></figure>



<p>Now I will login to the Team as an external user that is a member of the Contoso custom Team I created, and I should only see SpookyFall2022 discount code, which is indeed what I see:</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="370" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2022/09/image-18-1024x370.png" alt="" class="wp-image-1477" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-18-1024x370.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-18-300x108.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-18-768x278.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-18-940x340.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-18-640x231.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2022/09/image-18.png 1153w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The great part about this is I am now relying on actual security to trim the rows, as opposed to a developer just filtering things via queries. It is now impossible for a user who is associated with one <strong>&#8220;Dataverse&#8221; Team</strong>, to see records owned by other Teams (or other Users) as long as ownership is setup properly.</p>



<h3 class="wp-block-heading">Summary and Closing Thoughts</h3>



<p>In this post I&#8217;ve shown how you can create custom <strong>&#8220;Dataverse&#8221; Team</strong> records, associate users to those teams, and then assign record ownership to the custom teams in order to get advanced layers of security in your Dataverse for Teams apps, instead of granting overly broad permissions and relying on crude filtering for security.</p>



<p>Using this approach, you will still need to manage the process of changing record ownership yourself. Records created will always be assigned ownership to the original user that created the record by default. But you can do this with additional formulas that execute after <strong>Patch()</strong> or <strong>SubmitForm()</strong> statements, or you can even automate this by creating a Power Automate workflow triggered when Rows are Added to the table, that does the reassignment automatically. Even if the reassignment fails temporarily, the worst that will happen is the record will only be visible to the creator instead of to the broader members of the custom <strong>&#8220;Dataverse&#8221; Team</strong>, so no data will be leaked.</p>



<p>If you like this approach or have comments or questions on it, please leave a comment in the thread below. Thanks for reading!</p>



<p></p><p>The post <a href="https://lifeonplanetgroove.com/advanced-security-in-dataverse-for-teams-via-record-ownership/">Advanced Security in Dataverse For Teams via Record Ownership</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PowerApps TextInput Number Mask Component</title>
		<link>https://lifeonplanetgroove.com/powerapps-textinput-number-mask-component/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=powerapps-textinput-number-mask-component</link>
					<comments>https://lifeonplanetgroove.com/powerapps-textinput-number-mask-component/#comments</comments>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Wed, 17 Nov 2021 06:03:32 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[PowerApps]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1425</guid>

					<description><![CDATA[<p>Inspired by a great and creative solution by Matthew Devaney for creating number input masks for TextInputs, I wanted to see if I could turn this into a reusable component for easier consumption. Read on to see the solution. Overview I am continually amazed at the creativity coming from the low-code/no-code space these days, and [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/powerapps-textinput-number-mask-component/">PowerApps TextInput Number Mask Component</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Inspired by a great and creative solution by Matthew Devaney for creating number input masks for TextInputs, I wanted to see if I could turn this into a reusable component for easier consumption. Read on to see the solution.</p>



<span id="more-1425"></span>



<h3 class="wp-block-heading">Overview</h3>



<p>I am continually amazed at the creativity coming from the low-code/no-code space these days, and a post by <a href="https://matthewdevaney.com/" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Matthew Devaney</a> today gave me some inspiration to build on the solution and make a component out of it for easier consumption. In short, Matthew made a slick solution for applying a number formatting mask to a Text Input control as the user types in it. </p>



<p>First of all, you should go read Matthew&#8217;s post <a href="https://matthewdevaney.com/powerapps-phone-number-formatting-for-any-country-input-mask/" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Power Apps Phone Number Formatting For Any Country (Input Mask)</a> for the underlying concepts and technique for accomplishing the number mask feature. Once you&#8217;ve read that post, come back here to see how to turn it into a reusable component. Components make things much more consumable by app authors, and if you want a primer on Components you can read for following links:</p>



<ul class="wp-block-list"><li><a href="https://docs.microsoft.com/en-us/powerapps/maker/canvas-apps/create-component" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Create a component for canvas apps &#8211; Power Apps | Microsoft Docs</a></li><li><a href="https://grey-frog-177824.hostingersite.com/powerapps-reusable-components/" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">PowerApps Reusable Components &#8211; Life on Planet Groove</a></li></ul>



<h3 class="wp-block-heading">Creating the Component</h3>



<p>To make the input number mask more easily consumable, I am going to show how to make use of PowerApps Components. This will enable app authors to add input mask capabilities multiple times on a single screen or on other screens in an app with a lot less manual configuration, as the bulk of the logic formulas are encapsulated in the Component and don&#8217;t need to be constantly copy/pasted every time you need to use it.</p>



<p>My goal is to be able to easily insert a number mask component next to each TextInput that needs to be masked, and then set a few properties on the Component and TextInput to link them together and get the functionality. No cut/copy/paste of any complex formulas necessary.</p>



<p>To start with, I am going to create a new Component by clicking the Components tab in the left tree view area, and choosing + New Component.</p>



<p>I&#8217;ll name the Component &#8220;InputNumberMask&#8221;. I&#8217;ll set the default Width to something relatively small like 135, and height to 35.</p>



<p>Next, I&#8217;ll Insert a Label and a Slider. I&#8217;ll set their X and Y positions both to 0, and their Width and Height properties to Parent.Width and Parent.Height.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="298" height="248" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-3.png" alt="" class="wp-image-1429"/></figure>



<h3 class="wp-block-heading">Adding Custom Properties</h3>



<p>Next, I&#8217;ll add some input and output properties to my control, which will be used to set the desired number mask and supply the input text to mask, and will return the output masked text and a max length number.</p>



<p>First I&#8217;ll add an input property of Type Text called &#8220;NumberMask&#8221;. This will be the desired mask format that a user will configure. A key option when setting this property up is to check the box to <strong>Raise OnReset when value changes</strong> (you&#8217;ll see why in a moment).</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="319" height="773" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-2.png" alt="" class="wp-image-1428" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-2.png 319w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-2-124x300.png 124w" sizes="auto, (max-width: 319px) 100vw, 319px" /></figure>



<p>Next I&#8217;ll add an input property of Type Text called &#8220;TextToMask&#8221;. This will be the text that is typed into the TextInput that needs to have the mask applied to it.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="322" height="771" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-1.png" alt="" class="wp-image-1427" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-1.png 322w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-1-125x300.png 125w" sizes="auto, (max-width: 322px) 100vw, 322px" /></figure>



<p>Next, I&#8217;ll add another property of type Behavior. These are new and still in Preview/Experimental phase, but they enable creating behavior/event properties like OnChange, OnSelect, etc. To enable this, I&#8217;ll have to go to the <strong>File </strong>menu, choose <strong>Settings</strong>, <strong>Upcoming Features</strong>, and under <strong>Experimental </strong>enable the <strong>Enhanced Component Properties</strong> feature. </p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="976" height="632" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-4.png" alt="" class="wp-image-1430" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-4.png 976w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-4-300x194.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-4-768x497.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-4-940x609.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-4-640x414.png 640w" sizes="auto, (max-width: 976px) 100vw, 976px" /></figure>



<p>With components, in general you can&#8217;t reference controls directly between components and screens, you can only pass input/output variables  I&#8217;ll need some way of calling <strong>Reset()</strong> to reset the value in my <strong>TextInput</strong>, and since I can&#8217;t pass in a Control as an input parameter, I&#8217;ll instead raise a custom event from within the component. I&#8217;ll add this last property as a Behavior type, call it <strong>OnChange</strong>, and set the Type to <strong>Boolean</strong>.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="317" height="777" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-5.png" alt="" class="wp-image-1431" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-5.png 317w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-5-122x300.png 122w" sizes="auto, (max-width: 317px) 100vw, 317px" /></figure>



<p>Finally I&#8217;ll add two output properties. The first one will be named &#8220;FormattedText&#8221;, be type Text, and will contain the final text value with mask applied.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="320" height="611" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-11.png" alt="" class="wp-image-1437" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-11.png 320w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-11-157x300.png 157w" sizes="auto, (max-width: 320px) 100vw, 320px" /></figure>



<p>And the last property is a convenience one, &#8220;MaxLength&#8221;, type Number, which will just be the total Length of the FormattedText, so you can set the MaxLength of your TextInput equal to this.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="321" height="612" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-12.png" alt="" class="wp-image-1438" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-12.png 321w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-12-157x300.png 157w" sizes="auto, (max-width: 321px) 100vw, 321px" /></figure>



<h3 class="wp-block-heading">Configuring the Slider and Component with Masking Formulas</h3>



<p>Now that the properties are configured, I can port over Matthew&#8217;s formulas into the Slider control and Component properties. I&#8217;ll select the <strong>Slider </strong>control, and set the <strong>Default </strong>property of the Slider equal to <code><strong>Len(Parent.TextToMask)</strong></code>. </p>



<p>In the OnChange of the Slider, I&#8217;ll use Matthew&#8217;s code as is, except I&#8217;ll change the MatchAll function to grab from Parent.TextToMask property instead of directly from the TextInput:</p>



<pre class="wp-block-code"><code>Set(
    varFormattedNumber,
    With(
        {
            varTextNumbersOnly: Concat(
                MatchAll(
                    Parent.TextToMask,
                    Match.Digit
                ),
                FullMatch
            )
        },
        Text(
            Value(varTextNumbersOnly),
            LookUp(
                colNumberFormat,
                CountNumbers = Len(varTextNumbersOnly),
                NumberFormat
            )
        )
    )
);
Parent.OnChange()</code></pre>



<p>Note with the code above, we are creating/updating a variable, <strong>varFormattedNumber</strong>, to store the output masked text every time the Slider changes (which is every keypress of the TextInput). Also note the added line at the bottom to raise the component&#8217;s custom <strong>OnChange </strong>event.</p>



<p>Next, I&#8217;ll select the Component itself. In the <strong>OnReset </strong>property, I&#8217;ll paste the other big block of Matthew&#8217;s that is responsible for creating the Collection of mask characters. Again, minimal changes are needed, and I&#8217;ll just grab the mask from the Component&#8217;s property directly (<strong>Self.NumberMask</strong>):</p>



<pre class="wp-block-code"><code>ClearCollect(
    colNumberFormat,
    With(
        {varTextNumberFormat: Self.NumberMask},
        With(
            {
                varTableNumberFormat: ForAll(
                    Sequence(Len(varTextNumberFormat)),
                    With(
                        {
                            varNumberCurrentLength: Left(
                                varTextNumberFormat,
                                Value
                            )
                        },
                        {
                            NumberFormat: varNumberCurrentLength,
                            CountNumbers: CountRows(
                                MatchAll(
                                    varNumberCurrentLength,
                                    "#"
                                )
                            )
                        }
                    )
                )
            },
            ForAll(
                Sequence(
                    Max(
                        varTableNumberFormat,
                        CountNumbers
                    )
                ),
                LookUp(
                    varTableNumberFormat,
                    CountNumbers = Value
                )
            )
        )
    )
)</code></pre>



<p>Note that this <strong>OnReset </strong>event will be triggered every time a consumer of the component sets or changes the <strong>NumberMask </strong>property (which is why it was important earlier to <strong>Raise the OnReset</strong> event for this property). The component needs some event to fire in order to create the collection/table of mask characters, and the <strong>OnReset </strong>of the control is a perfect place to do that.</p>



<p>Next, I&#8217;ll change the <strong>MaxLength </strong>property on the component so that it defaults to <code><strong>Len(Self.NumberMask)</strong></code>.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="588" height="43" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-10.png" alt="" class="wp-image-1436" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-10.png 588w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-10-300x22.png 300w" sizes="auto, (max-width: 588px) 100vw, 588px" /></figure>



<p>Then I&#8217;ll change the <strong>FormattedText </strong>output property to <code><strong>varFormattedNumber</strong></code>.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="585" height="46" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-9.png" alt="" class="wp-image-1435" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-9.png 585w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-9-300x24.png 300w" sizes="auto, (max-width: 585px) 100vw, 585px" /></figure>



<p>Finally, I&#8217;ll set the Slider <strong>Visible </strong>property to <strong>False</strong>, and set my Label&#8217;s <strong>Text </strong>property to <code><strong>Parent.NumberMask</strong></code>. This last part is just so that at design time a developer can see this component visually initially. After configuration, the consumer can set the Visible property of the Component itself to False so nothing actually shows in the UI.</p>



<h3 class="wp-block-heading">Consuming the Component</h3>



<p>To use the Component, I&#8217;ll go back to the <strong>Screen </strong>tab on the <strong>Treeview</strong>, and I&#8217;ll Insert a <strong>TextInput </strong>control on my canvas, and then also insert an instance of my <strong>InputNumberMask </strong>component right next to the <strong>TextInput</strong>.</p>



<p>To wire these two up together, I&#8217;ll select the <strong>Component </strong>and set the <strong>NumberMask </strong>property to whatever mask format I want, for example for US phone numbers it would be &#8220;(###) ###-####&#8221; or for US social security numbers &#8220;###-##-####&#8221;. Another cool idea is to set this mask string as the <strong>HintText </strong>property on your <strong>TextInput </strong>control, and then point the <strong>NumberMask </strong>property on the component to the <strong>HintText </strong>(<strong>TextInput1.HintText</strong>). This way your users will see a little placeholder in the <strong>TextInput </strong>with what the mask will look like.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="574" height="42" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-8.png" alt="" class="wp-image-1434" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-8.png 574w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-8-300x22.png 300w" sizes="auto, (max-width: 574px) 100vw, 574px" /></figure>



<p>For the <strong>TextToMask </strong>property, I&#8217;ll set it equal to the <strong>.Text</strong> property of my <strong>TextInput </strong>(in this case it is <strong>TextInput1.Text</strong>).</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="555" height="48" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-7.png" alt="" class="wp-image-1433" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-7.png 555w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-7-300x26.png 300w" sizes="auto, (max-width: 555px) 100vw, 555px" /></figure>



<p>Lastly, I&#8217;ll set the <strong>OnChange </strong>property of the component to <code><strong>Reset(TextInput1)</strong></code>.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="593" height="49" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/image-6.png" alt="" class="wp-image-1432" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-6.png 593w, https://lifeonplanetgroove.com/wp-content/uploads/2021/11/image-6-300x25.png 300w" sizes="auto, (max-width: 593px) 100vw, 593px" /></figure>



<p>Now I&#8217;ll set a couple properties on the <strong>TextInput </strong>itself. First, I&#8217;ll change its <strong>Default </strong>property to my Component&#8217;s output property, <strong>FormattedText </strong>(<strong>InputNumberMask_1.FormattedText</strong>). </p>



<p>And finally an optional property if you want to enforce <strong>MaxLength</strong>, is to set the <strong>MaxLength </strong>of the <strong>TextInput </strong>to the Component&#8217;s <strong>MaxLength </strong>output property (<strong>InputNumberMask_1.MaxLength</strong>).</p>



<p>I can play/preview the App and see it in action:</p>



<p></p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="532" height="100" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/inputmask-1.gif" alt="" class="wp-image-1441"/></figure>



<h3 class="wp-block-heading">Conclusion and Download</h3>



<p>By creating this as a Component, I&#8217;ve encapsulated all the logic in one place, and to consume it, I just need to add the Component to the screen and set 5 properties (3 on the component, and 2 on the TextInput). I can easily add multiple instances of this component on a screen (to support multiple TextInputs). </p>



<p>I&#8217;ve uploaded an exported zip of my sample app with the component in it standalone, and also as a component library  in a Solution package. Feel free to use in your apps or build upon it.</p>



<div class="wp-block-file"><a href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/InputNumberMaskComponentSampleAppPackage_20211117051615.zip" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">InputNumberMaskComponentSampleAppPackage_20211117051615</a><a href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/InputNumberMaskComponentSampleAppPackage_20211117051615.zip" class="wp-block-file__button ext-link" download rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Download</a></div>



<div class="wp-block-file"><a href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/InputMaskComponents_1_0_0_1.zip" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">InputMaskComponents_1_0_0_1</a><a href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2021/11/InputMaskComponents_1_0_0_1.zip" class="wp-block-file__button ext-link" download rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Download</a></div><p>The post <a href="https://lifeonplanetgroove.com/powerapps-textinput-number-mask-component/">PowerApps TextInput Number Mask Component</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://lifeonplanetgroove.com/powerapps-textinput-number-mask-component/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>On the Value of Cynicism in the Enterprise</title>
		<link>https://lifeonplanetgroove.com/on-the-value-of-cynicism-in-the-enterprise/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=on-the-value-of-cynicism-in-the-enterprise</link>
					<comments>https://lifeonplanetgroove.com/on-the-value-of-cynicism-in-the-enterprise/#comments</comments>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Mon, 22 Mar 2021 23:28:44 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1417</guid>

					<description><![CDATA[<p>In my org at work, we are currently going through a Dare to Lead workshop, based on Brené Brown&#8217;s book of the same name. It&#8217;s got some nuggets of wisdom, but this part of Section 3 on &#8220;armored leadership&#8221; and cynicism had me scratching my head and disagreeing vehemently. 6. Armored LeadershipHiding Behind Cynicism Cynicism [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/on-the-value-of-cynicism-in-the-enterprise/">On the Value of Cynicism in the Enterprise</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>In my org at work, we are currently going through a Dare to Lead workshop, based on  Brené  Brown&#8217;s book of the same name. It&#8217;s got some nuggets of wisdom, but this part of Section 3 on &#8220;armored leadership&#8221; and cynicism had me scratching my head and disagreeing vehemently.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>6. Armored Leadership<br>Hiding Behind Cynicism</p><p>Cynicism and sarcasm are first cousins who hang out in the cheap seats. But don&#8217;t underestimate them &#8211; they often leave a trail of hurt feelings, anger, confusion, and resentment in their wake. I&#8217;ve seen them bring down relationships, teams, and cultures when modeled by people at the highest levels and/or left unchecked. Like most hurtful comments and passive-aggresiveness, cynicism and sarcasm are bad in person and even worse when they travel through email or text. And, in global teams, culture and language differences make them toxic&#8230;</p><p>In a world roiled by incessant and tumultuous change, swamped by boatloads of fear and anxiety and rampant feelings of scarcity, cynicism and sarcasm are easy and cheap. In fact, I&#8217;d say that they&#8217;re worse than armor &#8211; we use cynicism and sarcasm as getting-out-of-contributing-free cards.</p></blockquote>



<p>First of all, the author is conflating sarcasm, skepticism, and pessimism with cynicism, while these all have very different meanings behind them. For example, later on, she writes:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Cynicism and sarcasm often mask anger, fear, or feelings of inadequacy, and even despair. They&#8217;re a safe way for us to send out an emotional trial balloon and if it doesn&#8217;t go over well, we make it a joke&#8230;</p></blockquote>



<p>And later this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Again, while a cynic might argue that someone who clings to hope is a sucker, or ridiculously earnest, this type of armor typically comes from pain. Often, people&#8217;s cynicism is related to despair. As the theologian Rob Bell explains, &#8216;Despair is the belief that tomorrow will be just like today.&#8217;</p></blockquote>



<p>This is pessimism, for sure, and potentially skepticism (doubt in the face of truths that show tomorrow will be different), but this is not cynicism.</p>



<h3 class="wp-block-heading">Understanding Cynicism and its Roots</h3>



<p>Cynicism is an ancient Greek philosophical school of thought. The ancient Cynics aimed to live in harmony with nature, and to eschew wealth, fame, fortune, and power, often via ascetic practices. Ancients Cynics would often point out the hypocrisy of others, exposing their motives and pretensions underlying the norms of society. Their goal was to achieve happiness through virtue.</p>



<p>There is nothing in ancient cynicism around despair, hopelessness, pessimism, inaction. Rather there is the challenging of norms and conventions, and the questioning of motivations of others, and whether they are acting solely out of self-interest, or out of virtue. Reading about the prototypical Cynic, <a href="https://en.wikipedia.org/wiki/Diogenes" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Diogenes</a>, one can see the true roots of this school of thought.</p>



<p>In modern or contemporary meanings, cynicism has evolved to mean a questioning or distrust of the motives of others. A line from Wikipedia stands out to me:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>  Cynicism is often confused with pessimism or nihilism, perhaps due to its distrust in others. The differences between the three is that cynicism is a distrust by prudence; while due to a sense of defeatism, pessimism is the distrust of potential success. Nihilism on its part have distrust cast upon the belief that life have any valuable meaning. </p><cite>Wikipedia:  <a href="https://en.wikipedia.org/wiki/Cynicism_(contemporary)" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Cynicism (contemporary) &#8211; Wikipedia</a> </cite></blockquote>



<p>I think in the case of Dare to Lead, cynicism is being miscast as pessimism, and while I can certainly agree that pessimism is an undesirable quality in an organization, along with sarcasm, I do think that cynicism has an important role to play as a check and balance against corruption.</p>



<p>Cynicism is a tool that can point out injustices, inequity, and expose selfish motivations behind decisions in our workplaces. It is cynicism that enables us to ask &#8220;why is my company&#8217;s Political Action Committee donating money to senators and congress people who actively supported insurrection against our country?&#8221;, or to question the motivations behind the differing response of force at the Jan 6th insurrection, vs the BLM protests in the same area, or whether this licensing change is actually a bait and switch for our customers and will really tick them off.</p>



<p>In fact, our constitutional democracy is based heavily on a Madisonian cynical view that assumes that people in government are motivated by self-interest, and that earlier democracies had been failures for not taking this into account.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p> But it is wrong to assume that cynicism has no place in a well-ordered constitutional system. In fact, the opposite is true. Cynicism about governmental abuse of power as well as the tendency of interest groups to influence and control government inspired the Framers. In fact, a dominant theme of The Federalist Papers is &#8220;the desirability of adopting the Constitution as a means of controlling interest groups.&#8221; In The Federalist No. 10, James Madison &#8220;expressly embraced the notion that what would separate his constitution from those that had gone before it would be a more realistic [i.e., cynical] conception of human nature.&#8221;&#8216; As I previously observed: The problem confronting the Framers was that, on the one hand, they did not want to organize another monarchy, but on the other hand, the earlier democracies had all been abject failures, nothing less than &#8216;spectacles of turbulence and contention.&#8217; Madison&#8217;s view was that the problem with previous democracies had lain in the assumptions made by their organizers. Specifically, prior to the Federalists&#8217; construction of our political regime, &#8216;the whole of political thought had turned on ways to inculcate virtue in a small class that would govern.&#8217; In stark contrast, the government that Madison had in mind (and the one that ultimately emerged) would be based on the [cynical] assumption that the postconstitutional world would be populated by people motivated by self-interest rather than by virtue. The Framers frankly and self-consciously took the view that they had to construct the Constitution to deal with the corruption and ineptitude of the leaders who would govern the postconstitutional order. </p><cite> Jonathan R. Macey, <a href="https://core.ac.uk/download/pdf/216735783.pdf" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Cynicism and Trust in Politics and Constitutional Theory</a>, 87 Cornell L. Rev. 280 (2002) Available at: http://scholarship.law.cornell.edu/clr/vol87/iss2/2 </cite></blockquote>



<p> I would argue that in discouraging cynicism, and not listening to the issues raised by the questioning of motives and intentions can actually be one of the root causes of anger and resentment in the organization, and a barrier to real effective change. Trust is necessary in any organization, but so is a healthy dose of cynicism to keep any corruption in check.</p>



<p>This book, Dare to Lead, is about the qualities necessary to be a brave, empathetic, and effective leader, through listening, having tough conversations (&#8220;rumbles&#8221; as they are referred to in the book), &#8220;being vulnerable&#8221;, and &#8220;living into our values&#8221;. And so I question why this same book is discouraging cynicism, which is one of the tools that employees have at their disposal to speak truth to power. It&#8217;s very easy to avoid hard conversations as a leader when you discourage the people underneath you from questioning and challenging your motivations that drive your decision-making.</p>



<p>I was honestly enjoying the setup to this section of the book, which included having &#8220;hard conversations&#8221;, embracing vulnerability, building a &#8220;Safe container&#8221; so that employees can share difficult or challenging things without fear, and yet I come to this part of the book and am essentially told that no, it&#8217;s not ok to have a questioning attitude. If we can&#8217;t question motives, then we are all just essentially &#8220;yes-people&#8221; in the org.</p>



<p>This immediate dismissal of cynicism has the Cynic in me now fully awake, and questioning the motives of leadership for even assigning me this training. Is it to create a culture of &#8220;yes-people&#8221;? I know this is most likely due to the author not really taking the time to understand cynicism, and conflating it with other behaviors, but I would expect the author to understand the difference, and to recognize the unique meaning of cynicism and its necessity in an organization.</p>



<p>I for one feel that we need a little more cynicism in the workplace, and I would hope that my leadership would exercise cynicism and question the motives of <em>their </em>leaders, so that we have accountability all the way to the top.</p>



<p> </p><p>The post <a href="https://lifeonplanetgroove.com/on-the-value-of-cynicism-in-the-enterprise/">On the Value of Cynicism in the Enterprise</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://lifeonplanetgroove.com/on-the-value-of-cynicism-in-the-enterprise/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Advanced Error Handling with Power Automate</title>
		<link>https://lifeonplanetgroove.com/advanced-error-handling-with-power-automate/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=advanced-error-handling-with-power-automate</link>
					<comments>https://lifeonplanetgroove.com/advanced-error-handling-with-power-automate/#comments</comments>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Mon, 18 Nov 2019 22:34:47 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Microsoft Flow]]></category>
		<category><![CDATA[Power Automate]]></category>
		<category><![CDATA[PowerApps]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1353</guid>

					<description><![CDATA[<p>This post will show you how to handle errors properly in Power Automate (formerly Microsoft Flow), including expected errors from APIs and connectors, and also how to deal with being throttled. Overview Power Automate&#8217;s default response to errors from connectors is pretty simple &#8211; exit the workflow right there, and record the entire run as [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/advanced-error-handling-with-power-automate/">Advanced Error Handling with Power Automate</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>This post will show you how to handle errors properly in Power Automate (formerly Microsoft Flow), including expected errors from APIs and connectors, and also how to deal with being throttled.<span id="more-1353"></span></p>
<h3>Overview</h3>
<p>Power Automate&#8217;s default response to errors from connectors is pretty simple &#8211; exit the workflow right there, and record the entire run as a failure. In most cases this is what you might want, however sometimes you need to handle an error yourself and take action on it, or ignore it and move on, similar to a try-catch approach in many programming languages.</p>
<p>For example, before committing a record, you might want to check if it already exists first. If it does, then perform an update, if it doesn&#8217;t, go ahead and create it. When calling a RESTful web service to fetch a record by a unique ID, if it can&#8217;t be found, the service will most likely return a 404 status code. In Flow, a 404 is considered an error, and the workflow will fail and terminate at that point unless additional error handling is implemented. In this case though, a 404 shouldn&#8217;t be considered an error per se &#8211; it&#8217;s a legitimate response that tells you something, which you want to then handle and move on from.</p>
<p>To handle an error in Flow, you have to first configure the Run After behavior of your action that you want to happen after the error. You can configure the Run After behavior by clicking the ellipsis (…) on the title bar of an Action, and choosing <strong>Configure run after</strong>.</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 283px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/menu-runafter.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1400" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/menu-runafter-300x283.png" alt="" width="300" height="283" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/11/menu-runafter-300x283.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/menu-runafter.png 594w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>The default setting for every action is to only run if the previous action was successful. If the previous action generates an error, then the workflow will exit before executing the subsequent action. To handle an error then, you will need to make the subsequent action run even if the previous action failed, which you can enable with the &#8220;<strong>has failed</strong>&#8221; checkbox.</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 155px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/dialog-runafter.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1401" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/dialog-runafter-300x155.png" alt="" width="300" height="155" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/11/dialog-runafter-300x155.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/dialog-runafter-1024x529.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/dialog-runafter-768x396.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/dialog-runafter-940x485.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/dialog-runafter-640x330.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/dialog-runafter.png 1271w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>In the image above, I have a SharePoint GetItem action followed by a Switch action, and the Switch is set to run if the SharePoint action fails or is successful.</p>
<h3>Handling Status Codes</h3>
<p>The great thing about the Connectors in the Power Platform is that they are built on web service standards. Each connector is basically a wrapper around a first party or third party web service, and leverages HTTP requests under the hood to communicate. Since each request through a connector is just a web service call, then we should be able to get at the status code response, the headers that the server sent back, and the body of the response.</p>
<p>Power Automate exposes all of this to us via Expressions, which are built using the Azure Logic Apps <a href="https://docs.microsoft.com/en-us/azure/logic-apps/workflow-definition-language-functions-reference" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">Workflow Definition Language</a>. Using the <a href="https://docs.microsoft.com/en-us/azure/logic-apps/workflow-definition-language-functions-reference#outputs" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">outputs()</a> function in an Expression, we are able to get at the complete HTTP response from a connector action. Check out the <a href="https://docs.microsoft.com/en-us/azure/logic-apps/workflow-definition-language-functions-reference#outputs" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">nice docs for this function</a>, where you can see a sample JSON response from a Twitter GetUser action:</p>
<pre class="striped:false marking:false nums:false nums-toggle:false wrap-toggle:false lang:js decode:true" title="Sample output from Twitter GetUser action">{
  "statusCode": 200,
  "headers": {
    "Pragma": "no-cache",
    "Vary": "Accept-Encoding",
    "x-ms-request-id": "a916ec8f52211265d98159adde2efe0b",
    "X-Content-Type-Options": "nosniff",
    "Timing-Allow-Origin": "*",
    "Cache-Control": "no-cache",
    "Date": "Mon, 09 Apr 2018 18:47:12 GMT",
    "Set-Cookie": "ARRAffinity=b9400932367ab5e3b6802e3d6158afffb12fcde8666715f5a5fbd4142d0f0b7d;Path=/;HttpOnly;Domain=twitter-wus.azconn-wus.p.azurewebsites.net",
    "X-AspNet-Version": "4.0.30319",
    "X-Powered-By": "ASP.NET",
    "Content-Type": "application/json; charset=utf-8",
    "Expires": "-1",
    "Content-Length": "339"
  },
  "body": {
    "FullName": "Contoso Corporation",
    "Location": "Generic Town, USA",
    "Id": 283541717,
    "UserName": "ContosoInc",
    "FollowersCount": 172,
    "Description": "Leading the way in transforming the digital workplace.",
    "StatusesCount": 93,
    "FriendsCount": 126,
    "FavouritesCount": 46,
    "ProfileImageUrl": "https://pbs.twimg.com/profile_images/908820389907722240/gG9zaHcd_400x400.jpg"
  }
}</pre>
<p>Notice the collection of headers we have access to, the body of the response, and the statusCode.</p>
<p>Using this, we can write Conditions that check the return status code and handle errors accordingly. The syntax for getting the HTTP Status Code in an Expression is like this:</p>
<pre class="striped:false marking:false nums:false wrap-toggle:false lang:default highlight:0 decode:true" title="Getting the status code">outputs('your_action_name').statusCode</pre>
<p>Note that your action name needs to be in single quotes (not double!), and if you have spaces in your Action name (which most do), you&#8217;ll have to escape them with underscores instead.</p>
<p>A really nice pattern for error handling is to use a Switch action, and use the above formula in the &#8220;On&#8221; field. Click in this field, and click the <strong>Expression</strong> tab. Type this formula and click the <strong>OK</strong> button to insert your expression.</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 150px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/dialog-outputs-expression.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1406" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/dialog-outputs-expression-300x150.png" alt="" width="300" height="150" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/11/dialog-outputs-expression-300x150.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/dialog-outputs-expression.png 624w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>Then you can create a Case for each expected status code. For example,  Case &#8216;200&#8217;, you can then Update the item, Case &#8216;404&#8217; create a new item, and Case &#8216;500&#8217; terminate the workflow with an error message (because something unrecoverably bad probably happened).</p>
<p>Below you can see an image of a Flow where I am looking for a specific item by ID from SharePoint, and a Switch that runs if that action succeeds or fails, and then processes 200, 404, and anything else in separate cases:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 106px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/flow-error1-fullflow.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1402" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/flow-error1-fullflow-300x106.png" alt="" width="300" height="106" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-300x106.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-1024x363.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-768x272.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-1536x545.png 1536w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-940x334.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-640x227.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow.png 2018w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>And here you can see it running with a 404 failure code (I looked for an item with ID 256, which does not exist), and see how it ran the 404 case in the Switch:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 201px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/flow-error1-fullflow-after.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1403" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/flow-error1-fullflow-after-300x201.png" alt="" width="300" height="201" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-after-300x201.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-after-768x516.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-after-940x631.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-after-640x430.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/flow-error1-fullflow-after.png 1023w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<h3>Handling Throttling Responses</h3>
<p>When you get throttled by a web service, it will usually return a 429 status code. These are handled already by Power Automate, so you don&#8217;t have to handle it yourself with home grown looping retry logic. Power Automate already has built-in mechanisms to handle throttling, including automatic retries and exponential back-offs.</p>
<p>You can configure the throttle response behavior by clicking the Ellipsis (…) on the Action title bar, and choosing <strong>Settings</strong>.</p>
<p>Near the bottom of the page, you&#8217;ll find the settings for <strong>Retry Policy</strong>. The default is an Exponential retry <del>with 4 attempts</del> with 2 attempts (EDIT:11/19/2019, just announced the day I posted this article, this has been changed from 4 to 2, <a href="https://flow.microsoft.com/en-us/blog/october-updates-for-microsoft-flow/" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">https://flow.microsoft.com/en-us/blog/october-updates-for-microsoft-flow/</a>). You can configure total # of retries, back-off approach (fixed or exponential), and intervals. Notice that 429 (too many requests), 408 (request timeout), and 5XX (internal server error) errors are handled in this way for you.</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 188px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/retry-policy.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1404" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/11/retry-policy-300x188.png" alt="" width="300" height="188" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/11/retry-policy-300x188.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/retry-policy-1024x640.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/retry-policy-768x480.png 768w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/retry-policy-940x588.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/retry-policy-640x400.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/11/retry-policy.png 1259w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p><p>The post <a href="https://lifeonplanetgroove.com/advanced-error-handling-with-power-automate/">Advanced Error Handling with Power Automate</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://lifeonplanetgroove.com/advanced-error-handling-with-power-automate/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>PowerApps Reusable Components</title>
		<link>https://lifeonplanetgroove.com/powerapps-reusable-components/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=powerapps-reusable-components</link>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Tue, 26 Mar 2019 15:49:30 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1376</guid>

					<description><![CDATA[<p>This post will show you how to create a reusable component for PowerApps, which you can then place on multiple screens in the same app, or export and use on multiple apps. Overview In this post, I&#8217;ll show you how to create reusable canvas components for your PowerApps. If you haven&#8217;t seen the announcement and [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/powerapps-reusable-components/">PowerApps Reusable Components</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>This post will show you how to create a reusable component for PowerApps, which you can then place on multiple screens in the same app, or export and use on multiple apps.</p>
<p><span id="more-1376"></span></p>
<h3>Overview</h3>
<p>In this post, I&#8217;ll show you how to create reusable canvas components for your PowerApps. If you haven&#8217;t seen the announcement and intro videos for this feature, I suggest you check those out here first:</p>
<p><a href="https://powerapps.microsoft.com/en-us/blog/components-available-in-preview/" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">https://powerapps.microsoft.com/en-us/blog/components-available-in-preview/</a></p>
<p>For this example, I&#8217;m going to create a control to display today&#8217;s date, visualized as one of those daily tear-off calendars you might have seen at some point on someone&#8217;s desk.</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 222px; max-height: 214px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/basic-design.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-full wp-image-1380" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/basic-design.png" alt="basic-design" width="222" height="214" /></a></p>
<p>Since the component will be reusable on multiple screens, I&#8217;ll add properties to the control to set the data and visual configurations. I&#8217;ll also show how to use relative sizing to scale the controls when the component is resized, and how to scale font sizes as well.</p>
<h3>Creating the App</h3>
<p>For this post, I&#8217;ll create a new blank Canvas app, using the Phone layout. I&#8217;ll name the app CalendarComponent (from <strong>File &gt; App Settings</strong>), and then <strong>Save</strong> it (always name and Save your app right away to avoid losing work if your browser closes).</p>
<h3>Enabling Components</h3>
<p>Components are an experimental/preview feature right now (March 2019), and in order to work with them, you first have to enable that feature. You can do this by going into your app, and navigating to <strong>File &gt; App Settings &gt; Advanced Settings</strong>. At the bottom of this screen, you&#8217;ll see the option to enable Components:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 87px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/enable-components.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1385" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/enable-components-300x87.png" alt="enable-components" width="300" height="87" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/enable-components-300x87.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/enable-components-1024x299.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/enable-components-940x275.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/enable-components-640x187.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/enable-components.png 1066w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>Once enabled, you should see a <strong>Components</strong> menu item on the <strong>Insert</strong> menu:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 184px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/components-menu.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1383" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/components-menu-300x184.png" alt="components-menu" width="300" height="184" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/components-menu-300x184.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/components-menu-640x393.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/components-menu.png 651w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<h3>Building the Component</h3>
<p>From the <strong>Components</strong> menu, I&#8217;ll select <strong>New Component</strong>. I will rename it to DailyTearOff.</p>
<p>The first thing I will do is set the component width and height. Your component can be resized once it&#8217;s placed on a screen, but this size will be its initial default size. I&#8217;ll make this 200&#215;200 pixels:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 239px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/component-size.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1382" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/component-size-300x239.png" alt="component-size" width="300" height="239" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/component-size-300x239.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/component-size-640x511.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/component-size.png 737w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>Next, I&#8217;ll add some controls to the canvas.</p>
<ul class="disc">
<li>A rectangle, 200&#215;45, placed at the top. A label on top of this also 200&#215;45, with font size 21 and Align.Center, Color.White, and Font of Lato Black.</li>
<li>A label for the date number, 200&#215;120, font size 64, Align.Center, and font of Lato Black. Place this directly underneath the previous two controls.</li>
<li>Finally another label and rectangle at the bottom, similar to the top, 200&#215;35, font size 16, Align.Center, Color.White, and Font Lato Black.</li>
</ul>
<p>It should look like this so far (the text in the labels is just static text I typed):</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 222px; max-height: 214px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/basic-design.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-full wp-image-1380" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/basic-design.png" alt="basic-design" width="222" height="214" /></a></p>
<p>Here is what the initial control tree looks like (I&#8217;ve renamed the controls to work with them more easily later):</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 298px; max-height: 300px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/initial-control-tree.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1386" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/initial-control-tree-298x300.png" alt="initial-control-tree" width="298" height="300" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/initial-control-tree-298x300.png 298w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/initial-control-tree-150x150.png 150w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/initial-control-tree.png 532w" sizes="auto, (max-width: 298px) 100vw, 298px" /></a></p>
<h3>Adding Properties</h3>
<p>A component can have properties, just like other out-of-box PowerApps controls. I&#8217;ll add some properties to control the data and display of the component. The first property I&#8217;ll add is a Date property. I&#8217;ll name it Date, and set the data type to <strong>Date and Time</strong>, and click <strong>Create</strong>:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 289px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/date-property.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1384" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/date-property-300x289.png" alt="date-property" width="300" height="289" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/date-property-300x289.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/date-property-1024x989.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/date-property-940x908.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/date-property-640x618.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/date-property.png 1452w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>If I click the component in the tree view, and look at it&#8217;s properties, I will now see <strong>Date</strong>. Also notice that it is set to a default value of <strong><code>Now()</code></strong>. I could change that default if I want, and it will also get overridden with whatever the user of the component sets as the value.</p>
<p>Next, I&#8217;ll add some properties to control the display of the date info. For example, Month display could use long month, or short month format. Same with the weekday. I could also control casing of the month and day values if I wanted to with additional properties (I&#8217;ll leave those as another exercise for the reader).</p>
<p>I&#8217;ll add the following additional properties:</p>
<ul class="disc">
<li>UseShortDayFormat &#8211; Boolean, Input</li>
<li>UseShortMonthFormat &#8211; Boolean, Input</li>
</ul>
<h3>Wire the Component to the Properties</h3>
<p>Now that the properties are defined, I&#8217;ll wire up the component to the values. First, I&#8217;ll wire up the Date property so it controls the label values. I&#8217;ll start with the day number label. In the Text formula, I&#8217;ll put the following:</p>
<pre>Day(Parent.Date)</pre>
<p>In this case, Parent is the Component itself, so we can reference it that way.</p>
<p>Next I&#8217;ll adjust the month and day of week label displays. To get the names of the weekday and month, I&#8217;ll use the Text function, with a custom date format string. I&#8217;ll also use the boolean properties to control short/long display, and then force upper case. In the day of week label, I&#8217;ll put the following:</p>
<pre class="brush:plain">Upper(If(Parent.UseShortDayFormat, Text(Parent.Date,"ddd"), Text(Parent.Date, "dddd")))</pre>
<p>In the month label, I&#8217;ll use the following:</p>
<pre class="brush:plain">Upper(If(Parent.UseShortMonthFormat, Text(Parent.Date,"mmm"), Text(Parent.Date, "mmmm")))</pre>
<h3>Testing it Out</h3>
<p>Now that I&#8217;ve got it wired up, I&#8217;ll test it out. I&#8217;ll switch to one of my screens, and place the component on the screen. It looks nice!</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 179px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/component-first-added.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1381" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/component-first-added-300x179.png" alt="component-first-added" width="300" height="179" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/component-first-added-300x179.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/component-first-added-1024x611.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/component-first-added-940x561.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/component-first-added-640x382.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/component-first-added.png 1487w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>However if I resize the component, not so much:</p>
<p><img loading="lazy" decoding="async" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/animated-first.gif" alt="animated-first" width="300" height="241" /></p>
<h3>Relative Positioning</h3>
<p>In order to get this to resize well, I&#8217;ll have to use relative positioning, adjusting the width/height as well as X/Y positions of the elements, relative to the parent component size. There are lots of ways to do this depending on your requirements, and how I approach this below is just one way of doing this.</p>
<p>For my approach, I&#8217;m not going to be concerned about growth in Width so much, but rather when the height changes, I want to adjust the elements inside and scale them. So for all of the controls inside, I&#8217;ll change all their Widths to match the component&#8217;s, using Parent.Width. To speed this up, I&#8217;ll use <strong>Ctrl + A</strong> to select all the controls on the component canvas, pull down the <strong>Width</strong> property from the formula bar, and put in <strong>Parent.Width</strong>.</p>
<p>For the height, I&#8217;ll need to know the ratio of the items in their original default sizes (200&#215;45, 200&#215;120, 200&#215;35). Then I&#8217;ll adjust the height of each control to be the height of the parent multiplied by this original ratio (CurrentParentHeight * OriginalControlHeight/OriginalControlWidth).</p>
<p>For example, for the top rectangle, I&#8217;ll set its height to the following:</p>
<pre>Parent.Height*45/200</pre>
<p>I&#8217;ll go through and do this same thing for each of the controls on the screen.</p>
<p>Finally, I will need to adjust the Y position of each control, so that each control is positioned correctly during resizing. The top label and rectangle will always be at the top, so they will be fixed at Y=0. For the ones underneath, I&#8217;ll use relative Y positioning. For the main day number label, I&#8217;ll set the Y value to this formula:</p>
<pre>RectangleHeader.Height</pre>
<p>For the bottom ones, I&#8217;ll set it to the following:</p>
<pre>LabelDate.Y + LabelDate.Height</pre>
<p>At this point, it works much better, with the exception of font-scaling.</p>
<p>At large/wide or small/skinny sizes, it would be nice if the font also scaled as well. Let&#8217;s see how we can accomplish that. Fonts are specified in points in PowerApps, and we can convert to pixels with this formula: 1pt = 1.3333333 pixels</p>
<p>If we know the ratio of pixel size to the overall height of each label control, we can adjust the font accordingly. The formula I&#8217;ll use is the following:</p>
<pre>OriginalFontSize * (CurrentLabelHeight/OriginalFontSize*1.33) * (OriginalFontSize*1.33/OriginalLabelHeight)</pre>
<p>If I place this in the Size property of the label for the Date number, I&#8217;ll end up with a formula like this:</p>
<pre>(64*LabelDate.Height/(64*1.33)*(64*1.33/120))</pre>
<p>EDIT 3/28/19: As my backpacking middle-school math-wiz son points out, above can be simplified to:</p>
<pre>OriginalFontSize * (CurrentLabelHeight/OriginalLabelHeight)</pre>
<p>In the case of the Date label:</p>
<pre>64*LabelDate.Height/120</pre>
<p>Now it sizes much more nicely!:</p>
<p><img loading="lazy" decoding="async" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/animated-final.gif" alt="animated-final" width="300" height="241" /></p>
<p>&nbsp;</p>
<h3>Summary</h3>
<p>Hopefully I&#8217;ve showed you in this post how to create a component, along with some approaches for resizing the controls inside.</p><p>The post <a href="https://lifeonplanetgroove.com/powerapps-reusable-components/">PowerApps Reusable Components</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PowerApps Design &#8211; Create a Digital Alarm Clock Display</title>
		<link>https://lifeonplanetgroove.com/powerapps-design-create-a-digital-alarm-clock-display/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=powerapps-design-create-a-digital-alarm-clock-display</link>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Wed, 13 Mar 2019 02:24:28 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1355</guid>

					<description><![CDATA[<p>In this post, we&#8217;ll look at creating an LED style digital alarm clock display, to help add some cool retro visuals to some PowerApps data. Overview In this post, we&#8217;ll look at how to use SVG images and some formulas to create a digital alarm clock style display in PowerApps. This is going to involve [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/powerapps-design-create-a-digital-alarm-clock-display/">PowerApps Design – Create a Digital Alarm Clock Display</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>In this post, we&#8217;ll look at creating an LED style digital alarm clock display, to help add some cool retro visuals to some PowerApps data.</p>
<p><span id="more-1355"></span></p>
<h3>Overview</h3>
<p>In this post, we&#8217;ll look at how to use SVG images and some formulas to create a digital alarm clock style display in PowerApps. This is going to involve some image manipulation, so I&#8217;ll use one of my favorite free vector programs, Inkscape, to create SVG files that can be used in the clock display. I&#8217;ll also be using a free-for-commercial use digital clock font for this example (thanks to the author).</p>
<ul>
<li>Inkscape: <a title="https://inkscape.org/release" href="https://inkscape.org/release" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">https://inkscape.org/release</a></li>
<li>Calculatrix 7: <a href="https://blogfonts.com/calculatrix-7.font" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">https://blogfonts.com/calculatrix-7.font</a></li>
</ul>
<h3>Create the Images</h3>
<p>For the first part, we will need to create images for each digit of the clock 0-9, as well as the colon, AM/PM, and also a blank image (you&#8217;ll see why later).</p>
<p>Download the font to your machine. Unzip the package, right-click the TTF file, and choose Install Font (if you are on Windows).</p>
<p>Open up Inkscape, and create a new image. From <strong>File &gt; Document Properties</strong>, make the image 36 Wide by 60 tall. For the units, choose pixels (<strong>px</strong>).</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 269px; max-height: 300px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/document-size.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1360" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/document-size-269x300.png" alt="document-size" width="269" height="300" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/document-size-269x300.png 269w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/document-size-640x712.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/document-size.png 834w" sizes="auto, (max-width: 269px) 100vw, 269px" /></a></p>
<p>Click the <strong>Text</strong> Tool, and click in the middle of the image. In the toolbar at the top, change the font to <strong>Calculatrix 7</strong>, and font size to <strong>36</strong>. If you don&#8217;t see a toolbar, choose <strong>View &gt; Show/Hide &gt; Tools Control Bar</strong>.</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 46px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/toolbar.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1365" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/toolbar-300x46.png" alt="toolbar" width="300" height="46" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/toolbar-300x46.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/toolbar-640x98.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/toolbar.png 773w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<p>Type a zero &#8220;0&#8221;. Click the <strong>Arrow</strong> selection tool. Click the <strong>zero</strong>. We are going to center it on the canvas. Click <strong>Object &gt; Align and Distribute</strong>. In the <strong>Align</strong> box, choose <strong>Relative to Page</strong>, and then click the buttons to center on the horizontal and vertical axis.</p>
<p>While the zero is still selected, change the fill color using <strong>Object &gt; Fill and Stroke</strong>. Change the fill color. For this example, I&#8217;m using a bright blue LED color, R=90, G=254, B=254, A=255. Your image should look like this:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 184px; max-height: 300px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/first-number.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1362" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/first-number-184x300.png" alt="first-number" width="184" height="300" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/first-number-184x300.png 184w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/first-number.png 618w" sizes="auto, (max-width: 184px) 100vw, 184px" /></a></p>
<p>One last step, is to covert the font to a vector path, this is so that we don&#8217;t embed or need the font on the client machine. With the object selected, go to <strong>Path &gt; Object to Path</strong>.</p>
<p>Save the image as &#8220;<strong>0.svg</strong>&#8220;. Repeat this process for the rest of the numbers 1-9.</p>
<p>Create two images for AM and PM (&#8220;am.svg&#8221; and &#8220;pm.svg&#8221;). Since these are two characters long, make the AM/PM images 100&#215;60, instead of 36&#215;60.</p>
<p>Create an image for the colon separator. I didn&#8217;t like the colon in the font, and the pipe character, &#8220;|&#8221;, and letter i &#8220;I&#8221; all looked alike. I made a custom implementation by stacking two separate commas on top of each other. I made this image 15&#215;60. Name the image &#8220;colon.svg&#8221; and save it.</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 107px; max-height: 300px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/colon.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1359" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/colon-107x300.png" alt="colon" width="107" height="300" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/colon-107x300.png 107w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/colon.png 297w" sizes="auto, (max-width: 107px) 100vw, 107px" /></a></p>
<p>One last image to make. Create an image 36&#215;60 completely blank, and save it as &#8220;blank.svg&#8221;. We&#8217;ll use this one in place of a number when the hour is a single digit.</p>
<h3>Setup the PowerApp</h3>
<p>Create a new blank canvas PowerApp, choosing the Phone form factor. Go to File, name your App (I called mine LEDClockDemo), and Save it. Always name and save your Apps right away to avoid losing work if your browser crashes!</p>
<h3>Import the Images</h3>
<p>From the File menu of PowerApps, choose Media. Add all the SVG files you created earlier. There should be 14 total images.</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 195px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/imported-images.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1363" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/imported-images-300x195.png" alt="imported-images" width="300" height="195" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/imported-images-300x195.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/imported-images-1024x666.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/imported-images-940x611.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/imported-images-640x416.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/imported-images.png 1205w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<h3>Add the Controls</h3>
<p>Insert a button on this form, and move it to the top. Change the text to &#8220;Fill Data&#8221;. We are going to use this button to populate an array of Time objects, for each minute of every day. In the OnSelect function, paste the formula below:</p>
<pre class="lang:default highlight:0 decode:true ">ClearCollect(ClockImages,{Key:0,Image:'0'},{Key:1,Image:'1'},{Key:2,Image:'2'},{Key:3,Image:'3'},{Key:4,Image:'4'},{Key:5,Image:'5'},{Key:6,Image:'6'},{Key:7,Image:'7'},{Key:8,Image:'8'},{Key:9,Image:'9'});
Clear(Times);
ClearCollect(Hours, [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]);
ClearCollect(Minutes,[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59]);
ForAll(Hours, ForAll(Minutes, Collect(Times,Time(Hours[@Value],Value,0))))</pre>
<p>Invoke the button&#8217;s OnSelect action by holding the Alt key down and clicking the button. You should now have an array called &#8220;Times&#8221; filled with a date/time object containing every minute of the day. You&#8217;ll also have an array called &#8220;ClockImages&#8221; that you can lookup Images by number.</p>
<p>Insert a gallery on to the screen. Change the data source to use the Times array. Change the layout to just display a title only. Your screen should look like this:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 174px; max-height: 300px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/raw-times.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1364" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/raw-times-174x300.png" alt="raw-times" width="174" height="300" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/raw-times-174x300.png 174w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/raw-times-596x1024.png 596w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/raw-times.png 617w" sizes="auto, (max-width: 174px) 100vw, 174px" /></a></p>
<p>Edit the gallery template by clicking the Pencil icon on the first row of the gallery.</p>
<p>Insert an Image control into the template row. Change the Fill property to Black. Change the Width to 36, and the Height to 60. Set the Image property to &#8216;0&#8217;. Copy this image, and paste it 5 other times into the template row. Arrange them so they are all next to each other in a line. Change the third image to use &#8216;colon&#8217; in the Image property. Change the last image to use &#8216;am&#8217; in the Image property. Change the Width of the &#8216;am&#8217; image to 100 pixels. You should now see something like this:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 300px; max-height: 153px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/basic-clock.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1358" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/basic-clock-300x153.png" alt="basic-clock" width="300" height="153" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/basic-clock-300x153.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/basic-clock-1024x524.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/basic-clock-940x481.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/basic-clock-640x328.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/basic-clock.png 1159w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a></p>
<h3>Add the Clock Logic</h3>
<p>Now we&#8217;ll add in the logic on each number to control which digits display. We&#8217;ll try to account for 24 hour time display based on locale as well.</p>
<p>Click on the first digit. In the Image property, write the following formula:</p>
<pre class="lang:default highlight:0 decode:true">If(Clock.IsClock24(),If(Hour(ThisItem.Value)&lt;10,'0',Hour(ThisItem.Value)&lt;20,'1',Hour(ThisItem.Value)&gt;20,'2'),If(Or(And(Hour(ThisItem.Value)&gt;=10,Hour(ThisItem.Value)&lt;=12),Hour(ThisItem.Value)=0,Hour(ThisItem.Value)&gt;=22),'1','blank'))
</pre>
<p>Click the second hour image. In the Image property, write the following formula. We&#8217;ll use a little string manipulation to our advantage, instead of lots of tests with numbers:</p>
<pre class="lang:default highlight:0 decode:true ">If(Or(Clock.IsClock24(),And(Hour(ThisItem.Value)&lt;=12, Hour(ThisItem.Value)&gt;0)),LookUp(ClockImages,Key=Value(Right(Text(Hour(ThisItem.Value)),1))).Image,LookUp(ClockImages,Key=Value(Right(Text(Hour(ThisItem.Value)-12),1))).Image)
</pre>
<p>Click the first minute image. In the Image property, write the following formula. The minutes are much easier to do, we can just grab the first or last character and convert to a number:</p>
<pre class="lang:default highlight:0 decode:true">If(Len(Text(Minute(ThisItem.Value)))=2,LookUp(ClockImages,Key=Value(Left(Text(Minute(ThisItem.Value)),1))).Image,'0')
</pre>
<p>Click the second minute image, and place the following formula in the Image property:</p>
<pre class="lang:default highlight:0 decode:true ">LookUp(ClockImages,Key=Value(Right(Text(Minute(ThisItem.Value)),1))).Image</pre>
<p>Now click the AM/PM image. In the visible property, put the following formula:</p>
<pre class="lang:default highlight:0 decode:true ">!Clock.IsClock24()</pre>
<p>In the Image property, use the following formula to toggle AM/PM if displaying in 12 hour format:</p>
<pre class="lang:default highlight:0 decode:true">If(Hour(ThisItem.Value)>12,'pm','am')</pre>
<p>Your clock should now work and look something like this:</p>
<p><a class="img-prettyPhoto alignnone ext-image" style="width: 284px; max-height: 300px; max-width: 100%;" title="" href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/finished-clock.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="alignnone scale-with-grid size-medium wp-image-1361" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2019/03/finished-clock-284x300.png" alt="finished-clock" width="284" height="300" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2019/03/finished-clock-284x300.png 284w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/finished-clock-970x1024.png 970w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/finished-clock-940x992.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/finished-clock-640x675.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2019/03/finished-clock.png 1027w" sizes="auto, (max-width: 284px) 100vw, 284px" /></a></p>
<h3>Conclusion</h3>
<p>In this post, we&#8217;ve seen how to build a retro-style clock display with some svg graphics and formulas. We bound actual date time values to our clock, and used the formulas to change the displayed numbers according to the bound date/time.</p>
<p>There are of course questions: How can I easily reuse this on multiple screens? How can I change the color of the numbers without making new images? Right now these are challenges for sure, but as the platform matures, we may get things like custom font support, support for creating custom vector icons, and support for building your own PowerApps controls using React.</p><p>The post <a href="https://lifeonplanetgroove.com/powerapps-design-create-a-digital-alarm-clock-display/">PowerApps Design – Create a Digital Alarm Clock Display</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Testing Online Connectivity in PowerApps</title>
		<link>https://lifeonplanetgroove.com/testing-online-connectivity-in-powerapps/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=testing-online-connectivity-in-powerapps</link>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Thu, 17 Jan 2019 19:20:23 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1344</guid>

					<description><![CDATA[<p>This post will walk through testing the Connection.Connected property in your PowerApps. Connection.Connected If you are building a PowerApp with offline capabilities, then it becomes very important to test whether the device has an active internet connection. The sensor function Connection.Connected can be used to test for connectivity &#8211; if true, you are connected, false [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/testing-online-connectivity-in-powerapps/">Testing Online Connectivity in PowerApps</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>This post will walk through testing the Connection.Connected property in your PowerApps.<br />
<span id="more-1344"></span></p>
<h3>Connection.Connected</h3>
<p>If you are building a PowerApp with offline capabilities, then it becomes very important to test whether the device has an active internet connection. The sensor function <code>Connection.Connected</code><br />
can be used to test for connectivity &#8211; if true, you are connected, false not so much. A common scenario is to check the result of this function in an OnSelect formula. If connected, write or submit to a live data source, if disconnected, write to local collection for submittal later:</p>
<pre>OnSelect = If(Connection.Connected, Patch(Contacts, Defaults(Contacts),{Name:"Adam"}), Collect(DraftContacts,{Name:"Adam"}))</pre>
<p>While developing your App, it&#8217;s somewhat difficult to test this in the web browser in PowerApps Studio, as the Connection.Connected function will usually return TRUE, even if you can&#8217;t connect to the internet (unplugged LAN cable, hotel Wifi without accepting terms of use, etc.). Even if you totally disable your network adapters, or put your computer in airplane mode, the property can still be unreliable. Sometimes it reports correctly, sometimes it takes a long time after changing connection status to update in the App, but usually just reports true.</p>
<p>Add to this the fact that if you are disconnected to test offline capabilities, then you can&#8217;t really make any changes and Save in PowerApps Studio, because, well, you are disconnected, right?</p>
<h3>Fakin&#8217; It</h3>
<p>To get around this, you can fake it in the web browser. I call this Force Offline. It&#8217;s pretty simple to implement:</p>
<ol>
<li>Create a new screen, name it <strong>Debug</strong>, and put a button on it. This will be a hidden screen, since we won&#8217;t make any way for a user to navigate to it.</li>
<li>In the button&#8217;s <strong>OnSelect()</strong>, set a global variable:
<pre>Set(ForceOffline, !ForceOffline)</pre>
</li>
<li>In the button&#8217;s <strong>Text</strong> property, change the label:
<pre>If(ForceOffline, "Normal Connection Mode", "Force Offline Mode")</pre>
</li>
<li>Now, wherever you reference <code>Connection.Connected</code>, wrap it in a check for ForceOffline mode first. Using the earlier example, you&#8217;d rewrite it like this:<br />
OnSelect =</p>
<pre>If(If(ForceOffline, false, Connection.Connected), Patch(Contacts, Defaults(Contacts),{Name:"Adam"}), Collect(DraftContacts,{Name:"Adam"})</pre>
</li>
</ol>
<p>Now, when you want to test, just go to that screen in Edit mode, and Alt + Click the button and put it into Force Offline mode. You can now test away as-if your app is Offline, change it back and test Online, all without having to futz with Airplane mode or disabling/unplugging adapters!</p><p>The post <a href="https://lifeonplanetgroove.com/testing-online-connectivity-in-powerapps/">Testing Online Connectivity in PowerApps</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Microsoft Flow Quotas Explained</title>
		<link>https://lifeonplanetgroove.com/microsoft-flow-quotas-explained/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=microsoft-flow-quotas-explained</link>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Wed, 27 Jun 2018 17:24:34 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1334</guid>

					<description><![CDATA[<p>Many of my customers have wanted clarification on the quotas for Microsoft Flow for the various license levels we have. This post will attempt to clear up any confusion. Overview The licensing page for PowerApps and Flow lists some quotas and limits depending on your license level, and can be a bit confusing. This post [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/microsoft-flow-quotas-explained/">Microsoft Flow Quotas Explained</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Many of my customers have wanted clarification on the quotas for Microsoft Flow for the various license levels we have. This post will attempt to clear up any confusion.<span id="more-1334"></span></p>
<h3>Overview</h3>
<p>The <a href="https://flow.microsoft.com/en-us/pricing/" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">licensing page for PowerApps and Flow</a> lists some quotas and limits depending on your license level, and can be a bit confusing. This post will attempt to clarifiy how exactly these quotas work in combination with particular license levels. Any specific numbers listed here may change over time, so they are valid as of the time of this initial posting (6/27/2018). I will keep the post updated if any of these numbers change, but as usual, you should refer to the <a href="https://flow.microsoft.com/en-us/pricing/" class="ext-link" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;">official licensing page</a> for the most current figures.</p>
<h3>Maximum Flow Frequency</h3>
<p>This limit creates the most confusion with my customers. The maximum flow frequency defines the shortest period of time that an automated flow trigger is allowed to check for changes. This maximum is based on the license level of the user who last edited and saved the Flow. Since flows run usually without any direct user interaction, there is no prompt for credentials when a Flow runs, so the Flow ends up running under the context and license level of the user who last edited and saved the Flow.</p>
<p>For Office365 Enterprise level licenses, this maximum frequency is currently 5 minutes. So this means that for any connectors that use a trigger that fires automatically, the test/check for the trigger&#8217;s condition (e.g. item created, row inserted, item updated, etc.) will only take place a maximum of once every 5 minutes for O365 E-level licenses.</p>
<p>This does NOT mean that instances of a Flow cannot be run more frequently than that. It just means that the check for the trigger condition will not occur more frequently than the max flow frequency. If the trigger check detects multiple changes in the backend system, it can start one instance of the Flow for each detected change immediately. Then the trigger polling mechanism will go to sleep and stop checking for changes again until the max flow frequency has passed.</p>
<p>Let&#8217;s look at an example for the SharePoint Connector, checking for items created in a list (but you can easily substitute rows in SQL Server connector, Tweets in Twitter connector, files added in DropBox connector, etc.). In this example, we are assuming the user that last saved the flow has an E3 license level (so a 5 minute max flow frequency):</p>
<ul class="disc">
<li>Flow has a SharePoint connector, with a Trigger on a SharePoint list for when Items are Created.</li>
<li>The trigger runs at 1:10PM, and detects no changes. No workflows are started. The Flow goes to sleep and will not check again for the max flow frequency (5 minutes in this case)</li>
<li>At 1:12PM, 4 new list items are created in SharePoint.</li>
<li>At 1:15PM, the trigger check is again performed. 4 new items are discovered, so 4 new workflow runs are immediately started concurrently, one for each item.</li>
<li>Next check for changes will occur at 1:20PM.</li>
</ul>
<p>Notice in this example that when multiple changes are detected, workflow runs are spawned immediately for each change and run concurrently, they are not queued up, they do not stack up and have to wait for the max flow frequency to pass for the next run to execute. The max flow frequency simply drives how often the trigger conditions are checked for.</p>
<p>It&#8217;s interesting to note that you can control how many concurrent runs are started when the trigger fires. Most of our 1st party and 3rd party triggers use a polling system, where Flow checks the system regularly for changes. Most of these systems also have a way to return an array of changes in a single check. If you go into the Settings for a trigger (pull the ellipsis &#8230; down next to the Trigger and choose Settings), you may see a SplitOn section if the system is able to send back multiple changes with a single trigger change request. SplitOn determines the field in the trigger response that contains the array of items that has changed. You may also see a Concurrency Control section. If a system sends back an array of changes in response to a trigger check, you can control how many instances are spawned concurrently. Leave it off if you want to spawn as many as possible.</p>
<p><figure id="attachment_1337" aria-describedby="caption-attachment-1337" style="width: 300px" class="wp-caption alignnone"><a class="img-prettyPhoto ext-image" title="SplitOn and Concurrency Control in a trigger's settings." href="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2018/06/trigger-settings.png" data-rel="prettyPhoto" rel="external nofollow" onclick="this.target=&#039;_blank&#039;;"><img loading="lazy" decoding="async" class="scale-with-grid size-medium wp-image-1337" src="https://grey-frog-177824.hostingersite.com/wp-content/uploads/2018/06/trigger-settings-300x245.png" alt="SplitOn and Concurrency Control in a trigger's settings." width="300" height="245" srcset="https://lifeonplanetgroove.com/wp-content/uploads/2018/06/trigger-settings-300x245.png 300w, https://lifeonplanetgroove.com/wp-content/uploads/2018/06/trigger-settings-1024x837.png 1024w, https://lifeonplanetgroove.com/wp-content/uploads/2018/06/trigger-settings-940x768.png 940w, https://lifeonplanetgroove.com/wp-content/uploads/2018/06/trigger-settings-640x523.png 640w, https://lifeonplanetgroove.com/wp-content/uploads/2018/06/trigger-settings.png 1239w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><figcaption id="caption-attachment-1337" class="wp-caption-text">SplitOn and Concurrency Control in a trigger&#8217;s settings.</figcaption></figure></p>
<h4>Automated Triggers</h4>
<p>Automated triggers are subject to the maximum flow frequency. Automated triggers include the Scheduled trigger, and any other triggers not listed below in the Manual Triggers list.</p>
<h4>Manual Triggers</h4>
<p>Manual triggers are not subject to the maximum flow frequency. Manual triggers include the following:</p>
<ul class="disc">
<li>PowerApps trigger</li>
<li>HTTP Request trigger</li>
<li>Flow Button for Mobile</li>
</ul>
<p>You can start as many flows as you wish, as frequently as you wish, using the manual triggers.</p>
<h3>Maximum Flow Runs</h3>
<p>The other quota your Flows will be subjected to is the Maximum Flow Runs per Month. Pretty straightforward &#8211; this controls how many instances (&#8220;runs&#8221;) a particular user is allowed to start in a given month. For O365 E-level licenses, this is 2000 runs per month per user. However this limit is pooled across the tenant, so if one user has reached the maximum, and another user has hardly used any, the unused runs will start to be consumed until the entire pool for all users in the tenant is exhausted for that month. If you start to hit the limit, you can purchase additional blocks of 50,000 runs for $40 USD / month.</p>
<h3>Maximum Custom Connectors</h3>
<p>The last quota to be aware of, which affects PowerApps as well as Flow, is the maximum number of Custom API Connectors that a user can create. With the O365 E-level licenses, a given user can only create a maximum of 1 custom API connector. This does not have anything to do with how many custom connectors can be used or referenced within a PowerApp or Flow, it&#8217;s simply how many custom connectors a given user can create. A <strong>Connector</strong> is a wrapper around an API or a service. A <strong>Connection</strong> is an instance of a Connector being used inside of a PowerApp or Flow. The limit here applies to the creation of the <strong>Connector</strong>&#8211; once it&#8217;s created, any Flow or PowerApp author can create Connections using the Connector without limits.</p>
<p>If you plan on needing multiple custom connectors created (maybe to be consumed in multiple PowerApps or Flows), then you&#8217;ll either need to distribute the creation of these across your developers, or you&#8217;ll need to purchase and assign a P1/F1 or P2/F2 license to the user that defines/creates the custom connectors.</p>
<h3>Summary</h3>
<p>Hopefully this post has helped to clear up some of the confusion around Flow licensing. If you have any other questions, please post a comment!</p>
<p>&nbsp;</p><p>The post <a href="https://lifeonplanetgroove.com/microsoft-flow-quotas-explained/">Microsoft Flow Quotas Explained</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Set and Clear Person Column Values Using SharePoint REST API</title>
		<link>https://lifeonplanetgroove.com/set-person-column-value-using-sharepoint-rest-api/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=set-person-column-value-using-sharepoint-rest-api</link>
		
		<dc:creator><![CDATA[Adam Toth]]></dc:creator>
		<pubDate>Wed, 30 Mar 2016 16:51:11 +0000</pubDate>
				<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[sharepoint]]></category>
		<guid isPermaLink="false">http://www.lifeonplanetgroove.com/?p=1318</guid>

					<description><![CDATA[<p>This post will show you how to update a Person/Group column value in SharePoint using the REST API, including how to clear/empty the value in the columns. Setting a Person/Group Value If you want to set a Person or Group column value using SharePoint&#8217;s REST API, there are a couple of things you&#8217;ll need to [&#8230;]</p>
<p>The post <a href="https://lifeonplanetgroove.com/set-person-column-value-using-sharepoint-rest-api/">Set and Clear Person Column Values Using SharePoint REST API</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>This post will show you how to update a Person/Group column value in SharePoint using the REST API, including how to clear/empty the value in the columns.</p>
<h2>Setting a Person/Group Value</h2>
<p>If you want to set a Person or Group column value using SharePoint&#8217;s REST API, there are a couple of things you&#8217;ll need to do. First, you&#8217;ll need to include the correct standard headers, including a X-RequestDigest value, If-Match header for consistency, Content-Type and Accept headers (easiest to use JSON for both), and X-HttpMethod. Here is a raw set of headers:</p>
<pre class="brush:text">Method: POST
Accept: application/json;odata=verbose
Content-Type: application/json;odata=verbose
X-RequestDigest: &lt;-- your value here --&gt;
If-Match: *
X-HttpMethod: POST
</pre>
<p>&#8230;and a jQuery ajax example:</p>
<pre class="brush:javascript">$.ajax({
    url:'https://contoso.sharepoint.com/_api/web/lists/getbytitle('TestList')/Items',
    method:'POST', // --&gt; for any type of update, best to use POST, and set X-HttpMethod below
    headers: {
        'Accept':'application/json;odata=verbose',
        'Content-Type':'application/json;odata=verbose',
        'X-RequestDigest':$("#__REQUESTDIGEST").val(),
        'If-Match':'*', // --&gt; Use an etag value if you want to ensure consistency
        'X-HttpMethod':'POST' // --&gt; Only necessary for PUT,PATCH,MERGE,DELETE which some firewalls trap
    }
});
</pre>
<p>Next, the name of the column in your update is not the same as the actual column name, so you&#8217;ll need to append &#8220;Id&#8221; to the end of your column. For example, if your column name is &#8220;Requestor&#8221;, you&#8217;ll need to use &#8220;RequestorId&#8221; in your request body. Below is the raw body of a POST request updating both a single-value person column, and a multi-value person column. Notice the single-value column takes an integer ID value &#8211; this is the numeric ID of the user in SharePoint from the UserInformation list in the site collection. Also notice the Multi-value columns syntax, which requires an array object to be passed to it:</p>
<pre class="brush: text">{'__metadata':{'type':'SP.Data.TestListListItem'},
'Title':'My title',
'SinglePersonColumnId':9,
'MultiPersonColumnId':{'results':[9,12]}}
</pre>
<h2>Clearing Person/Group Values</h2>
<p>To clear out or empty the values in person or group columns, how you do it depends on if the column is single-value or multi-value.</p>
<p>For single-value person columns, all you have to do is set the value to -1.</p>
<pre class="brush: text;highlight:[3]">{'__metadata':{'type':'SP.Data.TestListListItem'},
'Title':'My title',
'SinglePersonColumnId':-1,
'MultiPersonColumnId':{'results':[9,12]}}
</pre>
<p>It requires an integer value, so null or empty string will give you an error: Cannot convert a primitive value to the expected type &#8216;Edm.Int32&#8217;.</p>
<p>For multi-value person columns, you have to set the results value to an empty array:</p>
<pre class="brush: text;highlight:[4]">{'__metadata':{'type':'SP.Data.TestListListItem'},
'Title':'My title',
'SinglePersonColumnId':-1,
'MultiPersonColumnId':{'results':[0]}}
</pre>
<p>That&#8217;s it!</p><p>The post <a href="https://lifeonplanetgroove.com/set-person-column-value-using-sharepoint-rest-api/">Set and Clear Person Column Values Using SharePoint REST API</a> first appeared on <a href="https://lifeonplanetgroove.com">Life on Planet Groove - Adam Toth's Blog</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
