{"id":661,"date":"2023-12-22T16:14:00","date_gmt":"2023-12-22T16:14:00","guid":{"rendered":"https:\/\/automatethemundane.com\/index.php\/2023\/12\/22\/display-mermaid-js-on-a-model-driven-app\/"},"modified":"2024-03-21T14:17:55","modified_gmt":"2024-03-21T14:17:55","slug":"display-mermaid-js-on-a-model-driven-app","status":"publish","type":"post","link":"https:\/\/automatethemundane.com\/index.php\/2023\/12\/22\/display-mermaid-js-on-a-model-driven-app\/","title":{"rendered":"Display Mermaid.js on a Model Driven App"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">The Why<\/h1>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">I am a big fan of mermaid.js <a href=\"https:\/\/mermaid.js.org\/\">Mermaid | Diagramming and charting tool<\/a>. I love how easy it is to build diagrams and charts using code. For a while I have been wanting to integrate into a Model Driven App, but haven't had a great use case. This week however I was asked to come up with a solution to speed up diagrams being built by our team and gave it a whirl. This post will go over the basics of building a mermaid diagram using power automate, saving it in Dataverse, then showing it in a model driven app. <\/p>\n\n\n\n<h1 class=\"wp-block-heading\">The How<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Table and app setup<\/h2>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">I have a solution called Mermaid. In the solution I have a table called mermaid with a multiline rich text column called mermaidhtml.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-1024x477.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">I have also created a MDA called Mermaid App with the mermaid table in it. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mermaid Setup<\/h2>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">For this example I will be making a very simple diagram that shows the created by, the created on, and the Primary Name. You can get very complex with this and its really up to you as to what you want to make. Using the mermaid live editor I can plan out my design then copy and paste the code to Power Automate<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-1-1024x428.png\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>flowchart TD\n    A&#91;Row Name] --&gt; B&#91;Created By]\n    A&#91;Row Name] --&gt; C&#91;Created On]<\/code><\/pre>\n\n\n\n<div class=\"wp-block-wp-mermaid-block mermaid\">\n\n\nflowchart TD\n    A[Row Name] --> B[Created By]\n    A[Row Name] --> C[Created On]\n\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Power Automate Flow<\/h2>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">The trigger is when a new row is added to the mermaid table. Then get the row info. The second action is to define the HTML table<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-2.png\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n  &lt;body&gt;\n    &lt;pre class=\"mermaid\"&gt;<\/code><\/pre>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">The next action is to define the HTML footer<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-3.png\" alt=\"\"\/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;\/pre&gt;\n    &lt;script type=\"module\"&gt;\n      import mermaid from 'https:\/\/cdn.jsdelivr.net\/npm\/mermaid@10\/dist\/mermaid.esm.min.mjs';\n    &lt;\/script&gt;\n  &lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">The next action is to define and set the actual mermaid code<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-4.png\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-5.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">For the created by I am using the following code<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@{outputs('Get_a_row_by_ID')?&#91;'body\/_createdby_value@OData.Community.Display.V1.FormattedValue']}<\/code><\/pre>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">Next we need to combine all the code<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-6.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">We can then create a row in our MDA and see the output of the compose<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-7-1024x459.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">We can then save it to an HTML file and open it to verify that it looks the way we want. \n<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-8.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">With the diagram looking the way we want we can now write it to Dataverse<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-9.png\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Web Resource Configuration<\/h2>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">Next we need to create the HTML code that will display the the diagram<\/p>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">The code requires you to configure two things the entity set name and the column logical name<\/p>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">To get the entity set name use the following http call in your browser<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;YOURORG.crm.dynamics.com\/api\/data\/v9.0\/EntityDefinitions(LogicalName='YOURTABLE')?$select=EntitySetName<\/code><\/pre>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">Update the code below with your information then save it as a .html file<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n    &lt;title&gt;Diagram&lt;\/title&gt;\n    &lt;style&gt;\n        \/* CSS to center the h1 heading *\/\n        body {\n            text-align: center;\n        }\n    &lt;\/style&gt;\n    &lt;script src=\"https:\/\/cdn.jsdelivr.net\/npm\/mermaid@10\/dist\/mermaid.min.js\"&gt;&lt;\/script&gt;\n    &lt;script&gt;\n        mermaid.initialize({ startOnLoad: false });\n\n        function fetchAndDisplayHtmlContent() {\n            var formContext = window.parent.Xrm.Page;\n            var recordId = formContext.data.entity.getId().replace('{', '').replace('}', '');\n\n            var entitySetName = \"ew_mermaids\"; \/\/ Update to your entity\n            var columnName = \"ew_mermaidhtml\"; \/\/ Update to use your column\n\n            var req = new XMLHttpRequest();\n            req.open(\"GET\", formContext.context.getClientUrl() + \"\/api\/data\/v9.0\/\" + entitySetName + \"(\" + recordId + \")?$select=\" + columnName, true);\n            req.setRequestHeader(\"OData-MaxVersion\", \"4.0\");\n            req.setRequestHeader(\"OData-Version\", \"4.0\");\n            req.setRequestHeader(\"Accept\", \"application\/json\");\n            req.setRequestHeader(\"Content-Type\", \"application\/json; charset=utf-8\");\n            req.onreadystatechange = function() {\n                if (this.readyState === 4) {\n                    req.onreadystatechange = null;\n                    if (this.status === 200) {\n                        var result = JSON.parse(this.response);\n                        var diagramHtml = result&#91;columnName];\n                        displayMermaidDiagram(diagramHtml);\n                    } else {\n                        \/\/ Handle error conditions\n                        var error = JSON.parse(this.response).error;\n                        console.error(\"Error fetching diagram HTML: \", error.message);\n                    }\n                }\n            };\n            req.send();\n        }\n\n        function displayMermaidDiagram(diagramHtml) {\n            var mermaidCode = extractMermaidCode(diagramHtml);\n            var container = document.getElementById('diagramContainer');\n            container.textContent = mermaidCode; \/\/ Use textContent for plain text\n            mermaid.init(undefined, container);\n        }\n\n        function extractMermaidCode(html) {\n            var match = \/&lt;pre class=&#91;'\"]mermaid&#91;'\"]&gt;(&#91;sS]*?)&lt;\/pre&gt;\/.exec(html);\n            return match ? match&#91;1].trim() : \"Diagram code not found\";\n        }\n    &lt;\/script&gt;\n&lt;\/head&gt;\n&lt;body onload=\"fetchAndDisplayHtmlContent()\"&gt;\n    &lt;h1&gt;Diagram&lt;\/h1&gt;\n    &lt;div id=\"diagramContainer\"&gt;&lt;\/div&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">Upload the html file to your solution as a webresource. For me I named it as testmermaidhtml<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-10-1024x496.png\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Form Configuration<\/h2>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">The last step in our journey is to configure the form to show the diagram<\/p>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">I updated a main form to have just the basic information I needed. Then I added a 2 column section and place the mermaidhtml column on the left hand side, then made it read only. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-11-1024x634.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">Then add a HTML web resource to the form and select the resource we created previously.\n\n<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-12.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">You should now see a \u201cerror\u201d on the screen. This is because you are not actually in a row and are not pulling in any information. \n<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-13-1024x632.png\" alt=\"\"\/><\/figure>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">Save and publish the form. Then navigate to the MDA you made earlier. You should now see the diagram on the form!<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/untitled-14-1024x460.png\" alt=\"\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Next Steps<\/h1>\n\n\n\n<p class=\"has-text-color\" style=\"color:rgb(0, 0, 0)\">This was a really fun project and I have a few ideas on how to improve it but for the time being go forth and have a great low code day. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Why I am a big fan of mermaid.js Mermaid | Diagramming and charting tool. I love how easy it is to build diagrams and charts using code. For a while I have been wanting to integrate into a Model Driven App, but haven&#8217;t had a great use case. This week however I was asked [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":659,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,23,6,30],"tags":[31,4,5,29],"class_list":["post-661","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dataverse","category-forms","category-model-driven-app","category-power-automate","tag-forms","tag-mda","tag-power-apps","tag-power-automate","entry","has-media"],"jetpack_featured_media_url":"https:\/\/automatethemundane.com\/wp-content\/uploads\/2023\/12\/photo-1602101319087-18d00e6109c0-scaled.jpg","_links":{"self":[{"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/posts\/661","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/comments?post=661"}],"version-history":[{"count":3,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/posts\/661\/revisions"}],"predecessor-version":[{"id":713,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/posts\/661\/revisions\/713"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/media\/659"}],"wp:attachment":[{"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/media?parent=661"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/categories?post=661"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/automatethemundane.com\/index.php\/wp-json\/wp\/v2\/tags?post=661"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}