├── .gitignore ├── .vuepress ├── .cache │ └── deps │ │ ├── @vue_devtools-api.js │ │ ├── @vue_devtools-api.js.map │ │ ├── @vuepress_shared.js │ │ ├── @vuepress_shared.js.map │ │ ├── @vueuse_core.js │ │ ├── @vueuse_core.js.map │ │ ├── _metadata.json │ │ ├── chunk-2M277TBP.js │ │ ├── chunk-2M277TBP.js.map │ │ ├── chunk-FEFTYQ2P.js │ │ ├── chunk-FEFTYQ2P.js.map │ │ ├── chunk-HQV6CKD5.js │ │ ├── chunk-HQV6CKD5.js.map │ │ ├── chunk-ZAX4UJVK.js │ │ ├── chunk-ZAX4UJVK.js.map │ │ ├── package.json │ │ ├── vue-router.js │ │ ├── vue-router.js.map │ │ ├── vue.js │ │ └── vue.js.map ├── .temp │ ├── internal │ │ ├── clientConfigs.js │ │ ├── layoutComponents.js │ │ ├── pagesComponents.js │ │ ├── pagesData.js │ │ ├── pagesRoutes.js │ │ ├── siteData.js │ │ └── themeData.js │ ├── pages │ │ ├── 00.introduction.html.js │ │ ├── 00.introduction.html.vue │ │ ├── 01.guide │ │ │ └── 1000.environment-configuration │ │ │ │ ├── DH1201.html.js │ │ │ │ ├── DH1201.html.vue │ │ │ │ ├── DH1202.html.js │ │ │ │ ├── DH1202.html.vue │ │ │ │ ├── DH1203.html.js │ │ │ │ ├── DH1203.html.vue │ │ │ │ ├── index.html.js │ │ │ │ ├── index.html.vue │ │ │ │ ├── installation-configuration.html.js │ │ │ │ └── installation-configuration.html.vue │ │ ├── 02.environment-configuration │ │ │ ├── DH1201.html.js │ │ │ ├── DH1201.html.vue │ │ │ ├── DH1202.html.js │ │ │ ├── DH1202.html.vue │ │ │ ├── DH1203.html.js │ │ │ ├── DH1203.html.vue │ │ │ ├── index.html.js │ │ │ ├── index.html.vue │ │ │ ├── installation-configuration.html.js │ │ │ └── installation-configuration.html.vue │ │ ├── 1000.environment-configuration │ │ │ ├── DH1201.html.js │ │ │ ├── DH1201.html.vue │ │ │ ├── DH1202.html.js │ │ │ ├── DH1202.html.vue │ │ │ ├── DH1203.html.js │ │ │ ├── DH1203.html.vue │ │ │ ├── index.html.js │ │ │ ├── index.html.vue │ │ │ ├── installation-configuration.html.js │ │ │ └── installation-configuration.html.vue │ │ ├── 1100.user-experience-design │ │ │ ├── ux-design.html.js │ │ │ └── ux-design.html.vue │ │ ├── 1200.naming-conventions │ │ │ ├── azure-resources.html.js │ │ │ ├── azure-resources.html.vue │ │ │ ├── azure-tags.html.js │ │ │ ├── azure-tags.html.vue │ │ │ ├── naming-conventions.html.js │ │ │ └── naming-conventions.html.vue │ │ ├── 1300.customization │ │ │ ├── entity-design.html.js │ │ │ └── entity-design.html.vue │ │ ├── 1400.extending-client-side │ │ │ ├── extending-clientside.html.js │ │ │ └── extending-clientside.html.vue │ │ ├── 1500.extending-server-side │ │ │ ├── extending-serverside.html.js │ │ │ └── extending-serverside.html.vue │ │ ├── 1600.external-applications │ │ │ ├── external-applications.html.js │ │ │ └── external-applications.html.vue │ │ ├── 1700.design-patterns │ │ │ ├── design-patterns.html.js │ │ │ └── design-patterns.html.vue │ │ ├── 1800.data-migrations │ │ │ ├── datamigrations.html.js │ │ │ └── datamigrations.html.vue │ │ ├── 2000.guidelines │ │ │ ├── possible-structure.html.js │ │ │ ├── possible-structure.html.vue │ │ │ ├── rules-list-test.html.js │ │ │ ├── rules-list-test.html.vue │ │ │ ├── tools.html.js │ │ │ ├── tools.html.vue │ │ │ ├── tryout-markdown.html.js │ │ │ └── tryout-markdown.html.vue │ │ ├── 3000.powerautomate │ │ │ ├── powerautomate.html.js │ │ │ └── powerautomate.html.vue │ │ ├── 404.html.js │ │ ├── 404.html.vue │ │ ├── CONTRIBUTING.html.js │ │ ├── CONTRIBUTING.html.vue │ │ ├── index.html.js │ │ └── index.html.vue │ ├── register-components │ │ └── clientConfig.091b98ea.js │ ├── styles │ │ ├── index.scss │ │ └── palette.scss │ └── vite-root │ │ └── index.html ├── components │ ├── Depends.vue │ ├── NumberModifier.vue │ ├── Recommended.vue │ ├── Required.vue │ └── RuleList.vue ├── config.js └── public │ ├── apple-touch-icon-114x114.png │ ├── apple-touch-icon-144x144.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-57x57.png │ ├── assets │ ├── ALM-source-control.png │ ├── aPaaS.png │ ├── environment-5-security-layers.png │ ├── environment-DLP-Applying.png │ ├── environment-DLP.png │ ├── environment-naming-admin.png │ ├── environment-naming-homescreen.png │ ├── poweratomate-keep-condition-empty.png │ ├── powerautomate-connection-references.png │ ├── powerautomate-copy-setname.jpeg │ └── powerautomate-lookup-with-type.png │ ├── favicon-128.png │ ├── favicon-16x16.png │ ├── favicon-196x196.png │ ├── favicon-32x32.png │ ├── favicon-64x64.png │ ├── favicon-96x96.png │ ├── favicon.ico │ └── logo.png ├── 00.introduction.md ├── 1000.environment-configuration ├── DH1201.md ├── DH1202.md ├── DH1203.md ├── README.md └── installation-configuration.md ├── 1100.user-experience-design └── ux-design.md ├── 1200.naming-conventions ├── azure-resources.md ├── azure-tags.md └── naming-conventions.md ├── 1300.customization └── entity-design.md ├── 1400.extending-client-side └── extending-clientside.md ├── 1500.extending-server-side └── extending-serverside.md ├── 1600.external-applications └── external-applications.md ├── 1700.design-patterns └── design-patterns.md ├── 1800.data-migrations └── datamigrations.md ├── 2000.guidelines ├── possible-structure.md ├── rules-list-test.md ├── tools.md └── tryout-markdown.md ├── 3000.powerautomate └── powerautomate.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vuepress/dist -------------------------------------------------------------------------------- /.vuepress/.cache/deps/@vue_devtools-api.js: -------------------------------------------------------------------------------- 1 | import { 2 | isPerformanceSupported, 3 | now, 4 | setupDevtoolsPlugin 5 | } from "./chunk-2M277TBP.js"; 6 | import "./chunk-FEFTYQ2P.js"; 7 | export { 8 | isPerformanceSupported, 9 | now, 10 | setupDevtoolsPlugin 11 | }; 12 | //# sourceMappingURL=@vue_devtools-api.js.map 13 | -------------------------------------------------------------------------------- /.vuepress/.cache/deps/@vue_devtools-api.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "sources": [], 4 | "sourcesContent": [], 5 | "mappings": "", 6 | "names": [] 7 | } 8 | -------------------------------------------------------------------------------- /.vuepress/.cache/deps/@vuepress_shared.js: -------------------------------------------------------------------------------- 1 | import { 2 | isArray, 3 | isFunction, 4 | isString 5 | } from "./chunk-ZAX4UJVK.js"; 6 | import "./chunk-FEFTYQ2P.js"; 7 | 8 | // node_modules/@vuepress/shared/dist/index.js 9 | var resolveHeadIdentifier = ([ 10 | tag, 11 | attrs, 12 | content 13 | ]) => { 14 | if (tag === "meta" && attrs.name) { 15 | return `${tag}.${attrs.name}`; 16 | } 17 | if (["title", "base"].includes(tag)) { 18 | return tag; 19 | } 20 | if (tag === "template" && attrs.id) { 21 | return `${tag}.${attrs.id}`; 22 | } 23 | return JSON.stringify([tag, attrs, content]); 24 | }; 25 | var dedupeHead = (head) => { 26 | const identifierSet = /* @__PURE__ */ new Set(); 27 | const result = []; 28 | head.forEach((item) => { 29 | const identifier = resolveHeadIdentifier(item); 30 | if (!identifierSet.has(identifier)) { 31 | identifierSet.add(identifier); 32 | result.push(item); 33 | } 34 | }); 35 | return result; 36 | }; 37 | var ensureLeadingSlash = (str) => str.replace(/^\/?/, "/"); 38 | var ensureEndingSlash = (str) => /(\.html|\/)$/.test(str) ? str : str + "/"; 39 | var formatDateString = (str, defaultDateString = "") => { 40 | const dateMatch = str.match(/\b(\d{4})-(\d{1,2})-(\d{1,2})\b/); 41 | if (dateMatch === null) { 42 | return defaultDateString; 43 | } 44 | const [, yearStr, monthStr, dayStr] = dateMatch; 45 | return [yearStr, monthStr.padStart(2, "0"), dayStr.padStart(2, "0")].join("-"); 46 | }; 47 | var htmlEscapeMap = { 48 | "&": "&", 49 | "<": "<", 50 | ">": ">", 51 | "'": "'", 52 | '"': """ 53 | }; 54 | var htmlEscapeRegexp = /[&<>'"]/g; 55 | var htmlEscape = (str) => str.replace(htmlEscapeRegexp, (char) => htmlEscapeMap[char]); 56 | var htmlUnescapeMap = { 57 | "&": "&", 58 | "&": "&", 59 | "<": "<", 60 | "<": "<", 61 | ">": ">", 62 | ">": ">", 63 | "'": "'", 64 | "'": "'", 65 | """: '"', 66 | """: '"' 67 | }; 68 | var htmlUnescapeRegexp = /&(amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g; 69 | var htmlUnescape = (str) => str.replace(htmlUnescapeRegexp, (char) => htmlUnescapeMap[char]); 70 | var isLinkFtp = (link) => link.startsWith("ftp://"); 71 | var isLinkHttp = (link) => /^(https?:)?\/\//.test(link); 72 | var isLinkExternal = (link, base = "/") => { 73 | if (isLinkHttp(link) || isLinkFtp(link)) { 74 | return true; 75 | } 76 | if (link.startsWith("/") && !link.startsWith(base) && !link.endsWith(".md")) { 77 | return true; 78 | } 79 | return false; 80 | }; 81 | var isLinkMailto = (link) => /^mailto:/.test(link); 82 | var isLinkTel = (link) => /^tel:/.test(link); 83 | var isPlainObject = (val) => Object.prototype.toString.call(val) === "[object Object]"; 84 | var removeEndingSlash = (str) => str.replace(/\/$/, ""); 85 | var removeLeadingSlash = (str) => str.replace(/^\//, ""); 86 | var resolveLocalePath = (locales, routePath) => { 87 | const localePaths = Object.keys(locales).sort((a, b) => { 88 | const levelDelta = b.split("/").length - a.split("/").length; 89 | if (levelDelta !== 0) { 90 | return levelDelta; 91 | } 92 | return b.length - a.length; 93 | }); 94 | for (const localePath of localePaths) { 95 | if (routePath.startsWith(localePath)) { 96 | return localePath; 97 | } 98 | } 99 | return "/"; 100 | }; 101 | var resolveRoutePathFromUrl = (url, base = "/") => url.replace(/^(https?:)?\/\/[^/]*/, "").replace(new RegExp(`^${base}`), "/"); 102 | export { 103 | dedupeHead, 104 | ensureEndingSlash, 105 | ensureLeadingSlash, 106 | formatDateString, 107 | htmlEscape, 108 | htmlUnescape, 109 | isArray, 110 | isFunction, 111 | isLinkExternal, 112 | isLinkFtp, 113 | isLinkHttp, 114 | isLinkMailto, 115 | isLinkTel, 116 | isPlainObject, 117 | isString, 118 | removeEndingSlash, 119 | removeLeadingSlash, 120 | resolveHeadIdentifier, 121 | resolveLocalePath, 122 | resolveRoutePathFromUrl 123 | }; 124 | //# sourceMappingURL=@vuepress_shared.js.map 125 | -------------------------------------------------------------------------------- /.vuepress/.cache/deps/_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "hash": "e270e3fa", 3 | "browserHash": "2c2070fb", 4 | "optimized": { 5 | "@vue/devtools-api": { 6 | "src": "../../../node_modules/@vue/devtools-api/lib/esm/index.js", 7 | "file": "@vue_devtools-api.js", 8 | "fileHash": "80a495f0", 9 | "needsInterop": false 10 | }, 11 | "@vuepress/shared": { 12 | "src": "../../../node_modules/@vuepress/shared/dist/index.js", 13 | "file": "@vuepress_shared.js", 14 | "fileHash": "abc369aa", 15 | "needsInterop": false 16 | }, 17 | "@vueuse/core": { 18 | "src": "../../../node_modules/@vueuse/core/index.mjs", 19 | "file": "@vueuse_core.js", 20 | "fileHash": "b2b5e07f", 21 | "needsInterop": false 22 | }, 23 | "vue": { 24 | "src": "../../../node_modules/vue/dist/vue.runtime.esm-bundler.js", 25 | "file": "vue.js", 26 | "fileHash": "0f55171b", 27 | "needsInterop": false 28 | }, 29 | "vue-router": { 30 | "src": "../../../node_modules/vue-router/dist/vue-router.esm-bundler.js", 31 | "file": "vue-router.js", 32 | "fileHash": "aaa7ab2b", 33 | "needsInterop": false 34 | } 35 | }, 36 | "chunks": { 37 | "chunk-2M277TBP": { 38 | "file": "chunk-2M277TBP.js" 39 | }, 40 | "chunk-HQV6CKD5": { 41 | "file": "chunk-HQV6CKD5.js" 42 | }, 43 | "chunk-ZAX4UJVK": { 44 | "file": "chunk-ZAX4UJVK.js" 45 | }, 46 | "chunk-FEFTYQ2P": { 47 | "file": "chunk-FEFTYQ2P.js" 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /.vuepress/.cache/deps/chunk-2M277TBP.js: -------------------------------------------------------------------------------- 1 | // node_modules/@vue/devtools-api/lib/esm/time.js 2 | var supported; 3 | var perf; 4 | function isPerformanceSupported() { 5 | var _a; 6 | if (supported !== void 0) { 7 | return supported; 8 | } 9 | if (typeof window !== "undefined" && window.performance) { 10 | supported = true; 11 | perf = window.performance; 12 | } else if (typeof global !== "undefined" && ((_a = global.perf_hooks) === null || _a === void 0 ? void 0 : _a.performance)) { 13 | supported = true; 14 | perf = global.perf_hooks.performance; 15 | } else { 16 | supported = false; 17 | } 18 | return supported; 19 | } 20 | function now() { 21 | return isPerformanceSupported() ? perf.now() : Date.now(); 22 | } 23 | 24 | // node_modules/@vue/devtools-api/lib/esm/env.js 25 | function getDevtoolsGlobalHook() { 26 | return getTarget().__VUE_DEVTOOLS_GLOBAL_HOOK__; 27 | } 28 | function getTarget() { 29 | return typeof navigator !== "undefined" && typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}; 30 | } 31 | var isProxyAvailable = typeof Proxy === "function"; 32 | 33 | // node_modules/@vue/devtools-api/lib/esm/const.js 34 | var HOOK_SETUP = "devtools-plugin:setup"; 35 | var HOOK_PLUGIN_SETTINGS_SET = "plugin:settings:set"; 36 | 37 | // node_modules/@vue/devtools-api/lib/esm/proxy.js 38 | var ApiProxy = class { 39 | constructor(plugin, hook) { 40 | this.target = null; 41 | this.targetQueue = []; 42 | this.onQueue = []; 43 | this.plugin = plugin; 44 | this.hook = hook; 45 | const defaultSettings = {}; 46 | if (plugin.settings) { 47 | for (const id in plugin.settings) { 48 | const item = plugin.settings[id]; 49 | defaultSettings[id] = item.defaultValue; 50 | } 51 | } 52 | const localSettingsSaveId = `__vue-devtools-plugin-settings__${plugin.id}`; 53 | let currentSettings = Object.assign({}, defaultSettings); 54 | try { 55 | const raw = localStorage.getItem(localSettingsSaveId); 56 | const data = JSON.parse(raw); 57 | Object.assign(currentSettings, data); 58 | } catch (e) { 59 | } 60 | this.fallbacks = { 61 | getSettings() { 62 | return currentSettings; 63 | }, 64 | setSettings(value) { 65 | try { 66 | localStorage.setItem(localSettingsSaveId, JSON.stringify(value)); 67 | } catch (e) { 68 | } 69 | currentSettings = value; 70 | }, 71 | now() { 72 | return now(); 73 | } 74 | }; 75 | if (hook) { 76 | hook.on(HOOK_PLUGIN_SETTINGS_SET, (pluginId, value) => { 77 | if (pluginId === this.plugin.id) { 78 | this.fallbacks.setSettings(value); 79 | } 80 | }); 81 | } 82 | this.proxiedOn = new Proxy({}, { 83 | get: (_target, prop) => { 84 | if (this.target) { 85 | return this.target.on[prop]; 86 | } else { 87 | return (...args) => { 88 | this.onQueue.push({ 89 | method: prop, 90 | args 91 | }); 92 | }; 93 | } 94 | } 95 | }); 96 | this.proxiedTarget = new Proxy({}, { 97 | get: (_target, prop) => { 98 | if (this.target) { 99 | return this.target[prop]; 100 | } else if (prop === "on") { 101 | return this.proxiedOn; 102 | } else if (Object.keys(this.fallbacks).includes(prop)) { 103 | return (...args) => { 104 | this.targetQueue.push({ 105 | method: prop, 106 | args, 107 | resolve: () => { 108 | } 109 | }); 110 | return this.fallbacks[prop](...args); 111 | }; 112 | } else { 113 | return (...args) => { 114 | return new Promise((resolve) => { 115 | this.targetQueue.push({ 116 | method: prop, 117 | args, 118 | resolve 119 | }); 120 | }); 121 | }; 122 | } 123 | } 124 | }); 125 | } 126 | async setRealTarget(target) { 127 | this.target = target; 128 | for (const item of this.onQueue) { 129 | this.target.on[item.method](...item.args); 130 | } 131 | for (const item of this.targetQueue) { 132 | item.resolve(await this.target[item.method](...item.args)); 133 | } 134 | } 135 | }; 136 | 137 | // node_modules/@vue/devtools-api/lib/esm/index.js 138 | function setupDevtoolsPlugin(pluginDescriptor, setupFn) { 139 | const descriptor = pluginDescriptor; 140 | const target = getTarget(); 141 | const hook = getDevtoolsGlobalHook(); 142 | const enableProxy = isProxyAvailable && descriptor.enableEarlyProxy; 143 | if (hook && (target.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__ || !enableProxy)) { 144 | hook.emit(HOOK_SETUP, pluginDescriptor, setupFn); 145 | } else { 146 | const proxy = enableProxy ? new ApiProxy(descriptor, hook) : null; 147 | const list = target.__VUE_DEVTOOLS_PLUGINS__ = target.__VUE_DEVTOOLS_PLUGINS__ || []; 148 | list.push({ 149 | pluginDescriptor: descriptor, 150 | setupFn, 151 | proxy 152 | }); 153 | if (proxy) 154 | setupFn(proxy.proxiedTarget); 155 | } 156 | } 157 | 158 | export { 159 | isPerformanceSupported, 160 | now, 161 | setupDevtoolsPlugin 162 | }; 163 | //# sourceMappingURL=chunk-2M277TBP.js.map 164 | -------------------------------------------------------------------------------- /.vuepress/.cache/deps/chunk-FEFTYQ2P.js: -------------------------------------------------------------------------------- 1 | //# sourceMappingURL=chunk-FEFTYQ2P.js.map 2 | -------------------------------------------------------------------------------- /.vuepress/.cache/deps/chunk-FEFTYQ2P.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "sources": [], 4 | "sourcesContent": [], 5 | "mappings": "", 6 | "names": [] 7 | } 8 | -------------------------------------------------------------------------------- /.vuepress/.cache/deps/package.json: -------------------------------------------------------------------------------- 1 | {"type":"module"} -------------------------------------------------------------------------------- /.vuepress/.cache/deps/vue.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "sources": [], 4 | "sourcesContent": [], 5 | "mappings": "", 6 | "names": [] 7 | } 8 | -------------------------------------------------------------------------------- /.vuepress/.temp/internal/clientConfigs.js: -------------------------------------------------------------------------------- 1 | import clientConfig0 from 'C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/plugin-active-header-links/lib/client/config.js' 2 | import clientConfig1 from 'C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/plugin-back-to-top/lib/client/config.js' 3 | import clientConfig2 from 'C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/plugin-external-link-icon/lib/client/config.js' 4 | import clientConfig3 from 'C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/plugin-medium-zoom/lib/client/config.js' 5 | import clientConfig4 from 'C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/plugin-nprogress/lib/client/config.js' 6 | import clientConfig5 from 'C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/plugin-theme-data/lib/client/config.js' 7 | import clientConfig6 from 'C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/theme-default/lib/client/config.js' 8 | import clientConfig7 from 'C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/.vuepress/.temp/register-components/clientConfig.091b98ea.js' 9 | 10 | export const clientConfigs = [ 11 | clientConfig0, 12 | clientConfig1, 13 | clientConfig2, 14 | clientConfig3, 15 | clientConfig4, 16 | clientConfig5, 17 | clientConfig6, 18 | clientConfig7, 19 | ] 20 | -------------------------------------------------------------------------------- /.vuepress/.temp/internal/layoutComponents.js: -------------------------------------------------------------------------------- 1 | import { defineAsyncComponent } from 'vue' 2 | 3 | export const layoutComponents = { 4 | "404": defineAsyncComponent(() => import("C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/theme-default/lib/client/layouts/404.vue")), 5 | "Layout": defineAsyncComponent(() => import("C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/node_modules/@vuepress/theme-default/lib/client/layouts/Layout.vue")), 6 | } 7 | -------------------------------------------------------------------------------- /.vuepress/.temp/internal/pagesRoutes.js: -------------------------------------------------------------------------------- 1 | import { Vuepress } from '@vuepress/client' 2 | 3 | const routeItems = [ 4 | ["v-61cfcd0a","/00.introduction.html",{"title":"Introduction"},["/00.introduction","/00.introduction.md"]], 5 | ["v-73005554","/CONTRIBUTING.html",{"title":"How to contribute"},["/CONTRIBUTING","/CONTRIBUTING.md"]], 6 | ["v-8daa1a0e","/",{"title":"Home"},["/index.html","/README.md"]], 7 | ["v-5c63ceb0","/1200.naming-conventions/azure-resources.html",{"title":"Azure Resources"},["/1200.naming-conventions/azure-resources","/1200.naming-conventions/azure-resources.md"]], 8 | ["v-50cbde04","/1200.naming-conventions/azure-tags.html",{"title":"Azure Tags"},["/1200.naming-conventions/azure-tags","/1200.naming-conventions/azure-tags.md"]], 9 | ["v-ba4dba04","/1200.naming-conventions/naming-conventions.html",{"title":"Naming conventions"},["/1200.naming-conventions/naming-conventions","/1200.naming-conventions/naming-conventions.md"]], 10 | ["v-d652d7a8","/1100.user-experience-design/ux-design.html",{"title":"UX design"},["/1100.user-experience-design/ux-design","/1100.user-experience-design/ux-design.md"]], 11 | ["v-695a5e6c","/1000.environment-configuration/DH1201.html",{"title":"Regel 1201"},["/1000.environment-configuration/DH1201","/1000.environment-configuration/DH1201.md"]], 12 | ["v-65f0ad2e","/1000.environment-configuration/DH1202.html",{"title":"Regel DH1202"},["/1000.environment-configuration/DH1202","/1000.environment-configuration/DH1202.md"]], 13 | ["v-6286fbf0","/1000.environment-configuration/DH1203.html",{"title":"Regel 1203"},["/1000.environment-configuration/DH1203","/1000.environment-configuration/DH1203.md"]], 14 | ["v-6f09952d","/1000.environment-configuration/installation-configuration.html",{"title":"This is another rule 3"},["/1000.environment-configuration/installation-configuration","/1000.environment-configuration/installation-configuration.md"]], 15 | ["v-6cf4ec6e","/1000.environment-configuration/",{"title":"Overview"},["/1000.environment-configuration/index.html","/1000.environment-configuration/README.md"]], 16 | ["v-0cf8cfc0","/1300.customization/entity-design.html",{"title":"Entity design"},["/1300.customization/entity-design","/1300.customization/entity-design.md"]], 17 | ["v-bbf2e5b6","/1400.extending-client-side/extending-clientside.html",{"title":"Extending client-side"},["/1400.extending-client-side/extending-clientside","/1400.extending-client-side/extending-clientside.md"]], 18 | ["v-53892bf6","/1500.extending-server-side/extending-serverside.html",{"title":"Extending server-side"},["/1500.extending-server-side/extending-serverside","/1500.extending-server-side/extending-serverside.md"]], 19 | ["v-287069e4","/1600.external-applications/external-applications.html",{"title":"External applications"},["/1600.external-applications/external-applications","/1600.external-applications/external-applications.md"]], 20 | ["v-2167bd5a","/1700.design-patterns/design-patterns.html",{"title":"Design Patterns"},["/1700.design-patterns/design-patterns","/1700.design-patterns/design-patterns.md"]], 21 | ["v-6f172275","/1800.data-migrations/datamigrations.html",{"title":"Data migrations"},["/1800.data-migrations/datamigrations","/1800.data-migrations/datamigrations.md"]], 22 | ["v-17bb38ad","/2000.guidelines/possible-structure.html",{"title":"Guidelines Dynamichands"},["/2000.guidelines/possible-structure","/2000.guidelines/possible-structure.md"]], 23 | ["v-df17b1fa","/2000.guidelines/rules-list-test.html",{"title":"Rule list based on pages"},["/2000.guidelines/rules-list-test","/2000.guidelines/rules-list-test.md"]], 24 | ["v-0edc2073","/2000.guidelines/tools.html",{"title":"Tools"},["/2000.guidelines/tools","/2000.guidelines/tools.md"]], 25 | ["v-14c6e1f6","/2000.guidelines/tryout-markdown.html",{"title":"Try-out"},["/2000.guidelines/tryout-markdown","/2000.guidelines/tryout-markdown.md"]], 26 | ["v-59a9b32e","/3000.powerautomate/powerautomate.html",{"title":"Power Automate"},["/3000.powerautomate/powerautomate","/3000.powerautomate/powerautomate.md"]], 27 | ["v-3706649a","/404.html",{"title":""},["/404"]], 28 | ] 29 | 30 | export const pagesRoutes = routeItems.reduce( 31 | (result, [name, path, meta, redirects]) => { 32 | result.push( 33 | { 34 | name, 35 | path, 36 | component: Vuepress, 37 | meta, 38 | }, 39 | ...redirects.map((item) => ({ 40 | path: item, 41 | redirect: path, 42 | })) 43 | ) 44 | return result 45 | }, 46 | [ 47 | { 48 | name: '404', 49 | path: '/:catchAll(.*)', 50 | component: Vuepress, 51 | } 52 | ] 53 | ) 54 | -------------------------------------------------------------------------------- /.vuepress/.temp/internal/siteData.js: -------------------------------------------------------------------------------- 1 | export const siteData = { 2 | "base": "/", 3 | "lang": "en-US", 4 | "title": "PowerApps Guidelines", 5 | "description": "Coding standards and Guidelines for Customizing and Extending PowerApps & Dynamics 365", 6 | "head": [ 7 | [ 8 | "link", 9 | { 10 | "rel": "apple-touch-icon", 11 | "sizes": "57x57", 12 | "href": "/apple-icon-57x57.png" 13 | } 14 | ], 15 | [ 16 | "link", 17 | { 18 | "rel": "apple-touch-icon", 19 | "sizes": "114x114", 20 | "href": "/apple-icon-114x114.png" 21 | } 22 | ], 23 | [ 24 | "link", 25 | { 26 | "rel": "apple-touch-icon", 27 | "sizes": "144x144", 28 | "href": "/apple-icon-144x144.png" 29 | } 30 | ], 31 | [ 32 | "link", 33 | { 34 | "rel": "apple-touch-icon", 35 | "sizes": "152x152", 36 | "href": "/apple-icon-152x152.png" 37 | } 38 | ], 39 | [ 40 | "link", 41 | { 42 | "rel": "icon", 43 | "sizes": "196x196", 44 | "href": "/favicon-196x196.png" 45 | } 46 | ], 47 | [ 48 | "link", 49 | { 50 | "rel": "icon", 51 | "sizes": "128x128", 52 | "href": "/favicon-128.png" 53 | } 54 | ], 55 | [ 56 | "link", 57 | { 58 | "rel": "icon", 59 | "sizes": "96x96", 60 | "href": "/favicon-96x96.png" 61 | } 62 | ], 63 | [ 64 | "link", 65 | { 66 | "rel": "icon", 67 | "sizes": "64x64", 68 | "href": "/favicon-64x64.png" 69 | } 70 | ], 71 | [ 72 | "link", 73 | { 74 | "rel": "icon", 75 | "sizes": "32x32", 76 | "href": "/favicon-32x32.png" 77 | } 78 | ], 79 | [ 80 | "link", 81 | { 82 | "rel": "icon", 83 | "sizes": "16x16", 84 | "href": "/favicon-16x16.png" 85 | } 86 | ], 87 | [ 88 | "meta", 89 | { 90 | "name": "msapplication-TileColor", 91 | "content": "#f18800" 92 | } 93 | ], 94 | [ 95 | "meta", 96 | { 97 | "name": "theme-color", 98 | "content": "#ffffff" 99 | } 100 | ] 101 | ], 102 | "locales": {} 103 | } 104 | 105 | if (import.meta.webpackHot) { 106 | import.meta.webpackHot.accept() 107 | if (__VUE_HMR_RUNTIME__.updateSiteData) { 108 | __VUE_HMR_RUNTIME__.updateSiteData(siteData) 109 | } 110 | } 111 | 112 | if (import.meta.hot) { 113 | import.meta.hot.accept(({ siteData }) => { 114 | __VUE_HMR_RUNTIME__.updateSiteData(siteData) 115 | }) 116 | } 117 | -------------------------------------------------------------------------------- /.vuepress/.temp/internal/themeData.js: -------------------------------------------------------------------------------- 1 | export const themeData = { 2 | "repo": "AutomateValue/PowerApps-Guidelines", 3 | "editLink": true, 4 | "logo": "/logo.png", 5 | "navbar": [ 6 | { 7 | "text": "Home", 8 | "link": "/" 9 | }, 10 | { 11 | "text": "AutomateValue", 12 | "link": "https://automatevalue.com" 13 | } 14 | ], 15 | "sidebar": [ 16 | "00.introduction", 17 | { 18 | "title": "Environment Configuration", 19 | "children": [ 20 | "/1000.environment-configuration/", 21 | "/1000.environment-configuration/DH1201", 22 | "/1000.environment-configuration/DH1202", 23 | "/1000.environment-configuration/DH1203", 24 | "/1000.environment-configuration/installation-configuration" 25 | ], 26 | "text": "Environment Configuration" 27 | }, 28 | { 29 | "title": "User Experience-Design", 30 | "children": [ 31 | "/1100.user-experience-design/ux-design" 32 | ], 33 | "text": "User Experience-Design" 34 | }, 35 | { 36 | "title": "Naming Conventions", 37 | "children": [ 38 | "/1200.naming-conventions/azure-resources", 39 | "/1200.naming-conventions/azure-tags", 40 | "/1200.naming-conventions/naming-conventions" 41 | ], 42 | "text": "Naming Conventions" 43 | }, 44 | { 45 | "title": "Customization", 46 | "children": [ 47 | "/1300.customization/entity-design" 48 | ], 49 | "text": "Customization" 50 | }, 51 | { 52 | "title": "Extending Client-Side", 53 | "children": [ 54 | "/1400.extending-client-side/extending-clientside" 55 | ], 56 | "text": "Extending Client-Side" 57 | }, 58 | { 59 | "title": "Extending Server-Side", 60 | "children": [ 61 | "/1500.extending-server-side/extending-serverside" 62 | ], 63 | "text": "Extending Server-Side" 64 | }, 65 | { 66 | "title": "External Applications", 67 | "children": [ 68 | "/1600.external-applications/external-applications" 69 | ], 70 | "text": "External Applications" 71 | }, 72 | { 73 | "title": "Design Patterns", 74 | "children": [ 75 | "/1700.design-patterns/design-patterns" 76 | ], 77 | "text": "Design Patterns" 78 | }, 79 | { 80 | "title": "Data Migrations", 81 | "children": [ 82 | "/1800.data-migrations/datamigrations" 83 | ], 84 | "text": "Data Migrations" 85 | }, 86 | { 87 | "title": "Guidelines", 88 | "children": [ 89 | "/2000.guidelines/possible-structure", 90 | "/2000.guidelines/rules-list-test", 91 | "/2000.guidelines/tools", 92 | "/2000.guidelines/tryout-markdown" 93 | ], 94 | "text": "Guidelines" 95 | }, 96 | { 97 | "title": "Powerautomate", 98 | "children": [ 99 | "/3000.powerautomate/powerautomate" 100 | ], 101 | "text": "Powerautomate" 102 | }, 103 | "CONTRIBUTING" 104 | ], 105 | "locales": { 106 | "/": { 107 | "selectLanguageName": "English" 108 | } 109 | }, 110 | "darkMode": true, 111 | "selectLanguageText": "Languages", 112 | "selectLanguageAriaLabel": "Select language", 113 | "sidebarDepth": 2, 114 | "editLinkText": "Edit this page", 115 | "lastUpdated": true, 116 | "lastUpdatedText": "Last Updated", 117 | "contributors": true, 118 | "contributorsText": "Contributors", 119 | "notFound": [ 120 | "There's nothing here.", 121 | "How did we get here?", 122 | "That's a Four-Oh-Four.", 123 | "Looks like we've got some broken links." 124 | ], 125 | "backToHome": "Take me home", 126 | "openInNewWindow": "open in new window", 127 | "toggleDarkMode": "toggle dark mode", 128 | "toggleSidebar": "toggle sidebar" 129 | } 130 | 131 | if (import.meta.webpackHot) { 132 | import.meta.webpackHot.accept() 133 | if (__VUE_HMR_RUNTIME__.updateThemeData) { 134 | __VUE_HMR_RUNTIME__.updateThemeData(themeData) 135 | } 136 | } 137 | 138 | if (import.meta.hot) { 139 | import.meta.hot.accept(({ themeData }) => { 140 | __VUE_HMR_RUNTIME__.updateThemeData(themeData) 141 | }) 142 | } 143 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/00.introduction.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-61cfcd0a", 3 | "path": "/00.introduction.html", 4 | "title": "Introduction", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Why would you use this guidelines", 12 | "slug": "why-would-you-use-this-guidelines", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Basic principles", 18 | "slug": "basic-principles", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "How do you get started", 24 | "slug": "how-do-you-get-started", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "To which guidelines should you comply", 30 | "slug": "to-which-guidelines-should-you-comply", 31 | "children": [] 32 | } 33 | ], 34 | "git": { 35 | "updatedTime": 1591459257000, 36 | "contributors": [ 37 | { 38 | "name": "remyvd", 39 | "email": "remy.vanduijkeren@dynamichands.nl", 40 | "commits": 1 41 | } 42 | ] 43 | }, 44 | "filePathRelative": "00.introduction.md" 45 | } 46 | 47 | if (import.meta.webpackHot) { 48 | import.meta.webpackHot.accept() 49 | if (__VUE_HMR_RUNTIME__.updatePageData) { 50 | __VUE_HMR_RUNTIME__.updatePageData(data) 51 | } 52 | } 53 | 54 | if (import.meta.hot) { 55 | import.meta.hot.accept(({ data }) => { 56 | __VUE_HMR_RUNTIME__.updatePageData(data) 57 | }) 58 | } 59 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/00.introduction.html.vue: -------------------------------------------------------------------------------- 1 | 44 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/DH1201.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-3b778a90", 3 | "path": "/01.guide/1000.environment-configuration/DH1201.html", 4 | "title": "Another test rule", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1201, 8 | "rule_category": "class-design", 9 | "title": "Another test rule", 10 | "severity": "Required", 11 | "read_more": true 12 | }, 13 | "excerpt": "

# Title DH1201

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n
", 14 | "headers": [], 15 | "git": { 16 | "updatedTime": null, 17 | "contributors": [] 18 | }, 19 | "filePathRelative": "01.guide/1000.environment-configuration/DH1201.md" 20 | } 21 | 22 | if (import.meta.webpackHot) { 23 | import.meta.webpackHot.accept() 24 | if (__VUE_HMR_RUNTIME__.updatePageData) { 25 | __VUE_HMR_RUNTIME__.updatePageData(data) 26 | } 27 | } 28 | 29 | if (import.meta.hot) { 30 | import.meta.hot.accept(({ data }) => { 31 | __VUE_HMR_RUNTIME__.updatePageData(data) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/DH1201.html.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/DH1202.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-380dd952", 3 | "path": "/01.guide/1000.environment-configuration/DH1202.html", 4 | "title": "Title DH1202", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1202, 8 | "rule_category": "class-design", 9 | "title": "Title DH1202", 10 | "severity": "Recommended", 11 | "read_more": false 12 | }, 13 | "excerpt": "

# Title DH1202

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n

Which I don't like, because you're repeating the abbreviation Id. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition:

\n
var contactId = ((EntityReference)customMethod[\"dh_Contact\"]).Id;\n
", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Title DH1202", 18 | "slug": "title-dh1202", 19 | "children": [] 20 | } 21 | ], 22 | "git": { 23 | "updatedTime": null, 24 | "contributors": [] 25 | }, 26 | "filePathRelative": "01.guide/1000.environment-configuration/DH1202.md" 27 | } 28 | 29 | if (import.meta.webpackHot) { 30 | import.meta.webpackHot.accept() 31 | if (__VUE_HMR_RUNTIME__.updatePageData) { 32 | __VUE_HMR_RUNTIME__.updatePageData(data) 33 | } 34 | } 35 | 36 | if (import.meta.hot) { 37 | import.meta.hot.accept(({ data }) => { 38 | __VUE_HMR_RUNTIME__.updatePageData(data) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/DH1202.html.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/DH1203.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-34a42814", 3 | "path": "/01.guide/1000.environment-configuration/DH1203.html", 4 | "title": "This is another rule 3", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1203, 8 | "rule_category": "class-design", 9 | "title": "This is another rule 3", 10 | "severity": "Depends", 11 | "read_more": false 12 | }, 13 | "excerpt": "

# Title DH1203

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n

Which I don't like, because you're repeating the abbreviation Id. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition:

\n
var contactId = ((EntityReference)customMethod[\"dh_Contact\"]).Id;\n
", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Title DH1203", 18 | "slug": "title-dh1203", 19 | "children": [] 20 | } 21 | ], 22 | "git": { 23 | "updatedTime": null, 24 | "contributors": [] 25 | }, 26 | "filePathRelative": "01.guide/1000.environment-configuration/DH1203.md" 27 | } 28 | 29 | if (import.meta.webpackHot) { 30 | import.meta.webpackHot.accept() 31 | if (__VUE_HMR_RUNTIME__.updatePageData) { 32 | __VUE_HMR_RUNTIME__.updatePageData(data) 33 | } 34 | } 35 | 36 | if (import.meta.hot) { 37 | import.meta.hot.accept(({ data }) => { 38 | __VUE_HMR_RUNTIME__.updatePageData(data) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/DH1203.html.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/index.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-1793089b", 3 | "path": "/01.guide/1000.environment-configuration/", 4 | "title": "Overview", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [], 9 | "git": { 10 | "updatedTime": null, 11 | "contributors": [] 12 | }, 13 | "filePathRelative": "01.guide/1000.environment-configuration/README.md" 14 | } 15 | 16 | if (import.meta.webpackHot) { 17 | import.meta.webpackHot.accept() 18 | if (__VUE_HMR_RUNTIME__.updatePageData) { 19 | __VUE_HMR_RUNTIME__.updatePageData(data) 20 | } 21 | } 22 | 23 | if (import.meta.hot) { 24 | import.meta.hot.accept(({ data }) => { 25 | __VUE_HMR_RUNTIME__.updatePageData(data) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/index.html.vue: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/installation-configuration.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-1660bc1b", 3 | "path": "/01.guide/1000.environment-configuration/installation-configuration.html", 4 | "title": "This is another rule 3", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1204, 8 | "rule_category": "class-design", 9 | "title": "This is another rule 3", 10 | "severity": "Depends", 11 | "read_more": false 12 | }, 13 | "excerpt": "", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Default environment is the Personal shared playground (shared)", 18 | "slug": "default-environment-is-the-personal-shared-playground-shared", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Deployment stratagy for customer type 1 & 2", 24 | "slug": "deployment-stratagy-for-customer-type-1-2", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "The five layers of security", 30 | "slug": "the-five-layers-of-security", 31 | "children": [] 32 | }, 33 | { 34 | "level": 2, 35 | "title": "Pervent data leakage", 36 | "slug": "pervent-data-leakage", 37 | "children": [] 38 | }, 39 | { 40 | "level": 2, 41 | "title": "Security", 42 | "slug": "security", 43 | "children": [] 44 | }, 45 | { 46 | "level": 2, 47 | "title": "Solutions", 48 | "slug": "solutions", 49 | "children": [] 50 | } 51 | ], 52 | "git": { 53 | "updatedTime": null, 54 | "contributors": [] 55 | }, 56 | "filePathRelative": "01.guide/1000.environment-configuration/installation-configuration.md" 57 | } 58 | 59 | if (import.meta.webpackHot) { 60 | import.meta.webpackHot.accept() 61 | if (__VUE_HMR_RUNTIME__.updatePageData) { 62 | __VUE_HMR_RUNTIME__.updatePageData(data) 63 | } 64 | } 65 | 66 | if (import.meta.hot) { 67 | import.meta.hot.accept(({ data }) => { 68 | __VUE_HMR_RUNTIME__.updatePageData(data) 69 | }) 70 | } 71 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/01.guide/1000.environment-configuration/installation-configuration.html.vue: -------------------------------------------------------------------------------- 1 | 65 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/DH1201.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-10871e6d", 3 | "path": "/02.environment-configuration/DH1201.html", 4 | "title": "Another test rule", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1201, 8 | "rule_category": "class-design", 9 | "title": "Another test rule", 10 | "severity": "Required", 11 | "read_more": true 12 | }, 13 | "excerpt": "

# Title DH1201

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n
", 14 | "headers": [], 15 | "git": { 16 | "updatedTime": null, 17 | "contributors": [] 18 | }, 19 | "filePathRelative": "02.environment-configuration/DH1201.md" 20 | } 21 | 22 | if (import.meta.webpackHot) { 23 | import.meta.webpackHot.accept() 24 | if (__VUE_HMR_RUNTIME__.updatePageData) { 25 | __VUE_HMR_RUNTIME__.updatePageData(data) 26 | } 27 | } 28 | 29 | if (import.meta.hot) { 30 | import.meta.hot.accept(({ data }) => { 31 | __VUE_HMR_RUNTIME__.updatePageData(data) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/DH1201.html.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/DH1202.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-123bf70c", 3 | "path": "/02.environment-configuration/DH1202.html", 4 | "title": "Title DH1202", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1202, 8 | "rule_category": "class-design", 9 | "title": "Title DH1202", 10 | "severity": "Recommended", 11 | "read_more": false 12 | }, 13 | "excerpt": "

# Title DH1202

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n

Which I don't like, because you're repeating the abbreviation Id. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition:

\n
var contactId = ((EntityReference)customMethod[\"dh_Contact\"]).Id;\n
", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Title DH1202", 18 | "slug": "title-dh1202", 19 | "children": [] 20 | } 21 | ], 22 | "git": { 23 | "updatedTime": null, 24 | "contributors": [] 25 | }, 26 | "filePathRelative": "02.environment-configuration/DH1202.md" 27 | } 28 | 29 | if (import.meta.webpackHot) { 30 | import.meta.webpackHot.accept() 31 | if (__VUE_HMR_RUNTIME__.updatePageData) { 32 | __VUE_HMR_RUNTIME__.updatePageData(data) 33 | } 34 | } 35 | 36 | if (import.meta.hot) { 37 | import.meta.hot.accept(({ data }) => { 38 | __VUE_HMR_RUNTIME__.updatePageData(data) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/DH1202.html.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/DH1203.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-13f0cfab", 3 | "path": "/02.environment-configuration/DH1203.html", 4 | "title": "This is another rule 3", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1203, 8 | "rule_category": "class-design", 9 | "title": "This is another rule 3", 10 | "severity": "Depends", 11 | "read_more": false 12 | }, 13 | "excerpt": "

# Title DH1203

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n

Which I don't like, because you're repeating the abbreviation Id. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition:

\n
var contactId = ((EntityReference)customMethod[\"dh_Contact\"]).Id;\n
", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Title DH1203", 18 | "slug": "title-dh1203", 19 | "children": [] 20 | } 21 | ], 22 | "git": { 23 | "updatedTime": null, 24 | "contributors": [] 25 | }, 26 | "filePathRelative": "02.environment-configuration/DH1203.md" 27 | } 28 | 29 | if (import.meta.webpackHot) { 30 | import.meta.webpackHot.accept() 31 | if (__VUE_HMR_RUNTIME__.updatePageData) { 32 | __VUE_HMR_RUNTIME__.updatePageData(data) 33 | } 34 | } 35 | 36 | if (import.meta.hot) { 37 | import.meta.hot.accept(({ data }) => { 38 | __VUE_HMR_RUNTIME__.updatePageData(data) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/DH1203.html.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/index.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-72cd37f4", 3 | "path": "/02.environment-configuration/", 4 | "title": "Overview", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [], 9 | "git": { 10 | "updatedTime": null, 11 | "contributors": [] 12 | }, 13 | "filePathRelative": "02.environment-configuration/README.md" 14 | } 15 | 16 | if (import.meta.webpackHot) { 17 | import.meta.webpackHot.accept() 18 | if (__VUE_HMR_RUNTIME__.updatePageData) { 19 | __VUE_HMR_RUNTIME__.updatePageData(data) 20 | } 21 | } 22 | 23 | if (import.meta.hot) { 24 | import.meta.hot.accept(({ data }) => { 25 | __VUE_HMR_RUNTIME__.updatePageData(data) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/index.html.vue: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/installation-configuration.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-1979b350", 3 | "path": "/02.environment-configuration/installation-configuration.html", 4 | "title": "This is another rule 3", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1204, 8 | "rule_category": "class-design", 9 | "title": "This is another rule 3", 10 | "severity": "Depends", 11 | "read_more": false 12 | }, 13 | "excerpt": "", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Default environment is the Personal shared playground (shared)", 18 | "slug": "default-environment-is-the-personal-shared-playground-shared", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Deployment stratagy for customer type 1 & 2", 24 | "slug": "deployment-stratagy-for-customer-type-1-2", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "The five layers of security", 30 | "slug": "the-five-layers-of-security", 31 | "children": [] 32 | }, 33 | { 34 | "level": 2, 35 | "title": "Pervent data leakage", 36 | "slug": "pervent-data-leakage", 37 | "children": [] 38 | }, 39 | { 40 | "level": 2, 41 | "title": "Security", 42 | "slug": "security", 43 | "children": [] 44 | }, 45 | { 46 | "level": 2, 47 | "title": "Solutions", 48 | "slug": "solutions", 49 | "children": [] 50 | } 51 | ], 52 | "git": { 53 | "updatedTime": null, 54 | "contributors": [] 55 | }, 56 | "filePathRelative": "02.environment-configuration/installation-configuration.md" 57 | } 58 | 59 | if (import.meta.webpackHot) { 60 | import.meta.webpackHot.accept() 61 | if (__VUE_HMR_RUNTIME__.updatePageData) { 62 | __VUE_HMR_RUNTIME__.updatePageData(data) 63 | } 64 | } 65 | 66 | if (import.meta.hot) { 67 | import.meta.hot.accept(({ data }) => { 68 | __VUE_HMR_RUNTIME__.updatePageData(data) 69 | }) 70 | } 71 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/02.environment-configuration/installation-configuration.html.vue: -------------------------------------------------------------------------------- 1 | 65 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/DH1201.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-695a5e6c", 3 | "path": "/1000.environment-configuration/DH1201.html", 4 | "title": "Regel 1201", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1201, 8 | "rule_category": "class-design", 9 | "title": "Regel 1201", 10 | "severity": "Required", 11 | "read_more": true 12 | }, 13 | "excerpt": "

# Title DH1201

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n
", 14 | "headers": [], 15 | "git": { 16 | "updatedTime": 1654501708000, 17 | "contributors": [ 18 | { 19 | "name": "remyvd", 20 | "email": "remy.vanduijkeren@dynamichands.nl", 21 | "commits": 1 22 | }, 23 | { 24 | "name": "remyvd", 25 | "email": "remy@automatevalue.com", 26 | "commits": 1 27 | } 28 | ] 29 | }, 30 | "filePathRelative": "1000.environment-configuration/DH1201.md" 31 | } 32 | 33 | if (import.meta.webpackHot) { 34 | import.meta.webpackHot.accept() 35 | if (__VUE_HMR_RUNTIME__.updatePageData) { 36 | __VUE_HMR_RUNTIME__.updatePageData(data) 37 | } 38 | } 39 | 40 | if (import.meta.hot) { 41 | import.meta.hot.accept(({ data }) => { 42 | __VUE_HMR_RUNTIME__.updatePageData(data) 43 | }) 44 | } 45 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/DH1201.html.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/DH1202.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-65f0ad2e", 3 | "path": "/1000.environment-configuration/DH1202.html", 4 | "title": "Regel DH1202", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1202, 8 | "rule_category": "class-design", 9 | "title": "Regel DH1202", 10 | "severity": "Recommended", 11 | "read_more": false 12 | }, 13 | "excerpt": "

# Title DH1202

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n

Which I don't like, because you're repeating the abbreviation Id. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition:

\n
var contactId = ((EntityReference)customMethod[\"dh_Contact\"]).Id;\n
", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Title DH1202", 18 | "slug": "title-dh1202", 19 | "children": [] 20 | } 21 | ], 22 | "git": { 23 | "updatedTime": 1654501708000, 24 | "contributors": [ 25 | { 26 | "name": "remyvd", 27 | "email": "remy.vanduijkeren@dynamichands.nl", 28 | "commits": 1 29 | }, 30 | { 31 | "name": "remyvd", 32 | "email": "remy@automatevalue.com", 33 | "commits": 1 34 | } 35 | ] 36 | }, 37 | "filePathRelative": "1000.environment-configuration/DH1202.md" 38 | } 39 | 40 | if (import.meta.webpackHot) { 41 | import.meta.webpackHot.accept() 42 | if (__VUE_HMR_RUNTIME__.updatePageData) { 43 | __VUE_HMR_RUNTIME__.updatePageData(data) 44 | } 45 | } 46 | 47 | if (import.meta.hot) { 48 | import.meta.hot.accept(({ data }) => { 49 | __VUE_HMR_RUNTIME__.updatePageData(data) 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/DH1202.html.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/DH1203.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-6286fbf0", 3 | "path": "/1000.environment-configuration/DH1203.html", 4 | "title": "Regel 1203", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1203, 8 | "rule_category": "class-design", 9 | "title": "Regel 1203", 10 | "severity": "Depends", 11 | "read_more": false 12 | }, 13 | "excerpt": "

# Title DH1203

\n

This Id always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the Id in code you use this:

\n
var contactId = ((EntityReference)customMethod[\"dh_ContactId\"]).Id;\n

Which I don't like, because you're repeating the abbreviation Id. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition:

\n
var contactId = ((EntityReference)customMethod[\"dh_Contact\"]).Id;\n
", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Title DH1203", 18 | "slug": "title-dh1203", 19 | "children": [] 20 | } 21 | ], 22 | "git": { 23 | "updatedTime": 1654501708000, 24 | "contributors": [ 25 | { 26 | "name": "remyvd", 27 | "email": "remy.vanduijkeren@dynamichands.nl", 28 | "commits": 1 29 | }, 30 | { 31 | "name": "remyvd", 32 | "email": "remy@automatevalue.com", 33 | "commits": 1 34 | } 35 | ] 36 | }, 37 | "filePathRelative": "1000.environment-configuration/DH1203.md" 38 | } 39 | 40 | if (import.meta.webpackHot) { 41 | import.meta.webpackHot.accept() 42 | if (__VUE_HMR_RUNTIME__.updatePageData) { 43 | __VUE_HMR_RUNTIME__.updatePageData(data) 44 | } 45 | } 46 | 47 | if (import.meta.hot) { 48 | import.meta.hot.accept(({ data }) => { 49 | __VUE_HMR_RUNTIME__.updatePageData(data) 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/DH1203.html.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/index.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-6cf4ec6e", 3 | "path": "/1000.environment-configuration/", 4 | "title": "Overview", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [], 9 | "git": { 10 | "updatedTime": 1654501708000, 11 | "contributors": [ 12 | { 13 | "name": "remyvd", 14 | "email": "remy.vanduijkeren@dynamichands.nl", 15 | "commits": 1 16 | }, 17 | { 18 | "name": "remyvd", 19 | "email": "remy@automatevalue.com", 20 | "commits": 1 21 | } 22 | ] 23 | }, 24 | "filePathRelative": "1000.environment-configuration/README.md" 25 | } 26 | 27 | if (import.meta.webpackHot) { 28 | import.meta.webpackHot.accept() 29 | if (__VUE_HMR_RUNTIME__.updatePageData) { 30 | __VUE_HMR_RUNTIME__.updatePageData(data) 31 | } 32 | } 33 | 34 | if (import.meta.hot) { 35 | import.meta.hot.accept(({ data }) => { 36 | __VUE_HMR_RUNTIME__.updatePageData(data) 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/index.html.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/installation-configuration.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-6f09952d", 3 | "path": "/1000.environment-configuration/installation-configuration.html", 4 | "title": "This is another rule 3", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "rule_id": 1204, 8 | "rule_category": "class-design", 9 | "title": "This is another rule 3", 10 | "severity": "Depends", 11 | "read_more": false 12 | }, 13 | "excerpt": "", 14 | "headers": [ 15 | { 16 | "level": 2, 17 | "title": "Default environment is the Personal shared playground (shared)", 18 | "slug": "default-environment-is-the-personal-shared-playground-shared", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Deployment stratagy for customer type 1 & 2", 24 | "slug": "deployment-stratagy-for-customer-type-1-2", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "The five layers of security", 30 | "slug": "the-five-layers-of-security", 31 | "children": [] 32 | }, 33 | { 34 | "level": 2, 35 | "title": "Pervent data leakage", 36 | "slug": "pervent-data-leakage", 37 | "children": [] 38 | }, 39 | { 40 | "level": 2, 41 | "title": "Security", 42 | "slug": "security", 43 | "children": [] 44 | }, 45 | { 46 | "level": 2, 47 | "title": "Solutions", 48 | "slug": "solutions", 49 | "children": [] 50 | } 51 | ], 52 | "git": { 53 | "updatedTime": 1654485104000, 54 | "contributors": [ 55 | { 56 | "name": "remyvd", 57 | "email": "remy.vanduijkeren@dynamichands.nl", 58 | "commits": 3 59 | }, 60 | { 61 | "name": "remyvd", 62 | "email": "remy@automatevalue.com", 63 | "commits": 1 64 | } 65 | ] 66 | }, 67 | "filePathRelative": "1000.environment-configuration/installation-configuration.md" 68 | } 69 | 70 | if (import.meta.webpackHot) { 71 | import.meta.webpackHot.accept() 72 | if (__VUE_HMR_RUNTIME__.updatePageData) { 73 | __VUE_HMR_RUNTIME__.updatePageData(data) 74 | } 75 | } 76 | 77 | if (import.meta.hot) { 78 | import.meta.hot.accept(({ data }) => { 79 | __VUE_HMR_RUNTIME__.updatePageData(data) 80 | }) 81 | } 82 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1000.environment-configuration/installation-configuration.html.vue: -------------------------------------------------------------------------------- 1 | 65 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1100.user-experience-design/ux-design.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-d652d7a8", 3 | "path": "/1100.user-experience-design/ux-design.html", 4 | "title": "UX design", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "1 Understand what User eXperience design means", 12 | "slug": "_1-understand-what-user-experience-design-means", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "2 Start from the navigation", 18 | "slug": "_2-start-from-the-navigation", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Addresses", 24 | "slug": "addresses", 25 | "children": [] 26 | } 27 | ], 28 | "git": { 29 | "updatedTime": 1626176054000, 30 | "contributors": [ 31 | { 32 | "name": "remyvd", 33 | "email": "remy.vanduijkeren@dynamichands.nl", 34 | "commits": 1 35 | }, 36 | { 37 | "name": "remyvd", 38 | "email": "remy@automatevalue.com", 39 | "commits": 1 40 | } 41 | ] 42 | }, 43 | "filePathRelative": "1100.user-experience-design/ux-design.md" 44 | } 45 | 46 | if (import.meta.webpackHot) { 47 | import.meta.webpackHot.accept() 48 | if (__VUE_HMR_RUNTIME__.updatePageData) { 49 | __VUE_HMR_RUNTIME__.updatePageData(data) 50 | } 51 | } 52 | 53 | if (import.meta.hot) { 54 | import.meta.hot.accept(({ data }) => { 55 | __VUE_HMR_RUNTIME__.updatePageData(data) 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1100.user-experience-design/ux-design.html.vue: -------------------------------------------------------------------------------- 1 | 51 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1200.naming-conventions/azure-resources.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-5c63ceb0", 3 | "path": "/1200.naming-conventions/azure-resources.html", 4 | "title": "Azure Resources", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Subscriptions and Resource groups", 12 | "slug": "subscriptions-and-resource-groups", 13 | "children": [] 14 | } 15 | ], 16 | "git": { 17 | "updatedTime": 1592906412000, 18 | "contributors": [ 19 | { 20 | "name": "remyvd", 21 | "email": "remy.vanduijkeren@dynamichands.nl", 22 | "commits": 1 23 | } 24 | ] 25 | }, 26 | "filePathRelative": "1200.naming-conventions/azure-resources.md" 27 | } 28 | 29 | if (import.meta.webpackHot) { 30 | import.meta.webpackHot.accept() 31 | if (__VUE_HMR_RUNTIME__.updatePageData) { 32 | __VUE_HMR_RUNTIME__.updatePageData(data) 33 | } 34 | } 35 | 36 | if (import.meta.hot) { 37 | import.meta.hot.accept(({ data }) => { 38 | __VUE_HMR_RUNTIME__.updatePageData(data) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1200.naming-conventions/azure-resources.html.vue: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1200.naming-conventions/azure-tags.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-50cbde04", 3 | "path": "/1200.naming-conventions/azure-tags.html", 4 | "title": "Azure Tags", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Must-haves", 12 | "slug": "must-haves", 13 | "children": [] 14 | } 15 | ], 16 | "git": { 17 | "updatedTime": 1592906412000, 18 | "contributors": [ 19 | { 20 | "name": "remyvd", 21 | "email": "remy.vanduijkeren@dynamichands.nl", 22 | "commits": 1 23 | } 24 | ] 25 | }, 26 | "filePathRelative": "1200.naming-conventions/azure-tags.md" 27 | } 28 | 29 | if (import.meta.webpackHot) { 30 | import.meta.webpackHot.accept() 31 | if (__VUE_HMR_RUNTIME__.updatePageData) { 32 | __VUE_HMR_RUNTIME__.updatePageData(data) 33 | } 34 | } 35 | 36 | if (import.meta.hot) { 37 | import.meta.hot.accept(({ data }) => { 38 | __VUE_HMR_RUNTIME__.updatePageData(data) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1200.naming-conventions/azure-tags.html.vue: -------------------------------------------------------------------------------- 1 | 70 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1200.naming-conventions/naming-conventions.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-ba4dba04", 3 | "path": "/1200.naming-conventions/naming-conventions.html", 4 | "title": "Naming conventions", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Environments must be named by purpose", 12 | "slug": "environments-must-be-named-by-purpose", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Don't use new_ as prefix", 18 | "slug": "don-t-use-new-as-prefix", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Don't use Id in the name of a lookup field", 24 | "slug": "don-t-use-id-in-the-name-of-a-lookup-field", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "One-To-Many relationships should have clear names", 30 | "slug": "one-to-many-relationships-should-have-clear-names", 31 | "children": [] 32 | }, 33 | { 34 | "level": 2, 35 | "title": "Many-To-Many relationships should have clear names", 36 | "slug": "many-to-many-relationships-should-have-clear-names", 37 | "children": [] 38 | } 39 | ], 40 | "git": { 41 | "updatedTime": 1591459257000, 42 | "contributors": [ 43 | { 44 | "name": "remyvd", 45 | "email": "remy.vanduijkeren@dynamichands.nl", 46 | "commits": 1 47 | } 48 | ] 49 | }, 50 | "filePathRelative": "1200.naming-conventions/naming-conventions.md" 51 | } 52 | 53 | if (import.meta.webpackHot) { 54 | import.meta.webpackHot.accept() 55 | if (__VUE_HMR_RUNTIME__.updatePageData) { 56 | __VUE_HMR_RUNTIME__.updatePageData(data) 57 | } 58 | } 59 | 60 | if (import.meta.hot) { 61 | import.meta.hot.accept(({ data }) => { 62 | __VUE_HMR_RUNTIME__.updatePageData(data) 63 | }) 64 | } 65 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1300.customization/entity-design.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-0cf8cfc0", 3 | "path": "/1300.customization/entity-design.html", 4 | "title": "Entity design", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "How do you decide between using a Lookup Field or an Option Set?", 12 | "slug": "how-do-you-decide-between-using-a-lookup-field-or-an-option-set", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Data Modeling as a team", 18 | "slug": "data-modeling-as-a-team", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Built-in vs. Custom Entities", 24 | "slug": "built-in-vs-custom-entities", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "User/Team vs. Organization", 30 | "slug": "user-team-vs-organization", 31 | "children": [] 32 | }, 33 | { 34 | "level": 2, 35 | "title": "Choosing other entity options", 36 | "slug": "choosing-other-entity-options", 37 | "children": [] 38 | }, 39 | { 40 | "level": 2, 41 | "title": "Existing vs. New Field", 42 | "slug": "existing-vs-new-field", 43 | "children": [] 44 | }, 45 | { 46 | "level": 2, 47 | "title": "Yes/No (or blank) choice", 48 | "slug": "yes-no-or-blank-choice", 49 | "children": [] 50 | }, 51 | { 52 | "level": 2, 53 | "title": "DateTime Fields", 54 | "slug": "datetime-fields", 55 | "children": [] 56 | }, 57 | { 58 | "level": 2, 59 | "title": "https://docs.microsoft.com/en-us/powerapps/maker/model-driven-apps/design-productive-forms", 60 | "slug": "https-docs-microsoft-com-en-us-powerapps-maker-model-driven-apps-design-productive-forms", 61 | "children": [] 62 | } 63 | ], 64 | "git": { 65 | "updatedTime": 1654135485000, 66 | "contributors": [ 67 | { 68 | "name": "remyvd", 69 | "email": "remy.vanduijkeren@dynamichands.nl", 70 | "commits": 2 71 | }, 72 | { 73 | "name": "remyvd", 74 | "email": "remy@automatevalue.com", 75 | "commits": 2 76 | } 77 | ] 78 | }, 79 | "filePathRelative": "1300.customization/entity-design.md" 80 | } 81 | 82 | if (import.meta.webpackHot) { 83 | import.meta.webpackHot.accept() 84 | if (__VUE_HMR_RUNTIME__.updatePageData) { 85 | __VUE_HMR_RUNTIME__.updatePageData(data) 86 | } 87 | } 88 | 89 | if (import.meta.hot) { 90 | import.meta.hot.accept(({ data }) => { 91 | __VUE_HMR_RUNTIME__.updatePageData(data) 92 | }) 93 | } 94 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1400.extending-client-side/extending-clientside.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-bbf2e5b6", 3 | "path": "/1400.extending-client-side/extending-clientside.html", 4 | "title": "Extending client-side", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Execution Context is automaticly given to OnChange and OnSave events", 12 | "slug": "execution-context-is-automaticly-given-to-onchange-and-onsave-events", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Don't use try...catch if you're not going to handle the error", 18 | "slug": "don-t-use-try-catch-if-you-re-not-going-to-handle-the-error", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "quetes in Dynamics 365", 24 | "slug": "quetes-in-dynamics-365", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "Use template strings instead of concatenation when it contains FetchXML", 30 | "slug": "use-template-strings-instead-of-concatenation-when-it-contains-fetchxml", 31 | "children": [] 32 | }, 33 | { 34 | "level": 2, 35 | "title": "seperate form and ribbon scripts", 36 | "slug": "seperate-form-and-ribbon-scripts", 37 | "children": [] 38 | }, 39 | { 40 | "level": 2, 41 | "title": "Don't change the javascript file or 'namespace' name that is being used in forms or ribbons (ISV)", 42 | "slug": "don-t-change-the-javascript-file-or-namespace-name-that-is-being-used-in-forms-or-ribbons-isv", 43 | "children": [] 44 | }, 45 | { 46 | "level": 2, 47 | "title": "Make only one event handler public for forms: the onLoadForm event handler (ISV)", 48 | "slug": "make-only-one-event-handler-public-for-forms-the-onloadform-event-handler-isv", 49 | "children": [] 50 | }, 51 | { 52 | "level": 2, 53 | "title": "Add onDataLoad and put fireOnChange in this method", 54 | "slug": "add-ondataload-and-put-fireonchange-in-this-method", 55 | "children": [] 56 | }, 57 | { 58 | "level": 2, 59 | "title": "Use x == null to check for undefined and null", 60 | "slug": "use-x-null-to-check-for-undefined-and-null", 61 | "children": [] 62 | }, 63 | { 64 | "level": 2, 65 | "title": "use check for truthy (or falsy)", 66 | "slug": "use-check-for-truthy-or-falsy", 67 | "children": [] 68 | }, 69 | { 70 | "level": 2, 71 | "title": "prefer IFFE Module pattern above others", 72 | "slug": "prefer-iffe-module-pattern-above-others", 73 | "children": [] 74 | }, 75 | { 76 | "level": 2, 77 | "title": "Remove braces from id's when doing OData calls", 78 | "slug": "remove-braces-from-id-s-when-doing-odata-calls", 79 | "children": [] 80 | }, 81 | { 82 | "level": 2, 83 | "title": "use ES2019 as target", 84 | "slug": "use-es2019-as-target", 85 | "children": [] 86 | }, 87 | { 88 | "level": 2, 89 | "title": "Clear notification at start of function", 90 | "slug": "clear-notification-at-start-of-function", 91 | "children": [] 92 | }, 93 | { 94 | "level": 2, 95 | "title": "Prevent 'Save & Create new' on Quick Create Form", 96 | "slug": "prevent-save-create-new-on-quick-create-form", 97 | "children": [] 98 | }, 99 | { 100 | "level": 2, 101 | "title": "Don't minifier javascript code", 102 | "slug": "don-t-minifier-javascript-code", 103 | "children": [] 104 | }, 105 | { 106 | "level": 2, 107 | "title": "First email or reply to", 108 | "slug": "first-email-or-reply-to", 109 | "children": [] 110 | }, 111 | { 112 | "level": 2, 113 | "title": "Set Form paramaters with the name and expected value", 114 | "slug": "set-form-paramaters-with-the-name-and-expected-value", 115 | "children": [] 116 | }, 117 | { 118 | "level": 2, 119 | "title": "", 120 | "slug": "", 121 | "children": [] 122 | } 123 | ], 124 | "git": { 125 | "updatedTime": 1646020873000, 126 | "contributors": [ 127 | { 128 | "name": "remyvd", 129 | "email": "remy.vanduijkeren@dynamichands.nl", 130 | "commits": 3 131 | }, 132 | { 133 | "name": "remyvd", 134 | "email": "remy@automatevalue.com", 135 | "commits": 3 136 | } 137 | ] 138 | }, 139 | "filePathRelative": "1400.extending-client-side/extending-clientside.md" 140 | } 141 | 142 | if (import.meta.webpackHot) { 143 | import.meta.webpackHot.accept() 144 | if (__VUE_HMR_RUNTIME__.updatePageData) { 145 | __VUE_HMR_RUNTIME__.updatePageData(data) 146 | } 147 | } 148 | 149 | if (import.meta.hot) { 150 | import.meta.hot.accept(({ data }) => { 151 | __VUE_HMR_RUNTIME__.updatePageData(data) 152 | }) 153 | } 154 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1500.extending-server-side/extending-serverside.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-53892bf6", 3 | "path": "/1500.extending-server-side/extending-serverside.html", 4 | "title": "Extending server-side", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Plugins & Workflow Activities must be stateless", 12 | "slug": "plugins-workflow-activities-must-be-stateless", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Always wrap the OrganizationServiceContext class", 18 | "slug": "always-wrap-the-organizationservicecontext-class", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Always implement paging for RetrieveMultiple when not using TopCount", 24 | "slug": "always-implement-paging-for-retrievemultiple-when-not-using-topcount", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "Exceptions thrown towards the platform within Plugins & Workflow Activities should always be of type 'InvalidPluginExecutionException' and contain an error code for identification", 30 | "slug": "exceptions-thrown-towards-the-platform-within-plugins-workflow-activities-should-always-be-of-type-invalidpluginexecutionexception-and-contain-an-error-code-for-identification", 31 | "children": [] 32 | }, 33 | { 34 | "level": 2, 35 | "title": "Use filtering attributes in plugin registration to improve performance", 36 | "slug": "use-filtering-attributes-in-plugin-registration-to-improve-performance", 37 | "children": [] 38 | }, 39 | { 40 | "level": 2, 41 | "title": "Make Plugins & Workflows asynchronous if possible to improve performance", 42 | "slug": "make-plugins-workflows-asynchronous-if-possible-to-improve-performance", 43 | "children": [] 44 | }, 45 | { 46 | "level": 2, 47 | "title": "Don't impersonate a user not knowing it is existing active user", 48 | "slug": "don-t-impersonate-a-user-not-knowing-it-is-existing-active-user", 49 | "children": [] 50 | }, 51 | { 52 | "level": 2, 53 | "title": "Write QueryExpressions as simple as possible", 54 | "slug": "write-queryexpressions-as-simple-as-possible", 55 | "children": [] 56 | }, 57 | { 58 | "level": 2, 59 | "title": "Try to use GetAttributeValue", 60 | "slug": "try-to-use-getattributevalue", 61 | "children": [] 62 | }, 63 | { 64 | "level": 2, 65 | "title": "Don't put every plugin in a seprate project", 66 | "slug": "don-t-put-every-plugin-in-a-seprate-project", 67 | "children": [] 68 | } 69 | ], 70 | "git": { 71 | "updatedTime": 1626176054000, 72 | "contributors": [ 73 | { 74 | "name": "remyvd", 75 | "email": "remy.vanduijkeren@dynamichands.nl", 76 | "commits": 3 77 | }, 78 | { 79 | "name": "remyvd", 80 | "email": "remy@automatevalue.com", 81 | "commits": 1 82 | } 83 | ] 84 | }, 85 | "filePathRelative": "1500.extending-server-side/extending-serverside.md" 86 | } 87 | 88 | if (import.meta.webpackHot) { 89 | import.meta.webpackHot.accept() 90 | if (__VUE_HMR_RUNTIME__.updatePageData) { 91 | __VUE_HMR_RUNTIME__.updatePageData(data) 92 | } 93 | } 94 | 95 | if (import.meta.hot) { 96 | import.meta.hot.accept(({ data }) => { 97 | __VUE_HMR_RUNTIME__.updatePageData(data) 98 | }) 99 | } 100 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1600.external-applications/external-applications.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-287069e4", 3 | "path": "/1600.external-applications/external-applications.html", 4 | "title": "External applications", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Implement handling of API limits for external applications", 12 | "slug": "implement-handling-of-api-limits-for-external-applications", 13 | "children": [] 14 | } 15 | ], 16 | "git": { 17 | "updatedTime": 1591459257000, 18 | "contributors": [ 19 | { 20 | "name": "remyvd", 21 | "email": "remy.vanduijkeren@dynamichands.nl", 22 | "commits": 1 23 | } 24 | ] 25 | }, 26 | "filePathRelative": "1600.external-applications/external-applications.md" 27 | } 28 | 29 | if (import.meta.webpackHot) { 30 | import.meta.webpackHot.accept() 31 | if (__VUE_HMR_RUNTIME__.updatePageData) { 32 | __VUE_HMR_RUNTIME__.updatePageData(data) 33 | } 34 | } 35 | 36 | if (import.meta.hot) { 37 | import.meta.hot.accept(({ data }) => { 38 | __VUE_HMR_RUNTIME__.updatePageData(data) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1600.external-applications/external-applications.html.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1700.design-patterns/design-patterns.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-2167bd5a", 3 | "path": "/1700.design-patterns/design-patterns.html", 4 | "title": "Design Patterns", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "lookup columns of lookup and set vaules on parent", 12 | "slug": "lookup-columns-of-lookup-and-set-vaules-on-parent", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "lookup ref in first lookup and set second lookup", 18 | "slug": "lookup-ref-in-first-lookup-and-set-second-lookup", 19 | "children": [] 20 | } 21 | ], 22 | "git": { 23 | "updatedTime": 1633406828000, 24 | "contributors": [ 25 | { 26 | "name": "remyvd", 27 | "email": "remy.vanduijkeren@dynamichands.nl", 28 | "commits": 1 29 | }, 30 | { 31 | "name": "remyvd", 32 | "email": "remy@automatevalue.com", 33 | "commits": 1 34 | } 35 | ] 36 | }, 37 | "filePathRelative": "1700.design-patterns/design-patterns.md" 38 | } 39 | 40 | if (import.meta.webpackHot) { 41 | import.meta.webpackHot.accept() 42 | if (__VUE_HMR_RUNTIME__.updatePageData) { 43 | __VUE_HMR_RUNTIME__.updatePageData(data) 44 | } 45 | } 46 | 47 | if (import.meta.hot) { 48 | import.meta.hot.accept(({ data }) => { 49 | __VUE_HMR_RUNTIME__.updatePageData(data) 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1700.design-patterns/design-patterns.html.vue: -------------------------------------------------------------------------------- 1 | 54 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1800.data-migrations/datamigrations.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-6f172275", 3 | "path": "/1800.data-migrations/datamigrations.html", 4 | "title": "Data migrations", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [], 9 | "git": { 10 | "updatedTime": 1591459257000, 11 | "contributors": [ 12 | { 13 | "name": "remyvd", 14 | "email": "remy.vanduijkeren@dynamichands.nl", 15 | "commits": 1 16 | } 17 | ] 18 | }, 19 | "filePathRelative": "1800.data-migrations/datamigrations.md" 20 | } 21 | 22 | if (import.meta.webpackHot) { 23 | import.meta.webpackHot.accept() 24 | if (__VUE_HMR_RUNTIME__.updatePageData) { 25 | __VUE_HMR_RUNTIME__.updatePageData(data) 26 | } 27 | } 28 | 29 | if (import.meta.hot) { 30 | import.meta.hot.accept(({ data }) => { 31 | __VUE_HMR_RUNTIME__.updatePageData(data) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/1800.data-migrations/datamigrations.html.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/2000.guidelines/possible-structure.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-17bb38ad", 3 | "path": "/2000.guidelines/possible-structure.html", 4 | "title": "Guidelines Dynamichands", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Interview Strategy", 12 | "slug": "interview-strategy", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Customization and Configuration", 18 | "slug": "customization-and-configuration", 19 | "children": [ 20 | { 21 | "level": 3, 22 | "title": "Form Design", 23 | "slug": "form-design", 24 | "children": [] 25 | }, 26 | { 27 | "level": 3, 28 | "title": "Entities", 29 | "slug": "entities", 30 | "children": [] 31 | }, 32 | { 33 | "level": 3, 34 | "title": "Fields", 35 | "slug": "fields", 36 | "children": [] 37 | }, 38 | { 39 | "level": 3, 40 | "title": "Business Process Flows", 41 | "slug": "business-process-flows", 42 | "children": [] 43 | }, 44 | { 45 | "level": 3, 46 | "title": "Business Rules", 47 | "slug": "business-rules", 48 | "children": [] 49 | }, 50 | { 51 | "level": 3, 52 | "title": "Workflows", 53 | "slug": "workflows", 54 | "children": [] 55 | }, 56 | { 57 | "level": 3, 58 | "title": "Solutions", 59 | "slug": "solutions", 60 | "children": [] 61 | }, 62 | { 63 | "level": 3, 64 | "title": "Security", 65 | "slug": "security", 66 | "children": [] 67 | } 68 | ] 69 | }, 70 | { 71 | "level": 2, 72 | "title": "Javascript", 73 | "slug": "javascript", 74 | "children": [ 75 | { 76 | "level": 3, 77 | "title": "Best Practices", 78 | "slug": "best-practices", 79 | "children": [] 80 | }, 81 | { 82 | "level": 3, 83 | "title": "Tools", 84 | "slug": "tools", 85 | "children": [] 86 | } 87 | ] 88 | }, 89 | { 90 | "level": 2, 91 | "title": "Tools", 92 | "slug": "tools-1", 93 | "children": [ 94 | { 95 | "level": 3, 96 | "title": "XRM Toolbox", 97 | "slug": "xrm-toolbox", 98 | "children": [] 99 | } 100 | ] 101 | }, 102 | { 103 | "level": 2, 104 | "title": "Migration of existing data", 105 | "slug": "migration-of-existing-data", 106 | "children": [] 107 | }, 108 | { 109 | "level": 2, 110 | "title": "References", 111 | "slug": "references", 112 | "children": [ 113 | { 114 | "level": 3, 115 | "title": "Websites and blogs", 116 | "slug": "websites-and-blogs", 117 | "children": [] 118 | } 119 | ] 120 | } 121 | ], 122 | "git": { 123 | "updatedTime": 1591459257000, 124 | "contributors": [ 125 | { 126 | "name": "remyvd", 127 | "email": "remy.vanduijkeren@dynamichands.nl", 128 | "commits": 1 129 | } 130 | ] 131 | }, 132 | "filePathRelative": "2000.guidelines/possible-structure.md" 133 | } 134 | 135 | if (import.meta.webpackHot) { 136 | import.meta.webpackHot.accept() 137 | if (__VUE_HMR_RUNTIME__.updatePageData) { 138 | __VUE_HMR_RUNTIME__.updatePageData(data) 139 | } 140 | } 141 | 142 | if (import.meta.hot) { 143 | import.meta.hot.accept(({ data }) => { 144 | __VUE_HMR_RUNTIME__.updatePageData(data) 145 | }) 146 | } 147 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/2000.guidelines/possible-structure.html.vue: -------------------------------------------------------------------------------- 1 | 63 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/2000.guidelines/rules-list-test.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-df17b1fa", 3 | "path": "/2000.guidelines/rules-list-test.html", 4 | "title": "Rule list based on pages", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [], 9 | "git": { 10 | "updatedTime": 1591459257000, 11 | "contributors": [ 12 | { 13 | "name": "remyvd", 14 | "email": "remy.vanduijkeren@dynamichands.nl", 15 | "commits": 1 16 | } 17 | ] 18 | }, 19 | "filePathRelative": "2000.guidelines/rules-list-test.md" 20 | } 21 | 22 | if (import.meta.webpackHot) { 23 | import.meta.webpackHot.accept() 24 | if (__VUE_HMR_RUNTIME__.updatePageData) { 25 | __VUE_HMR_RUNTIME__.updatePageData(data) 26 | } 27 | } 28 | 29 | if (import.meta.hot) { 30 | import.meta.hot.accept(({ data }) => { 31 | __VUE_HMR_RUNTIME__.updatePageData(data) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/2000.guidelines/rules-list-test.html.vue: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/2000.guidelines/tools.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-0edc2073", 3 | "path": "/2000.guidelines/tools.html", 4 | "title": "Tools", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [], 9 | "git": { 10 | "updatedTime": 1591459257000, 11 | "contributors": [ 12 | { 13 | "name": "remyvd", 14 | "email": "remy.vanduijkeren@dynamichands.nl", 15 | "commits": 1 16 | } 17 | ] 18 | }, 19 | "filePathRelative": "2000.guidelines/tools.md" 20 | } 21 | 22 | if (import.meta.webpackHot) { 23 | import.meta.webpackHot.accept() 24 | if (__VUE_HMR_RUNTIME__.updatePageData) { 25 | __VUE_HMR_RUNTIME__.updatePageData(data) 26 | } 27 | } 28 | 29 | if (import.meta.hot) { 30 | import.meta.hot.accept(({ data }) => { 31 | __VUE_HMR_RUNTIME__.updatePageData(data) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/2000.guidelines/tools.html.vue: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/2000.guidelines/tryout-markdown.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-14c6e1f6", 3 | "path": "/2000.guidelines/tryout-markdown.html", 4 | "title": "Try-out", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "This is awesome", 12 | "slug": "this-is-awesome", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Sections Heading", 18 | "slug": "sections-heading", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Alert Options", 24 | "slug": "alert-options", 25 | "children": [ 26 | { 27 | "level": 3, 28 | "title": "Line highlight in code blocks", 29 | "slug": "line-highlight-in-code-blocks", 30 | "children": [] 31 | } 32 | ] 33 | } 34 | ], 35 | "git": { 36 | "updatedTime": 1591459257000, 37 | "contributors": [ 38 | { 39 | "name": "remyvd", 40 | "email": "remy.vanduijkeren@dynamichands.nl", 41 | "commits": 1 42 | } 43 | ] 44 | }, 45 | "filePathRelative": "2000.guidelines/tryout-markdown.md" 46 | } 47 | 48 | if (import.meta.webpackHot) { 49 | import.meta.webpackHot.accept() 50 | if (__VUE_HMR_RUNTIME__.updatePageData) { 51 | __VUE_HMR_RUNTIME__.updatePageData(data) 52 | } 53 | } 54 | 55 | if (import.meta.hot) { 56 | import.meta.hot.accept(({ data }) => { 57 | __VUE_HMR_RUNTIME__.updatePageData(data) 58 | }) 59 | } 60 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/2000.guidelines/tryout-markdown.html.vue: -------------------------------------------------------------------------------- 1 | 66 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/3000.powerautomate/powerautomate.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-59a9b32e", 3 | "path": "/3000.powerautomate/powerautomate.html", 4 | "title": "Power Automate", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Do keep Conditions empty of steps", 12 | "slug": "do-keep-conditions-empty-of-steps", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Terminate with the correct status", 18 | "slug": "terminate-with-the-correct-status", 19 | "children": [] 20 | }, 21 | { 22 | "level": 2, 23 | "title": "Resource not found for the segment '[MY_GUID]' or Empty segment encountered in request URL. Please make sure that a valid request URL is specified.", 24 | "slug": "resource-not-found-for-the-segment-my-guid-or-empty-segment-encountered-in-request-url-please-make-sure-that-a-valid-request-url-is-specified", 25 | "children": [] 26 | }, 27 | { 28 | "level": 2, 29 | "title": "Avoid unneeded Apply to Each steps", 30 | "slug": "avoid-unneeded-apply-to-each-steps", 31 | "children": [] 32 | }, 33 | { 34 | "level": 2, 35 | "title": "Use Find Items as name for Lists steps", 36 | "slug": "use-find-items-as-name-for-lists-steps", 37 | "children": [] 38 | }, 39 | { 40 | "level": 2, 41 | "title": "USe Get Item as name for Get by ID steps .##", 42 | "slug": "use-get-item-as-name-for-get-by-id-steps", 43 | "children": [] 44 | }, 45 | { 46 | "level": 2, 47 | "title": "Make Apply to Each steps parallel when doing bulk", 48 | "slug": "make-apply-to-each-steps-parallel-when-doing-bulk", 49 | "children": [] 50 | }, 51 | { 52 | "level": 2, 53 | "title": "Use Connection References", 54 | "slug": "use-connection-references", 55 | "children": [] 56 | }, 57 | { 58 | "level": 2, 59 | "title": "Secured Inputs & Outputs", 60 | "slug": "secured-inputs-outputs", 61 | "children": [] 62 | }, 63 | { 64 | "level": 2, 65 | "title": "Actions Should Have Meaningful Names", 66 | "slug": "actions-should-have-meaningful-names", 67 | "children": [] 68 | }, 69 | { 70 | "level": 2, 71 | "title": "Consider Concurrency In Loops", 72 | "slug": "consider-concurrency-in-loops", 73 | "children": [] 74 | }, 75 | { 76 | "level": 2, 77 | "title": "Don’t Nest Too Deep", 78 | "slug": "don-t-nest-too-deep", 79 | "children": [] 80 | }, 81 | { 82 | "level": 2, 83 | "title": "Error Handling", 84 | "slug": "error-handling", 85 | "children": [] 86 | }, 87 | { 88 | "level": 2, 89 | "title": "Optimise & Look For Efficiencies", 90 | "slug": "optimise-look-for-efficiencies", 91 | "children": [] 92 | }, 93 | { 94 | "level": 2, 95 | "title": "Variables Should Have Meaningful Names", 96 | "slug": "variables-should-have-meaningful-names", 97 | "children": [] 98 | }, 99 | { 100 | "level": 2, 101 | "title": "Cloud Flows Should Be In Solutions", 102 | "slug": "cloud-flows-should-be-in-solutions", 103 | "children": [] 104 | }, 105 | { 106 | "level": 2, 107 | "title": "Always Think Scale", 108 | "slug": "always-think-scale", 109 | "children": [] 110 | }, 111 | { 112 | "level": 2, 113 | "title": "Comments", 114 | "slug": "comments", 115 | "children": [] 116 | }, 117 | { 118 | "level": 2, 119 | "title": "Consider Performance / Readability", 120 | "slug": "consider-performance-readability", 121 | "children": [] 122 | } 123 | ], 124 | "git": { 125 | "updatedTime": 1653026682000, 126 | "contributors": [ 127 | { 128 | "name": "remyvd", 129 | "email": "remy.vanduijkeren@dynamichands.nl", 130 | "commits": 6 131 | }, 132 | { 133 | "name": "remyvd", 134 | "email": "remy@automatevalue.com", 135 | "commits": 2 136 | } 137 | ] 138 | }, 139 | "filePathRelative": "3000.powerautomate/powerautomate.md" 140 | } 141 | 142 | if (import.meta.webpackHot) { 143 | import.meta.webpackHot.accept() 144 | if (__VUE_HMR_RUNTIME__.updatePageData) { 145 | __VUE_HMR_RUNTIME__.updatePageData(data) 146 | } 147 | } 148 | 149 | if (import.meta.hot) { 150 | import.meta.hot.accept(({ data }) => { 151 | __VUE_HMR_RUNTIME__.updatePageData(data) 152 | }) 153 | } 154 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/404.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-3706649a", 3 | "path": "/404.html", 4 | "title": "", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "layout": "404" 8 | }, 9 | "excerpt": "", 10 | "headers": [], 11 | "git": {}, 12 | "filePathRelative": null 13 | } 14 | 15 | if (import.meta.webpackHot) { 16 | import.meta.webpackHot.accept() 17 | if (__VUE_HMR_RUNTIME__.updatePageData) { 18 | __VUE_HMR_RUNTIME__.updatePageData(data) 19 | } 20 | } 21 | 22 | if (import.meta.hot) { 23 | import.meta.hot.accept(({ data }) => { 24 | __VUE_HMR_RUNTIME__.updatePageData(data) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/404.html.vue: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/CONTRIBUTING.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-73005554", 3 | "path": "/CONTRIBUTING.html", 4 | "title": "How to contribute", 5 | "lang": "en-US", 6 | "frontmatter": {}, 7 | "excerpt": "", 8 | "headers": [ 9 | { 10 | "level": 2, 11 | "title": "Getting Started", 12 | "slug": "getting-started", 13 | "children": [] 14 | }, 15 | { 16 | "level": 2, 17 | "title": "Making Changes", 18 | "slug": "making-changes", 19 | "children": [] 20 | } 21 | ], 22 | "git": { 23 | "updatedTime": 1591459257000, 24 | "contributors": [ 25 | { 26 | "name": "remyvd", 27 | "email": "remy.vanduijkeren@dynamichands.nl", 28 | "commits": 2 29 | } 30 | ] 31 | }, 32 | "filePathRelative": "CONTRIBUTING.md" 33 | } 34 | 35 | if (import.meta.webpackHot) { 36 | import.meta.webpackHot.accept() 37 | if (__VUE_HMR_RUNTIME__.updatePageData) { 38 | __VUE_HMR_RUNTIME__.updatePageData(data) 39 | } 40 | } 41 | 42 | if (import.meta.hot) { 43 | import.meta.hot.accept(({ data }) => { 44 | __VUE_HMR_RUNTIME__.updatePageData(data) 45 | }) 46 | } 47 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/CONTRIBUTING.html.vue: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /.vuepress/.temp/pages/index.html.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "key": "v-8daa1a0e", 3 | "path": "/", 4 | "title": "Home", 5 | "lang": "en-US", 6 | "frontmatter": { 7 | "home": true, 8 | "title": "Home", 9 | "heroImage": "logo.png", 10 | "heroText": "PowerApps Guidelines", 11 | "tagline": "Coding standards and Guidelines for Customizing and Extending Power Apps, Dynamics 365 Apps & Power Automate", 12 | "actions": [ 13 | { 14 | "text": "Get Started →", 15 | "link": "/00.introduction", 16 | "type": "primary" 17 | }, 18 | { 19 | "text": "Introduction", 20 | "link": "/guide/", 21 | "type": "secondary" 22 | } 23 | ], 24 | "features": [ 25 | { 26 | "title": "Code standards", 27 | "details": "No confusions how to do and name parts of the solution. Understanding solutions faster of other projects." 28 | }, 29 | { 30 | "title": "Guidelines", 31 | "details": "Follow the best practices of experienced senior consultants and developers. Don re-invent the wheel again." 32 | }, 33 | { 34 | "title": "Improve", 35 | "details": "Learn from this guidelines be reading it. Share your leasons learned and help improve this guidelines." 36 | } 37 | ], 38 | "footer": "LGPL-3.0 | Copyright © 2022 AutomateValue" 39 | }, 40 | "excerpt": "", 41 | "headers": [ 42 | { 43 | "level": 2, 44 | "title": "Set up and work locally", 45 | "slug": "set-up-and-work-locally", 46 | "children": [ 47 | { 48 | "level": 3, 49 | "title": "Prerequisites", 50 | "slug": "prerequisites", 51 | "children": [] 52 | }, 53 | { 54 | "level": 3, 55 | "title": "Running", 56 | "slug": "running", 57 | "children": [] 58 | } 59 | ] 60 | }, 61 | { 62 | "level": 2, 63 | "title": "Writing", 64 | "slug": "writing", 65 | "children": [] 66 | }, 67 | { 68 | "level": 2, 69 | "title": "Deploying", 70 | "slug": "deploying", 71 | "children": [] 72 | }, 73 | { 74 | "level": 2, 75 | "title": "Contributing", 76 | "slug": "contributing", 77 | "children": [] 78 | }, 79 | { 80 | "level": 2, 81 | "title": "Style of writing?", 82 | "slug": "style-of-writing", 83 | "children": [] 84 | } 85 | ], 86 | "git": { 87 | "updatedTime": 1654485104000, 88 | "contributors": [ 89 | { 90 | "name": "remyvd", 91 | "email": "remy.vanduijkeren@dynamichands.nl", 92 | "commits": 5 93 | }, 94 | { 95 | "name": "remyvd", 96 | "email": "remy@automatevalue.com", 97 | "commits": 2 98 | } 99 | ] 100 | }, 101 | "filePathRelative": "README.md" 102 | } 103 | 104 | if (import.meta.webpackHot) { 105 | import.meta.webpackHot.accept() 106 | if (__VUE_HMR_RUNTIME__.updatePageData) { 107 | __VUE_HMR_RUNTIME__.updatePageData(data) 108 | } 109 | } 110 | 111 | if (import.meta.hot) { 112 | import.meta.hot.accept(({ data }) => { 113 | __VUE_HMR_RUNTIME__.updatePageData(data) 114 | }) 115 | } 116 | -------------------------------------------------------------------------------- /.vuepress/.temp/register-components/clientConfig.091b98ea.js: -------------------------------------------------------------------------------- 1 | import { defineAsyncComponent } from 'vue' 2 | 3 | export default { 4 | enhance: ({ app }) => { 5 | app.component("Depends", defineAsyncComponent(() => import("C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/.vuepress/components/Depends.vue"))), 6 | app.component("NumberModifier", defineAsyncComponent(() => import("C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/.vuepress/components/NumberModifier.vue"))), 7 | app.component("Recommended", defineAsyncComponent(() => import("C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/.vuepress/components/Recommended.vue"))), 8 | app.component("Required", defineAsyncComponent(() => import("C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/.vuepress/components/Required.vue"))), 9 | app.component("RuleList", defineAsyncComponent(() => import("C:/Users/RemyvanDuijkeren/OneDrive/Source/PowerApps-Guidelines/.vuepress/components/RuleList.vue"))) 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /.vuepress/.temp/styles/index.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/.temp/styles/index.scss -------------------------------------------------------------------------------- /.vuepress/.temp/styles/palette.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/.temp/styles/palette.scss -------------------------------------------------------------------------------- /.vuepress/.temp/vite-root/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.vuepress/components/Depends.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /.vuepress/components/NumberModifier.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | -------------------------------------------------------------------------------- /.vuepress/components/Recommended.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /.vuepress/components/Required.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /.vuepress/components/RuleList.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 43 | 44 | -------------------------------------------------------------------------------- /.vuepress/config.js: -------------------------------------------------------------------------------- 1 | const { defaultTheme } = require('vuepress') 2 | const { registerComponentsPlugin } = require('@vuepress/plugin-register-components') 3 | const { path } = require('@vuepress/utils') 4 | //const { googleAnalyticsPlugin } = require('@vuepress/plugin-google-analytics') 5 | const { nav, sidebar } = require("vuepress-bar")({ addReadMeToFirstGroup: false }); 6 | 7 | // https://github.com/vuejs/vuepress/issues/613 8 | sidebar.forEach(element => { 9 | element.text = element.title; 10 | 11 | if (element.children) 12 | { 13 | let withSlash = []; 14 | element.children.forEach(child => { 15 | withSlash.push(`/${child}`); 16 | }); 17 | element.children = withSlash; 18 | } 19 | }); 20 | 21 | console.log(sidebar); 22 | 23 | module.exports = { 24 | lang: 'en-US', 25 | title: 'PowerApps Guidelines', 26 | description: 'Coding standards and Guidelines for Customizing and Extending PowerApps & Dynamics 365', 27 | theme: defaultTheme({ 28 | repo: 'AutomateValue/PowerApps-Guidelines', 29 | editLink: true, 30 | logo: '/logo.png', 31 | navbar: [ 32 | { text: 'Home', link: '/'}, 33 | { text: 'AutomateValue', link: 'https://automatevalue.com' }, 34 | ...nav 35 | ], 36 | //sidebar: 'auto' 37 | sidebar: sidebar.filter(i => i.title !== "Node Modules" && i !== "") 38 | }), 39 | head: [ 40 | ['link', { rel: 'apple-touch-icon', sizes: '57x57', href: '/apple-icon-57x57.png' }], 41 | ['link', { rel: 'apple-touch-icon', sizes: '114x114', href: '/apple-icon-114x114.png' }], 42 | ['link', { rel: 'apple-touch-icon', sizes: '144x144', href: '/apple-icon-144x144.png' }], 43 | ['link', { rel: 'apple-touch-icon', sizes: '152x152', href: '/apple-icon-152x152.png' }], 44 | ['link', { rel: 'icon', sizes: '196x196', href: '/favicon-196x196.png' }], 45 | ['link', { rel: 'icon', sizes: '128x128', href: '/favicon-128.png' }], 46 | ['link', { rel: 'icon', sizes: '96x96', href: '/favicon-96x96.png' }], 47 | ['link', { rel: 'icon', sizes: '64x64', href: '/favicon-64x64.png' }], 48 | ['link', { rel: 'icon', sizes: '32x32', href: '/favicon-32x32.png' }], 49 | ['link', { rel: 'icon', sizes: '16x16', href: '/favicon-16x16.png' }], 50 | ['meta', { name: 'msapplication-TileColor', content: '#f18800' }], 51 | ['meta', { name: 'theme-color', content: '#ffffff' }] 52 | ], 53 | plugins: [ 54 | //googleAnalyticsPlugin({ id: 'G-XXXXXXXXXX' }), 55 | registerComponentsPlugin({ componentsDir: path.resolve(__dirname, './components'), }), 56 | ], 57 | }; -------------------------------------------------------------------------------- /.vuepress/public/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /.vuepress/public/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /.vuepress/public/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /.vuepress/public/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /.vuepress/public/assets/ALM-source-control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/ALM-source-control.png -------------------------------------------------------------------------------- /.vuepress/public/assets/aPaaS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/aPaaS.png -------------------------------------------------------------------------------- /.vuepress/public/assets/environment-5-security-layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/environment-5-security-layers.png -------------------------------------------------------------------------------- /.vuepress/public/assets/environment-DLP-Applying.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/environment-DLP-Applying.png -------------------------------------------------------------------------------- /.vuepress/public/assets/environment-DLP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/environment-DLP.png -------------------------------------------------------------------------------- /.vuepress/public/assets/environment-naming-admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/environment-naming-admin.png -------------------------------------------------------------------------------- /.vuepress/public/assets/environment-naming-homescreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/environment-naming-homescreen.png -------------------------------------------------------------------------------- /.vuepress/public/assets/poweratomate-keep-condition-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/poweratomate-keep-condition-empty.png -------------------------------------------------------------------------------- /.vuepress/public/assets/powerautomate-connection-references.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/powerautomate-connection-references.png -------------------------------------------------------------------------------- /.vuepress/public/assets/powerautomate-copy-setname.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/powerautomate-copy-setname.jpeg -------------------------------------------------------------------------------- /.vuepress/public/assets/powerautomate-lookup-with-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/assets/powerautomate-lookup-with-type.png -------------------------------------------------------------------------------- /.vuepress/public/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/favicon-128.png -------------------------------------------------------------------------------- /.vuepress/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/favicon-16x16.png -------------------------------------------------------------------------------- /.vuepress/public/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/favicon-196x196.png -------------------------------------------------------------------------------- /.vuepress/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/favicon-32x32.png -------------------------------------------------------------------------------- /.vuepress/public/favicon-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/favicon-64x64.png -------------------------------------------------------------------------------- /.vuepress/public/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/favicon-96x96.png -------------------------------------------------------------------------------- /.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /.vuepress/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutomateValue/PowerApps-Guidelines/28a4e4aabfa474d6faa9589273cfef5d8d4f3c71/.vuepress/public/logo.png -------------------------------------------------------------------------------- /00.introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This website attempts to provide guidelines for PowerApp/Dynamics365 projects that have learned the hard way be seniors, but are everytime made by juniors. Of course, if you create such a document you should practice what you preach. So rest assured, these guidelines are representative to what we at DynamicHands do in our day-to-day work. Notice that not all guidelines have a clear rationale. Some of them are simply choices we made at DynamicHands. In the end, it doesn’t matter what choice you made, as long as you make one and apply it consistently. 4 | 5 | ## Why would you use this guidelines 6 | 7 | Although some might see coding guidelines as undesired overhead or something that limits creativity, this approach has already proven its value for many years. This is because not every consultant or developer: 8 | 9 | - is aware that code is generally read 10 times more than it is changed; 10 | - is aware of the potential pitfalls of certain solutions in the Power Platform; 11 | - is up to speed on certain conventions when building on the Power Platform; 12 | - is aware of the impact of using (or neglecting to use) particular solutions on aspects like security, performance, multi-language support, etc; 13 | - realizes that not every developer is as capable, skilled or experienced to understand elegant, but potentially very abstract solutions; 14 | 15 | ## Basic principles 16 | 17 | There are many unexpected things I run into during my work as a consultant, each deserving at least one guideline. Unfortunately, I still need to keep this document within a reasonable size. But unlike what some junior developers believe, that doesn't mean that something is okay just because it is not mentioned in this document. 18 | 19 | In general, if I have a discussion with a colleague about a smell that this document does not cover, I'll refer back to a set of basic principles that apply to all situations, regardless of context. These include: 20 | 21 | - The Principle of Least Surprise (or Astonishment): you should choose a solution that everyone can understand, and that keeps them on the right track. 22 | - Keep It Simple Stupid (a.k.a. KISS): the simplest solution is more than sufficient. 23 | - You Ain't Gonna Need It (a.k.a. YAGNI): create a solution for the problem at hand, not for the ones you think may happen later on. Can you predict the future? 24 | - Don't Repeat Yourself (a.k.a. DRY): avoid duplication within a component, a source control repository or a [bounded context](http://martinfowler.com/bliki/BoundedContext.html), without forgetting the [Rule of Three](http://lostechies.com/derickbailey/2012/10/31/abstraction-the-rule-of-three/) heuristic. 25 | - The [four principles of object-oriented programming](https://github.com/TelerikAcademy/Object-Oriented-Programming/tree/master/Topics/04.%20OOP-Principles-Part-1): encapsulation, abstraction, inheritance and polymorphism. 26 | - In general, generated code should not need to comply with coding guidelines. However, if it is possible to modify the templates used for generation, try to make them generate code that complies as much as possible. 27 | 28 | Regardless of the elegance of someone's solution, if it's too complex for the ordinary developer, exposes unusual behavior, or tries to solve many possible future issues, it is very likely the wrong solution and needs redesign. The worst response a developer can give you to these principles is: "But it works?". 29 | 30 | ## How do you get started 31 | 32 | - Ask all developers to carefully read this document at least once. This will give them a sense of the kind of guidelines the document contains. 33 | - Include the most critical coding guidelines on your Project Checklist and verify the remainder as part of your Peer Review. 34 | 35 | ## To which guidelines should you comply 36 | 37 | The document does not state that projects must comply with these guidelines, neither does it say which guidelines are more important than others. However, we encourage projects to decide themselves which guidelines are important, what deviations a project will use, who is the consultant in case doubts arise. Obviously, you should make these decisions before starting the real work. 38 | 39 | To help you in this decision, I’ve assigned a level of importance to each guideline: 40 | 41 | 1. = Guidelines that you should never skip and should be applicable to all situations 42 | 2. = Strongly recommended guidelines. 43 | 3. = May not be applicable in all situations. 44 | -------------------------------------------------------------------------------- /1000.environment-configuration/DH1201.md: -------------------------------------------------------------------------------- 1 | --- 2 | rule_id: 1201 3 | rule_category: class-design 4 | title: Regel 1201 5 | severity: Required 6 | read_more: true 7 | --- 8 | 9 | # Title DH1201 10 | 11 | This `Id` always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the `Id` in code you use this: 12 | 13 | ```csharp 14 | var contactId = ((EntityReference)customMethod["dh_ContactId"]).Id; 15 | ``` 16 | 17 | 18 | 19 | Which I don't like, because you're repeating the abbreviation `Id`. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition: 20 | 21 | ```csharp 22 | var contactId = ((EntityReference)customMethod["dh_Contact"]).Id; 23 | ``` -------------------------------------------------------------------------------- /1000.environment-configuration/DH1202.md: -------------------------------------------------------------------------------- 1 | --- 2 | rule_id: 1202 3 | rule_category: class-design 4 | title: Regel DH1202 5 | severity: Recommended 6 | read_more: false 7 | --- 8 | 9 | ## Title DH1202 10 | 11 | This `Id` always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the `Id` in code you use this: 12 | 13 | ```csharp 14 | var contactId = ((EntityReference)customMethod["dh_ContactId"]).Id; 15 | ``` 16 | 17 | Which I don't like, because you're repeating the abbreviation `Id`. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition: 18 | 19 | ```csharp 20 | var contactId = ((EntityReference)customMethod["dh_Contact"]).Id; 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /1000.environment-configuration/DH1203.md: -------------------------------------------------------------------------------- 1 | --- 2 | rule_id: 1203 3 | rule_category: class-design 4 | title: Regel 1203 5 | severity: Depends 6 | read_more: false 7 | --- 8 | 9 | ## Title DH1203 10 | 11 | This `Id` always bugged me, because of this simple fact - it's not an Id in code, it's a reference. So if you just wanted the `Id` in code you use this: 12 | 13 | ```csharp 14 | var contactId = ((EntityReference)customMethod["dh_ContactId"]).Id; 15 | ``` 16 | 17 | Which I don't like, because you're repeating the abbreviation `Id`. In my opinion this kind of violates "DRY" so I will avoid it if at all possible. Using the new school way it looks cleaner without this repetition: 18 | 19 | ```csharp 20 | var contactId = ((EntityReference)customMethod["dh_Contact"]).Id; 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /1000.environment-configuration/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Inhopud 4 | -------------------------------------------------------------------------------- /1000.environment-configuration/installation-configuration.md: -------------------------------------------------------------------------------- 1 | --- 2 | rule_id: 1204 3 | rule_category: class-design 4 | title: This is another rule 3 5 | severity: Depends 6 | read_more: false 7 | --- 8 | 9 | # Installation & configuration 10 | 11 | ## Default environment is the Personal shared playground (shared) 12 | 13 | ![environment-naming-admin](/assets/environment-naming-admin.png) 14 | 15 | Environments are tied to a geographic location that is configured at the time the 16 | the environment is created. 17 | 18 | Environment can be used to target different audiences and/or for different purposed such as dev, test, and production. 19 | 20 | Data Loss Perevention (DLP) policies can be applied to individual environment or tenant 21 | 22 | Every tenant has a Default environment 23 | 24 | Non-default environments can be created by licensed PowerApps and Flow user and 25 | can be restricted to only global and service admins via a tenant settings. 26 | 27 | 28 | ## Deployment stratagy for customer type 1 & 2 29 | 30 | Unmanged in Production vs Managed in production 31 | 32 | ## The five layers of security 33 | see image in asset 34 | 35 | ## Pervent data leakage 36 | 37 | Data loss prevention policies (DLP) enforce rules for which connectors can be used togheter. 38 | 39 | Connectors are classified as either Business Data only or No Business Data allowed. 40 | 41 | A connector in the business data oly group can only be used with other connectors from that group in the same app or flow. 42 | 43 | Tenant admins can define policies that apply to all environments. 44 | 45 | Multiple policies can apply to an environment 46 | 47 | The most restricive policy applies to the combination fo connectors. 48 | 49 | Use ONLY selected and EXCEPT to tailor which environment are impacted 50 | 51 | images in assets 52 | 53 | ## Security 54 | 55 | Non-interactive: 56 | 57 | - Poor: Connection string 58 | - Less poor: Encrypted string 59 | - Slightly Better: Non-interactive user 60 | - Best: App service 61 | - Bester: ClientId + Secret 62 | - Bestest: Certificate-based 63 | - Bonus points: Azure Vault 64 | - Medal: Managed Identities 65 | 66 | Interactive: 67 | 68 | - Passive 69 | - Poor: Connection string 70 | - Still poor: Encrypted connection string 71 | - Better: Connection string deployed as part of Azure app 72 | - Best: Registered app 73 | - Best: OAuth if impersonation is required 74 | 75 | - Active 76 | - Poor: Connection string 77 | - Better: Prompt for password 78 | - Better: Use registered app 79 | - Best: Xrm.Tooling 80 | 81 | ## Solutions 82 | 83 | - Focus on small footprint 84 | - (Re)use as much as possible of default functionality. Focus on What-if scenario that ure solution is removed: will the data still be available (as much as possible). 85 | 86 | Solution by type vs Solution by feature/functionality (prefered) -------------------------------------------------------------------------------- /1100.user-experience-design/ux-design.md: -------------------------------------------------------------------------------- 1 | # UX design 2 | 3 | ## 1 Understand what User eXperience design means 4 | 5 | TODO: Explain what UX is, compared with UI. 6 | 7 | What is this _UX_ thing anyway? It's not the same as User Interface design. 8 | 9 | _User knowing how to use the system_ vs _system knowing what the **user** wants_ 10 | 11 | The human brain hates uncertainty - UX design can reduce uncertainty via: 12 | 13 | - Choice reduction 14 | - Visual cues 15 | - Adapting to user interaction 16 | - Following the user's natural process 17 | 18 | User Experience is about the whole process 19 | [IMG] 20 | 21 | Why user experience is important for CRM systems: 22 | 23 | - The frequency of user pain 24 | - Online store customer: temporary pain caused during the commercial transaction 25 | - CRM system user: continuous pain through repeated encounters with the dat-to-day tools 26 | - The variety of use cases and user groups 27 | - People who don't share the same processes trying to use the same customer information system 28 | - Trying to deliver _sometething for everybody_ will results in monolithic enterpries software 29 | 30 | Why its'especially important with Dynamics 365: 31 | 32 | - Higher user expectations due to relative ease of out-of-the-box functionality 33 | - Simplified UI only delivers benefits when the actions visible are the relevant ones 34 | - Tons of new components to configure = more potential for UX sucess AND failure 35 | 36 | ## 2 Start from the navigation 37 | 38 | 39 | ## Addresses 40 | 41 | Account has two addresses (and Contact even has three), which are being keept in sync with the Address entity. Thats why you see all those address fields, because they are the same as in the Address entity. In the Address entity you can add more addresses, if really need to. 42 | 43 | Most organization agree which type of addres is stored in Address 1 and which in Address 2. For example Delivery addres is always Address 1 and Post Address is Address 2. This makes searching easier. If you want to search for thu both addresses, you can also search the Address entity. 44 | 45 | Make sure Address type is corretly filled. 46 | 47 | I know your feelings; these are the same when I entered the Dataverse world a long time ago. Dataverse is originated from model-driven apps. Learning about model-driven apps & Dynamics 365 apps will give you much more info why things are like this. In model-driven apps you will be given much more out-of-the box functionality then canvas apps, which will out-ways the negative points you mentioned. You need to do some of the work that normally a RDBMS does, which sucks, but it will grow on you. 48 | 49 | Account has two addresses (and Contact even has three), which are being keept in sync with the Address entity. Thats why you see all those address fields because they are the same as in the Address entity. In the Address entity you can add more addresses, if really need to. This solution is because historically in model-driven apps, editing related records was not that user friendly (it's improved now-a-days). 50 | 51 | Most organization agree which type of address is stored in Address 1 and which in Address 2. For example, Delivery address is always Address 1 and Post Address is Address 2. This makes searching easier. If you want to search in both addresses, you can also search the Address entity. 52 | 53 | Looking at all the phone numbers point: The Address entity has three phone numbers, which are specific for that address. Those Address phone numbers also exist on Account, to keep al the address fields the same. Often these are not used, but for companies in logistics, they can be handy. 54 | 55 | Views are different from Database Views! Microsoft should rename these to Lists or List Views, because they are connected to the entity and are primarily used for viewing in Lists. I agree that it is annoying you can only query one step further. I highly requested feature by Dynamics 365 consultants. 56 | 57 | Multi-valued fields are added recent because consultants really needed a solution for this much requested feature. Too bad that Microsoft created a not so great solution (not proper database-design, Power BI problems, etc.), and the general advice is to only use them when you have no other option. 58 | 59 | Dataverse indeed hides the many-2-many relationship implementation. I can understand your worries about this, but I have to say that this feature is one I think is a desirable choice by Dataverse. I practice you almost don't need to query this table. In contrast I have seen enough developers struggle with this in custom apps connecting to a RDBMS. Many-2-many relationship is a hard concept to grasp for a lot of people. If you really want to, you can still create your own many-2-many entity. 60 | 61 | Dataverse is indeed creating multiple columns, for like the Customer datatype, which can connect to Account or a Contact. This used to be explicitly (you can still do this), but connection to Account or Contact is used so much in Dynamics 365, that they made it implicit. 62 | 63 | I agree that experts should do data modeling if it concerns important business data. But sometimes data starts as a small side project by one person or a department: in this stage correct data modeling is not the most important thing. When it evolves it should be taken over by IT and be proper modeled. -------------------------------------------------------------------------------- /1200.naming-conventions/azure-resources.md: -------------------------------------------------------------------------------- 1 | # Azure Resources 2 | 3 | https://docs.microsoft.com/en-us/azure/architecture/best-practices/naming-conventions 4 | 5 | Don't agree with the ordering. The first part is the resource in the name, but azure itself already has perfect grouping options for that. It is more important to sort by Customer and Project/Application. 6 | 7 | ## Subscriptions and Resource groups 8 | 9 | Subscriptions are used for how resources are billed: the billing agreement. 10 | 11 | [Azure Tenants, Subscriptions & Resource Groups Explained](https://www.youtube.com/watch?v=FAbqJqr93v8) 12 | 13 | Resource groups exist for two reasons: 14 | 15 | - organization and billing. Put one solution into one resource group 16 | - security boundary for role based access control 17 | 18 | Capitals? RG, VM, FN 19 | 20 | https://github.com/uglide/azure-content/blob/master/articles/guidance/guidance-naming-conventions.md 21 | -------------------------------------------------------------------------------- /1200.naming-conventions/azure-tags.md: -------------------------------------------------------------------------------- 1 | # Azure Tags 2 | 3 | ## Must-haves 4 | 5 | Tag name | Values | Description 6 | --------------------|-----------------------------------|--------- 7 | Environment | prod, acc, test, dev, poc, demo | Environment 8 | ResourceOwner | bob@company.com | Owner Typicakky the creator - the person in charge of the resource 9 | Application | Spotler Connector | Application 10 | Importance | low, medium, high, critical | Importance 11 | CostCenter | HR, IT, DevOps, Finance | Cost center 12 | Project | ProjectName, Teamname | Project or team name 13 | ReviewOn | YYYY-MM-DD | Resource review date 14 | MaxUpTime | 14days | Max up time - useful for identifying and targeting tempory resources for automatic deletion after X time 15 | ManagedBy | DevOps, IT | Department in charge of managing the resource 16 | Approver | paul@company.com | Approver of budget 17 | Budget | 100 EUR/month | Budget threshold -------------------------------------------------------------------------------- /1500.extending-server-side/extending-serverside.md: -------------------------------------------------------------------------------- 1 | # Extending server-side 2 | 3 | ## Plugins & Workflow Activities must be stateless 4 | 5 | It isn't guaranteed that for every execution of your plugin or workflow activity, a new instance is created. Therefore you should always write your plugin and workflow activity classes as stateless. This means that you shouldn't use any properties or non-constant fields in your class. The only fields that could be used are: `const` and `static readonly`. 6 | 7 | ## Always wrap the OrganizationServiceContext class 8 | 9 | The OrganizationServiceContext class is a concrete class that doesn't have a base interface. This makes unit testing really difficult. If you decide to use this class, then always wrap it in your own class that has a base interface. Inject the base interface where needed. See example below. 10 | 11 | ````csharp 12 | public interface ICrmRepository : IOrganizationService 13 | { 14 | IQueryable CreateQuery() where TEntity : Entity; 15 | IQueryable CreateQuery(string entityLogicalName); 16 | 17 | // Other methods from the context class omitted, add what you require. 18 | } 19 | 20 | class CrmRepository : ICrmRepository 21 | { 22 | private readonly OrganizationServiceContext _context; 23 | private readonly IOrganizationService _service; 24 | 25 | public CrmRepository(IOrganizationService service, OrganizationServiceContext context) 26 | { 27 | _service = service; 28 | _context = context; 29 | } 30 | 31 | // Implementation omitted 32 | } 33 | 34 | ```` 35 | 36 | ## Always implement paging for RetrieveMultiple when not using TopCount 37 | 38 | When you use RetrieveMultiple, it will only return results up to a specific maximum (5000 by default). If your query would return more data, it requires you to execute another query. Even if you won't expect your query to ever reach that limit, implement it just in case. 39 | 40 | Documentation and sample code on how to implement this can be found here for [QueryExpressions](https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/org-service/page-large-result-sets-with-queryexpression) and [FetchExpressions](https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/org-service/page-large-result-sets-with-fetchxml). 41 | 42 | [MSDYN365 INTERNALS: PAGING GOTCHAS](https://markcarrington.dev/2021/02/23/msdyn365-internals-paging-gotchas/) 43 | 44 | # If you only expect one result from RetrieveMultiple then add TopCount = 1 45 | 46 | This will stop CRM from searching further. Optionally set it to 2, if you want to throw an error if there is more then 1 found. 47 | 48 | ## Exceptions thrown towards the platform within Plugins & Workflow Activities should always be of type 'InvalidPluginExecutionException' and contain an error code for identification 49 | 50 | When implementing error handling make sure that you always throw exceptions of type 'InvalidPluginExecutionException'. This exception class allows you to pass an errorcode of type integer. Always identify your errors with an unique number. This makes troubleshooting a lot easier as you can search code for this specific number. 51 | 52 | TODO: 53 | In the Unified Interface an exception not InvalidPluginExecutionExeception will be shown as. InvalidPluginExecutionExeception will shown the message as is. 54 | 55 | Exception Message: An unexpected error occurred from ISV code. (ErrorType = ClientError) Unexpected exception from plug-in (Execute): DH.Spotler.Plugins.CreateOrUpdateSpotlerJob: System.Exception: Object reference not set to an instance of an object. 56 | 57 | ## Use filtering attributes in plugin registration to improve performance 58 | 59 | When registering plugins you can specify filtering attributes. You must always do that if possible and reduce the amount of attributes to a minimum. This will result in the plugin to only be executed if required and thus increasing performance. 60 | 61 | ## Make Plugins & Workflows asynchronous if possible to improve performance 62 | 63 | The user won't need to wait for your plugin or workflow if it is asynchronous. This will improve the user experience and keeps dynamics running smoothly. 64 | 65 | ## Don't impersonate a user not knowing it is existing active user 66 | 67 | Don't run code based on an user that you don't know if it is active and has a licence, like when recreating an old task on behalf of that user. 68 | 69 | ## Write QueryExpressions as simple as possible ## 70 | 71 | When creating a QueryExpression the constructor will already create an FilterExpression (default And) and PagingInfo (and ColumnSet). This means a simple query can be written very clear, like: 72 | 73 | this._criteria = new FilterExpression(); 74 | this._pageInfo = new PagingInfo(); 75 | this._columnSet = new ColumnSet(); 76 | 77 | ```c# 78 | QueryExpression query = new QueryExpression 79 | { 80 | EntityName = entityName, 81 | ColumnSet = cols, 82 | Criteria = new FilterExpression 83 | { 84 | Conditions = 85 | { 86 | new ConditionExpression 87 | { 88 | AttributeName = attributeName, 89 | Operator = ConditionOperator.Equal, 90 | Values = { attributeValue } 91 | } 92 | } 93 | } 94 | }; 95 | 96 | var query = new QueryExpression(dh_spotlerpermission.EntityLogicalName) 97 | { 98 | ColumnSet = new ColumnSet("dh_name", "dh_subscribed"), 99 | Criteria = 100 | { 101 | Conditions = { new ConditionExpression("dh_leadid", ConditionOperator.Equal, originatingLead.Id) } 102 | } 103 | }; 104 | ``` 105 | 106 | ## Try to use GetAttributeValue ## 107 | 108 | http://crmentropy.blogspot.com/2013/08/entitygetattributevalue-explained.html 109 | 110 | 111 | ## Don't put every plugin in a seprate project 112 | 113 | This is a code smell. You see this when new developers take over a project (or not experinced), they will create a new project. -------------------------------------------------------------------------------- /1600.external-applications/external-applications.md: -------------------------------------------------------------------------------- 1 | # External applications 2 | 3 | ## Implement handling of API limits for external applications 4 | 5 | External applications may reach the API limits and start throwing an exception. If you are developing a third party application, then you should always implement this to avoid crashes. Below is a table of the different error codes and their description. 6 | | Error Code | Description | 7 | | --| -- | 8 | | -2147015902 | Number of requests exceeded the limit of X over time window of 300 seconds. | 9 | | -2147015903 | Combined execution time of incoming requests exceeded limit of X milliseconds over time window of 300 seconds. Decrease number of concurrent requests or reduce the duration of requests and try again later. | 10 | | -2147015898 | Number of concurrent requests exceeded the limit of X. | 11 | 12 | The ErrorDetails of the FaultException contains a 'Retry-After' property that specifies in how much time you can try again (see code below). 13 | 14 | ```` 15 | ex.Detail.ErrorDetails["Retry-After"] as TimeSpan? 16 | ```` 17 | -------------------------------------------------------------------------------- /1700.design-patterns/design-patterns.md: -------------------------------------------------------------------------------- 1 | # Design Patterns 2 | 3 | ## lookup columns of lookup and set vaules on parent 4 | async function onChangeProductId(executionContext) { 5 | const formContext = executionContext.getFormContext(); 6 | 7 | const productDetails = [columns.Manufacturer, columns.Model, columns.Capacity, columns.ProductionYear] 8 | 9 | const productLkp = getAttributeLookupValue(columns.ProductId, formContext); 10 | if (!productLkp) { 11 | productDetails.forEach(c => formContext.getAttribute(c).setValue(null)); 12 | return; 13 | } 14 | 15 | let options = "?$select="; 16 | productDetails.forEach(c => options += `${c},`); 17 | const product = await Xrm.WebApi.retrieveRecord(productLkp.entityType, productLkp.id.removeBraces(), options); 18 | 19 | productDetails.forEach(c => { 20 | if (product[c] && formContext.getAttribute(c).getValue() !== product[c]) { 21 | formContext.getAttribute(c).setValue(product[c]); 22 | } 23 | }); 24 | } 25 | 26 | ## lookup ref in first lookup and set second lookup 27 | async function onChangeCountry(executionContext) { 28 | const formContext = executionContext.getFormContext(); 29 | 30 | const countryLkp = getAttributeLookupValue(columns.Country, formContext); 31 | if (!countryLkp) { 32 | formContext.getAttribute(columns.Region).setValue(null); 33 | return; 34 | } 35 | 36 | const regionValue = `_${columns.Region}_value`; // lookup column needs to have the format '_{column}_value' to retrieve its data 37 | let options = `?$select=${regionValue}`; 38 | const country = await Xrm.WebApi.retrieveRecord(countryLkp.entityType, countryLkp.id.removeBraces(), options); 39 | 40 | if (country[regionValue]) { 41 | formContext.getAttribute(columns.Region).setValue([{ 42 | id: country[regionValue], 43 | name: country[`${regionValue}@OData.Community.Display.V1.FormattedValue`], 44 | entityType: country[`${regionValue}@Microsoft.Dynamics.CRM.lookuplogicalname`] 45 | }]); 46 | } 47 | } 48 | 49 | # async pattern 50 | 51 | Kick of async work and notify user using notification (like in Azure portal) https://docs.microsoft.com/en-us/power-platform-release-plan/2021wave1/power-apps/model-driven-app-adds-in-app-notifications 52 | 53 | This way the work is done in the background, but the user is still in the loop. 54 | 55 | Providing feedback to the user can be as simple as showing a dialog confirming the data was received, which gives the back end a second to process the message. In a healthy system there really shouldn’t be more than a few milliseconds delay before the message is processed. In other situations, you can use client-side script to “fake” the user into thinking the data was refreshed instantly. 56 | 57 | In the most complex cases your app can have a pending tasks concept and receive updates via SignalR. I like to give the example of the Azure Portal. Some long running operations, like provisioning a virtual machine, can’t be completed instantly. So when you complete the wizard, a task is kicked off, and you find out when it completes via the Notifications area in the corner of the screen. -------------------------------------------------------------------------------- /1800.data-migrations/datamigrations.md: -------------------------------------------------------------------------------- 1 | # Data migrations 2 | 3 | Migration of existing data: 4 | 5 | - Always push for only bringing over essential data 6 | - Consider reference ID that would allow lookup in legacy 7 | system 8 | - Review impact of old data on business rules and 9 | automation 10 | - Using separate entity might allow easier future retirement 11 | - Consider storing some data as notes instead of fields -------------------------------------------------------------------------------- /2000.guidelines/possible-structure.md: -------------------------------------------------------------------------------- 1 | # Guidelines Dynamichands 2 | 3 | Welcome the Dynamics 365 Guidelines. 4 | 5 | ## Interview Strategy 6 | 7 | ## Customization and Configuration 8 | 9 | ### Form Design 10 | 11 | ### Entities 12 | 13 | ### Fields 14 | 15 | #### Rollup Fields 16 | 17 | #### Calculated Fields 18 | 19 | ### Business Process Flows 20 | 21 | ### Business Rules 22 | 23 | ### Workflows 24 | 25 | ### Solutions 26 | 27 | ### Security 28 | 29 | #### Security Roles 30 | 31 | #### Field Security 32 | 33 | ## Javascript 34 | 35 | ### Best Practices 36 | 37 | ### Tools 38 | 39 | #### VS Code 40 | 41 | ## Tools 42 | 43 | ### XRM Toolbox 44 | 45 | ## Migration of existing data 46 | 47 | ## References 48 | 49 | ### Websites and blogs 50 | 51 | - [Rules to better crm for 52 | developers](https://rules.ssw.com.au/rules-to-better-crm-for-developers) 53 | 54 | - [Best practices 55 | SDK](https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/best-practices-sdk) 56 | 57 | - [Dynamics CRM Best 58 | Practices](https://community.dynamics.com/crm/b/dynamicscrmbestpractices) 59 | 60 | - [Managing 61 | Processes](https://crmbook.powerobjects.com/system-administration/processes/managing-processesbest-practices/) 62 | 63 | - [Deployment Administrators 64 | Guide](https://docs.microsoft.com/en-us/previous-versions/dynamicscrm-2016/deployment-administrators-guide/hh699761\(v=crm.8\)) 65 | 66 | - [Best practices for implementing dynamics 365 for 67 | sales](https://us.hitachi-solutions.com/blog/best-practices-for-implementing-dynamics-365-for-sales-and-dynamics-365-for-finance-and-operations/) 68 | 69 | - [A complete guide to dynamics 365 fields and 70 | entities](https://us.hitachi-solutions.com/blog/dynamics-365-roadmap-a-complete-guide-to-dynamics-365-fields-and-entities/) 71 | 72 | - [XRM Coaches](http://www.xrmcoaches.com/category/dynamics-crm/) 73 | 74 | - [XRM Coaches Webinars](http://www.xrmcoaches.com/webinars/) -------------------------------------------------------------------------------- /2000.guidelines/rules-list-test.md: -------------------------------------------------------------------------------- 1 | # Rule list based on pages 2 | 3 | -------------------------------------------------------------------------------- /2000.guidelines/tools.md: -------------------------------------------------------------------------------- 1 | # Tools -------------------------------------------------------------------------------- /2000.guidelines/tryout-markdown.md: -------------------------------------------------------------------------------- 1 | # Try-out 2 | 3 | [[toc]] 4 | 5 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 6 | 7 | ## This is awesome 8 | 9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum 10 | 11 | REQUIRED RULES use . 12 | 13 | RECOMMENDED RULES use . 14 | 15 | # Markdown :ok_hand: 16 | 17 | Her's my **awesome** text that lives in a '.md' file and is _emphasized_ in all of its magnificent glory! 🎉 18 | 19 | :tada: :100: :ok_hand: :+1: 20 | 21 | See [all emoji](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.json). 22 | 23 | > I ❤️ VuePress 24 | 25 | ## Sections Heading 26 | 27 | And lists are easy... 28 | 29 | - Apples 30 | - Bananas 31 | - Cherries 32 | 33 | And ordered lists... 34 | 35 | 1. First you do this 36 | 2. And then this 37 | 3. And finnaly this 38 | 39 | ## Alert Options 40 | ::: tip 41 | This is a tip 42 | ::: 43 | 44 | ::: warning No 45 | This is a warning 46 | ::: 47 | 48 | ::: danger 49 | This is a dangerous warning 50 | ::: 51 | 52 | ::: details 53 | This is a details block, which does not work in IE / Edge 54 | ::: 55 | 56 | ### Line highlight in code blocks 57 | 58 | ```js{4,2} 59 | export default { 60 | data () { 61 | return { 62 | msg: 'Highlighted!' 63 | } 64 | } 65 | } 66 | ``` 67 | 68 | #### Using Vue in Markdown 69 | 70 | _How are you doing?_ 71 | > **I'm doing fine, thanks!** 72 | 73 | _Great, I was wondering what `49 + 32` is?_ 74 | > **{{49 + 32}}** 75 | 76 | _Could you repeat that a few times?_ 77 | 78 | > **Sigh...** 79 |

{{49 + 32}}

80 | 81 | {{ 4 + 5 * 9 }} 82 | 83 | **Our Component:** 84 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Contributions are essential for keeping these guidleines great. If you see a problem or a great idea, please report this to us 4 | as a [Issue](https://github.com/DynamicHands/PowerApps-Guidelines/issues). 5 | 6 | Do you want to contribute then there are a few guidelines that we need contributors to follow so that your change 7 | can be accepted quickly. 8 | 9 | ## Getting Started 10 | 11 | * Make sure you have a [GitHub account](https://github.com/signup/free) 12 | * Fork the repository on GitHub (we use the [fork & pull model](https://help.github.com/articles/using-pull-requests)) 13 | * We use as branching strategy the [GitHub Flow Workflow](https://guides.github.com/introduction/flow/). 14 | 15 | ## Making Changes 16 | 17 | * If possible, create an issue for big improvements or features, so that people can discuss. 18 | * Make commits of logical units, so that we can pick and choose. 19 | * Make sure your commit messages have a good description. 20 | * Push your changes to your fork of the repository. 21 | * Submit a [pull request](https://help.github.com/articles/creating-a-pull-request/) to the PowerApps-Guidelines repository. 22 | * If needed we will give feedback about the pull request or accept it right away. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | title: Home 4 | heroImage: logo.png 5 | heroText: PowerApps Guidelines 6 | tagline: Coding standards and Guidelines for Customizing and Extending Power Apps, Dynamics 365 Apps & Power Automate 7 | actions: 8 | - text: Get Started → 9 | link: /00.introduction 10 | type: primary 11 | - text: Introduction 12 | link: /guide/ 13 | type: secondary 14 | features: 15 | - title: Code standards 16 | details: No confusions how to do and name parts of the solution. Understanding solutions faster of other projects. 17 | - title: Guidelines 18 | details: Follow the best practices of experienced senior consultants and developers. Don re-invent the wheel again. 19 | - title: Improve 20 | details: Learn from this guidelines be reading it. Share your leasons learned and help improve this guidelines. 21 | footer: LGPL-3.0 | Copyright © 2022 AutomateValue 22 | --- 23 | 24 | # PowerApps Guidelines project 25 | 26 | This project attempts to provide guidelines for the Power Platform, espacilly Power Apps, Power Automate and the Dynamics 365 CE apps. 27 | 28 | ## Set up and work locally 29 | 30 | These instructions will get you a copy of the PowerApps guidelines website up and running on your local machine for writing and development purposes. See deployment for notes on how to deploy the PowerApps guidelines website. 31 | 32 | ### Prerequisites 33 | 34 | The PowerApps guidelines website is build upon [VuePress](https://vuepress.vuejs.org/). To run the website locally it requires Node.js version 8.6 or higher and npm. To check if Node.js and npm is installed open the command line and type the following lines to show the versions of them: 35 | 36 | ```sh 37 | node -v 38 | npm -v 39 | ``` 40 | 41 | To install or update Node.js download the installer from To update npm open the command line and type: 42 | 43 | ```sh 44 | npm install npm@latest -g 45 | ``` 46 | 47 | Then restore all dependencies of the project by open the command line in the root of the project and type: 48 | ```sh 49 | npm install 50 | ``` 51 | 52 | To update existing packages to their latest version: 53 | 54 | ```sh 55 | npm outdated # show out of date dependencies 56 | npm update 57 | ``` 58 | 59 | ### Running 60 | 61 | To start writing documentation: 62 | 63 | ```sh 64 | npm run dev 65 | ``` 66 | 67 | This command will start a local development server on that runs the PowerApps guidelines website. Every change in the guidelines will be immediately visible on the local running website. 68 | 69 | ## Writing 70 | 71 | TODO 72 | 73 | We created two Vue-components to visualize if rules are required or recommended. Place the following tags behing the title of a guideline to indicate the importance: 74 | 75 | 1. The tag `` will be rendered into . Use this for guidelines that you should never skip and should be applicable to all situations. 76 | 2. The tag `` will be rendered into . Use this for strongly recommended guidelines. 77 | 3. The tag `` will be rendered into . Use this for guidellines that may not be applicable in all situations. 78 | 79 | ## Deploying 80 | 81 | We are hosting the PowerApps Guidelines on [Netlify](https://www.netlify.com/). Netlify will build on each commit in the `master` branch and publish it, so deploying is fully automated. 82 | 83 | [![Netlify Status](https://api.netlify.com/api/v1/badges/98c67366-67a1-45ad-b485-91c072a23906/deploy-status)](https://app.netlify.com/sites/powerapps-guidelines/deploys) 84 | 85 | Want to deploy yourself, than running the following command will publish the guidelines as a static website in the folder `.vuepress/dist` which can than be served by any webserver. 86 | 87 | ```sh 88 | npm run build 89 | ``` 90 | 91 | ## Contributing 92 | 93 | Please read [CONTRIBUTING.md](TODO) for details on our code of conduct, and the process for submitting pull requests to us. 94 | 95 | ## Style of writing? 96 | 97 | Same as [Microsoft Azure REST API Guidelines]([https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md) ? 98 | 99 | :white_check_mark: **DO** adopt this pattern. If you feel you need an exception, contact the Azure HTTP/REST Stewardship Board **prior** to implementation. 100 | 101 | :ballot_box_with_check: **YOU SHOULD** adopt this pattern. If not following this advice, you MUST disclose your reason during the Azure HTTP/REST Stewardship Board review. 102 | 103 | :heavy_check_mark: **YOU MAY** consider this pattern if appropriate to your situation. No notification to the Azure HTTP/REST Stewardship Board is required. 104 | 105 | :warning: **YOU SHOULD NOT** adopt this pattern. If not following this advice, you MUST disclose your reason during the Azure HTTP/REST Stewardship Board review. 106 | 107 | :no_entry: **DO NOT** adopt this pattern. If you feel you need an exception, contact the Azure HTTP/REST Stewardship Board **prior** to implementation. 108 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "powerapps-guidelines", 4 | "version": "1.0.0", 5 | "description": "Coding standards and Guidelines for Customizing and Extending PowerApps & Dynamics 365 Apps & Power Automate", 6 | "keywords": [ 7 | "powerapps", 8 | "powerautomate", 9 | "dynamics-crm", 10 | "dynamics-365", 11 | "d365", 12 | "guidelines", 13 | "coding-standards", 14 | "best-practices" 15 | ], 16 | "homepage": "https://github.com/AutomateValue/PowerApps-Guidelines", 17 | "bugs": { 18 | "url": "https://github.com/AutomateValue/PowerApps-Guidelines/issues" 19 | }, 20 | "repository": "github:AutomateValue/PowerApps-Guidelines", 21 | "author": "Remy van Duijkeren