├── img ├── 32px.png └── drb_icon.png ├── index.html ├── drb_index.htm ├── js ├── generate_drb_custom_js.bat ├── drb.namespaces.js ├── drb.logic.retrievenextlink.js ├── drb.logic.executeworkflow.js ├── drb.logic.create.js ├── drb.logic.update.js ├── drb.logic.delete.js ├── drb.utilities.js ├── drb.logic.order.js ├── drb.logic.retrievesingle.js ├── drb.xrm.js ├── drb.logic.predefinedquery.js ├── drb.logic.association.js ├── drb.common.xrm.js ├── drb.customui.js ├── drb.logic.column.js ├── drb.common.js ├── drb.logic.managefileimagedata.js └── drb.models.js ├── LICENSE ├── README.md ├── Dataverse REST Builder.sln └── css └── drb_custom.css /img/32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuidoPreite/DRB/HEAD/img/32px.png -------------------------------------------------------------------------------- /img/drb_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuidoPreite/DRB/HEAD/img/drb_icon.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dataverse REST Builder 4 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /drb_index.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dataverse REST Builder 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | 18 | 19 | -------------------------------------------------------------------------------- /js/generate_drb_custom_js.bat: -------------------------------------------------------------------------------- 1 | REM set the file to empty 2 | type NUL > drb_custom.js 3 | REM define the files to combine 4 | set list= drb.namespaces.js drb.dom.js drb.utilities.js drb.xrm.getdemodata.js drb.models.js drb.ui.js drb.xrm.js drb.common.xrm.js drb.common.map.js drb.common.js drb.logic.js drb.logic.bindings.js drb.generatecode.js drb.generatepostman.js drb.customui.js drb.logic.retrievesingle.js drb.logic.column.js drb.logic.filter.js drb.logic.order.js drb.logic.retrievemultiple.js drb.logic.set.js drb.logic.create.js drb.logic.update.js drb.logic.delete.js drb.logic.association.js drb.logic.retrievenextlink.js drb.logic.predefinedquery.js drb.logic.dataverseexecute.js drb.logic.executeworkflow.js drb.logic.managefileimagedata.js drb.collection.js drb.initialize.js 5 | REM merge the files 6 | for %%a in (%list%) do type %%a >> drb_custom.js & echo. >> drb_custom.js & echo. >> drb_custom.js -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Guido Preite 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /js/drb.namespaces.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Namespaces 2 | var DRB = {}; // Application Namespace 3 | DRB.DOM = {}; // DOM 4 | DRB.Common = {}; // Common Functions 5 | DRB.Metadata = {}; // Store temporarily the retrieved Metadata 6 | DRB.Models = {}; // Models used by the Application 7 | DRB.Settings = {}; // Settings used by the Application 8 | DRB.UI = {}; // Functions to manage UI elements 9 | DRB.Utilities = {}; // Utilities Functions 10 | DRB.Xrm = {}; // Xrm Functions 11 | DRB.Collection = {}; // Collection Functions 12 | DRB.CustomUI = {}; // Custom UI Functions 13 | DRB.GenerateCode = {}; // Generate Code Functions 14 | DRB.GeneratePostman = {}; // Generate Postman Functions 15 | 16 | DRB.Logic = {}; // Functions defined for each operation 17 | DRB.Logic.RetrieveSingle = {}; // Retrieve Single Functions 18 | DRB.Logic.RetrieveMultiple = {}; // Retrieve Multiple Functions 19 | DRB.Logic.Create = {}; // Create Functions 20 | DRB.Logic.Update = {}; // Update Functions 21 | DRB.Logic.Delete = {}; // Delete Functions 22 | DRB.Logic.Association = {}; // Associate, Disassociate Functions 23 | DRB.Logic.RetrieveNextLink = {}; // Retrieve NextLink Functions 24 | DRB.Logic.PredefinedQuery = {}; // Predefined Query Functions 25 | DRB.Logic.DataverseExecute = {}; // Dataverse Action, Dataverse Function Functions 26 | DRB.Logic.ExecuteWorkflow = {}; // Execute Workflow Functions 27 | DRB.Logic.ManageFileImageData = {}; // Manage File Image Data Functions 28 | // #endregion -------------------------------------------------------------------------------- /js/drb.logic.retrievenextlink.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.RetrieveNextLink 2 | /** 3 | * Retrieve NextLink - Bind NextLink 4 | * @param {string} id Id 5 | */ 6 | DRB.Logic.RetrieveNextLink.BindNextLink = function (id) { 7 | $("#" + id).on("change", function (e) { 8 | var nextLinkValue = $(this).val(); 9 | DRB.Metadata.CurrentNode.data.configuration.nextLink = nextLinkValue; 10 | // try to extract Table from the link 11 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 12 | var parseLink = nextLinkValue; 13 | if (parseLink.indexOf("?") > -1) { parseLink = parseLink.substring(0, parseLink.indexOf("?")); } 14 | if (parseLink.lastIndexOf("/") > -1 && parseLink.length > parseLink.lastIndexOf("/")) { 15 | parseLink = parseLink.substring(parseLink.lastIndexOf("/") + 1); 16 | var table = DRB.Utilities.GetRecordByProperty(DRB.Metadata.Tables, "EntitySetName", parseLink); 17 | if (DRB.Utilities.HasValue(table)) { 18 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = { logicalName: table.LogicalName, schemaName: table.SchemaName, label: table.Name, entitySetName: table.EntitySetName }; 19 | } 20 | } 21 | }); 22 | } 23 | 24 | /** 25 | * Retrieve NextLink - Start 26 | */ 27 | DRB.Logic.RetrieveNextLink.Start = function () { 28 | // create DOM and bindings 29 | DRB.CustomUI.AddProcess(); 30 | DRB.CustomUI.AddTokenHeader(); 31 | DRB.CustomUI.AddSpacer(); 32 | DRB.CustomUI.AddImpersonate(); 33 | DRB.CustomUI.AddSpacer(); 34 | DRB.CustomUI.AddFormattedValues(); 35 | DRB.CustomUI.AddDetectChanges(); 36 | DRB.CustomUI.AddRetrieveCount(); 37 | DRB.CustomUI.AddSpacer(); 38 | 39 | // #region NextLink 40 | var divNextLink = DRB.UI.CreateEmptyDiv(DRB.DOM.NextLink.Div.Id); 41 | divNextLink.append(DRB.UI.CreateSpan(DRB.DOM.NextLink.Span.Id, DRB.DOM.NextLink.Span.Name)); 42 | divNextLink.append(DRB.UI.CreateInputNextLink(DRB.DOM.NextLink.Input.Id)); 43 | $("#" + DRB.DOM.ConfigureContent.Id).append(divNextLink); 44 | DRB.Logic.RetrieveNextLink.BindNextLink(DRB.DOM.NextLink.Input.Id); 45 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.nextLink)) { 46 | $("#" + DRB.DOM.NextLink.Input.Id).val(DRB.Metadata.CurrentNode.data.configuration.nextLink).change(); 47 | } 48 | // #endregion 49 | 50 | DRB.CustomUI.AddSpacer(); 51 | } 52 | // #endregion -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dataverse REST Builder 2 | Dataverse REST Builder 3 | Dataverse REST Builder (DRB) is an application to create and execute requests against the Dataverse Web API endpoint.

4 | 5 | The tool is released as Managed Solution, for XrmToolBox (listed inside the Tool Library) or can be loaded inside Dataverse DevTools (VS Code extension). 6 | 7 | The tool is also available as Browser Extension for Google Chrome and Microsoft Edge. 8 | 9 | It is possible to export the requests in a format compatible with the following applications: 10 | - Postman 11 | - REST Client (VS Code extension) 12 | - Thunder Client (VS Code extension) 13 | 14 | **Demo**: https://guidopreite.github.io/DRB/ 15 | 16 | Dataverse REST Builder has been shown on _The DevConnect Show_ by Danish Naglekar, you can find the video below 17 | 18 | [![Ep.10: Guido Preite on The DevConnect Show](https://img.youtube.com/vi/VYtWd5QDQq8/0.jpg)](https://www.youtube.com/watch?v=VYtWd5QDQq8) 19 | 20 | Carl de Souza content about Dataverse REST Builder: 21 | 22 | Blog post: Using the Dataverse REST Builder to Build REST Requests 23 | 24 | [![Dataverse REST Builder | #PowerPlatformTV 045](https://img.youtube.com/vi/xrNrhyHRYR8/0.jpg)](https://www.youtube.com/watch?v=xrNrhyHRYR8) 25 | 26 | Managed Solution version [![Github Downloads](https://img.shields.io/github/downloads/GuidoPreite/DRB/total.svg)](https://github.com/GuidoPreite/DRB/releases) 27 | 28 | XrmToolBox version [![NuGet Downloads](https://img.shields.io/nuget/dt/GuidoPreite.DRB.svg)](https://www.xrmtoolbox.com/plugins/GuidoPreite.DRB/) 29 | -------------------------------------------------------------------------------- /js/drb.logic.executeworkflow.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.ExecuteWorkflow 2 | /** 3 | * Execute Workflow - Bind Table 4 | * @param {string} id Id 5 | */ 6 | DRB.Logic.ExecuteWorkflow.BindTable = function (id) { 7 | $("#" + id).on("change", function (e) { 8 | var tableLogicalName = $(this).val(); 9 | DRB.Metadata.QueryObjectTypeCode = null; 10 | var table = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 11 | if (DRB.Utilities.HasValue(table)) { 12 | // Fill data.configuration (primaryEntity) 13 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = { logicalName: table.LogicalName, schemaName: table.SchemaName, label: table.Name, entitySetName: table.EntitySetName }; 14 | // Metadata 15 | DRB.Metadata.QueryObjectTypeCode = table.ObjectTypeCode; 16 | } 17 | }); 18 | } 19 | 20 | /** 21 | * Execute Workflow - Start 22 | */ 23 | DRB.Logic.ExecuteWorkflow.Start = function () { 24 | // Metadata 25 | DRB.Metadata.QueryObjectTypeCode = null; 26 | 27 | // create DOM and bindings 28 | DRB.CustomUI.AddVersion(); 29 | DRB.CustomUI.AddProcess(); 30 | DRB.CustomUI.AddTokenHeader(); 31 | DRB.CustomUI.AddSpacer(); 32 | DRB.CustomUI.AddImpersonate(); 33 | DRB.CustomUI.AddSpacer(); 34 | 35 | // #region Table 36 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Table.Span.Id, DRB.DOM.Table.Span.Name)); 37 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.Table.Dropdown.Id)); 38 | DRB.UI.FillDropdown(DRB.DOM.Table.Dropdown.Id, DRB.DOM.Table.Dropdown.Name, new DRB.Models.Records(DRB.Metadata.Tables).ToDropdown()); 39 | DRB.Logic.ExecuteWorkflow.BindTable(DRB.DOM.Table.Dropdown.Id); 40 | // #endregion 41 | 42 | DRB.CustomUI.AddSpacer(); 43 | DRB.CustomUI.AddPrimaryId(); 44 | DRB.CustomUI.AddSpacer(); 45 | DRB.CustomUI.AddWorkflowId(); 46 | DRB.CustomUI.AddSpacer(); 47 | 48 | // #region Triggers 49 | // events triggered after due to DOM connections to other elements 50 | 51 | // Table 52 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryEntity)) { 53 | // check if the table exists 54 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName); 55 | if (!DRB.Utilities.HasValue(checkTable)) { 56 | // if the table doesn't exist reset the relevant values 57 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 58 | DRB.Metadata.CurrentNode.data.configuration.primaryId = ""; 59 | DRB.Metadata.CurrentNode.data.configuration.workflowId = ""; 60 | } else { 61 | // trigger change with table logical name 62 | $("#" + DRB.DOM.Table.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName).change(); 63 | } 64 | } 65 | // #endregion 66 | } 67 | // #endregion -------------------------------------------------------------------------------- /Dataverse REST Builder.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.1585 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C9B80C1E-1848-47AF-8460-0D2D1C266FB8}" 7 | ProjectSection(SolutionItems) = preProject 8 | drb_index.htm = drb_index.htm 9 | EndProjectSection 10 | EndProject 11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "img", "img", "{F6F90D6D-CAD2-4F8B-937D-827A59F5B29B}" 12 | ProjectSection(SolutionItems) = preProject 13 | img\32px.png = img\32px.png 14 | img\drb_icon.png = img\drb_icon.png 15 | EndProjectSection 16 | EndProject 17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "css", "css", "{B4CE0E38-C67F-43D4-895D-64F51D8949AB}" 18 | ProjectSection(SolutionItems) = preProject 19 | css\drb_custom.css = css\drb_custom.css 20 | css\drb_requirements.css = css\drb_requirements.css 21 | EndProjectSection 22 | EndProject 23 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "js", "js", "{551175FB-CD73-40F9-A36B-940B2C80F8FA}" 24 | ProjectSection(SolutionItems) = preProject 25 | js\drb.collection.js = js\drb.collection.js 26 | js\drb.common.js = js\drb.common.js 27 | js\drb.common.map.js = js\drb.common.map.js 28 | js\drb.common.xrm.js = js\drb.common.xrm.js 29 | js\drb.customui.js = js\drb.customui.js 30 | js\drb.dom.js = js\drb.dom.js 31 | js\drb.generatecode.js = js\drb.generatecode.js 32 | js\drb.generatepostman.js = js\drb.generatepostman.js 33 | js\drb.initialize.js = js\drb.initialize.js 34 | js\drb.logic.association.js = js\drb.logic.association.js 35 | js\drb.logic.bindings.js = js\drb.logic.bindings.js 36 | js\drb.logic.column.js = js\drb.logic.column.js 37 | js\drb.logic.create.js = js\drb.logic.create.js 38 | js\drb.logic.dataverseexecute.js = js\drb.logic.dataverseexecute.js 39 | js\drb.logic.delete.js = js\drb.logic.delete.js 40 | js\drb.logic.executeworkflow.js = js\drb.logic.executeworkflow.js 41 | js\drb.logic.filter.js = js\drb.logic.filter.js 42 | js\drb.logic.js = js\drb.logic.js 43 | js\drb.logic.managefileimagedata.js = js\drb.logic.managefileimagedata.js 44 | js\drb.logic.order.js = js\drb.logic.order.js 45 | js\drb.logic.predefinedquery.js = js\drb.logic.predefinedquery.js 46 | js\drb.logic.retrievemultiple.js = js\drb.logic.retrievemultiple.js 47 | js\drb.logic.retrievenextlink.js = js\drb.logic.retrievenextlink.js 48 | js\drb.logic.retrievesingle.js = js\drb.logic.retrievesingle.js 49 | js\drb.logic.set.js = js\drb.logic.set.js 50 | js\drb.logic.update.js = js\drb.logic.update.js 51 | js\drb.models.js = js\drb.models.js 52 | js\drb.namespaces.js = js\drb.namespaces.js 53 | js\drb.ui.js = js\drb.ui.js 54 | js\drb.utilities.js = js\drb.utilities.js 55 | js\drb.xrm.getdemodata.js = js\drb.xrm.getdemodata.js 56 | js\drb.xrm.js = js\drb.xrm.js 57 | js\drb_requirements.js = js\drb_requirements.js 58 | EndProjectSection 59 | EndProject 60 | Global 61 | GlobalSection(SolutionProperties) = preSolution 62 | HideSolutionNode = FALSE 63 | EndGlobalSection 64 | GlobalSection(NestedProjects) = preSolution 65 | {F6F90D6D-CAD2-4F8B-937D-827A59F5B29B} = {C9B80C1E-1848-47AF-8460-0D2D1C266FB8} 66 | {B4CE0E38-C67F-43D4-895D-64F51D8949AB} = {C9B80C1E-1848-47AF-8460-0D2D1C266FB8} 67 | {551175FB-CD73-40F9-A36B-940B2C80F8FA} = {C9B80C1E-1848-47AF-8460-0D2D1C266FB8} 68 | EndGlobalSection 69 | GlobalSection(ExtensibilityGlobals) = postSolution 70 | SolutionGuid = {5A7EF5CB-D852-4AF8-AEFD-1FC5A8996503} 71 | EndGlobalSection 72 | EndGlobal 73 | -------------------------------------------------------------------------------- /js/drb.logic.create.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.Create 2 | /** 3 | * Create - Start 4 | */ 5 | DRB.Logic.Create.Start = function () { 6 | // default settings 7 | var columnsCriteria = "IsValidForCreate"; 8 | var domObject = "SetColumns"; 9 | var metadataPath = "setFields"; 10 | 11 | // Metadata 12 | DRB.Metadata[metadataPath] = []; 13 | 14 | // create DOM and bindings 15 | DRB.CustomUI.AddVersion(); 16 | DRB.CustomUI.AddProcess(); 17 | DRB.CustomUI.AddTokenHeader(); 18 | DRB.CustomUI.AddSpacer(); 19 | DRB.CustomUI.AddImpersonate(); 20 | DRB.CustomUI.AddSpacer(); 21 | DRB.CustomUI.AddFormattedValues(); 22 | 23 | // #region Return Record 24 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.ReturnRecord.Span.Id, DRB.DOM.ReturnRecord.Span.Name)); 25 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.ReturnRecord.Dropdown.Id)); 26 | DRB.UI.FillDropdown(DRB.DOM.ReturnRecord.Dropdown.Id, DRB.DOM.ReturnRecord.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 27 | DRB.Logic.BindReturnRecord(DRB.DOM.ReturnRecord.Dropdown.Id); 28 | var returnRecordValue = "no"; 29 | if (DRB.Metadata.CurrentNode.data.configuration.returnRecord === true) { returnRecordValue = "yes"; } 30 | // trigger later 31 | // #endregion 32 | 33 | DRB.CustomUI.AddDetectDuplicates(); 34 | DRB.CustomUI.AddSpacer(); 35 | 36 | // #region Table 37 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Table.Span.Id, DRB.DOM.Table.Span.Name)); 38 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.Table.Dropdown.Id)); 39 | DRB.UI.FillDropdown(DRB.DOM.Table.Dropdown.Id, DRB.DOM.Table.Dropdown.Name, new DRB.Models.Records(DRB.Metadata.Tables).ToDropdown()); 40 | DRB.Logic.BindSetTable(DRB.DOM.Table.Dropdown.Id, columnsCriteria, domObject, metadataPath); 41 | // #endregion 42 | 43 | DRB.CustomUI.AddColumns(); 44 | DRB.CustomUI.AddSpacer(); 45 | DRB.CustomUI.AddRelationships(); 46 | DRB.CustomUI.AddTypeColumns(DRB.DOM.ConfigureContent.Id, columnsCriteria, domObject, metadataPath); 47 | DRB.CustomUI.AddSpacer(); 48 | 49 | // #region Triggers 50 | // events triggered after due to DOM connections to other elements 51 | 52 | // Table 53 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryEntity)) { 54 | // check if the table exists 55 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName); 56 | if (!DRB.Utilities.HasValue(checkTable)) { 57 | // if the table doesn't exist reset the connected values 58 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 59 | DRB.Metadata.CurrentNode.data.configuration.primaryIdField = ""; 60 | DRB.Metadata.CurrentNode.data.configuration.fields = []; 61 | DRB.Metadata.CurrentNode.data.configuration.oneToMany = []; 62 | DRB.Metadata.CurrentNode.data.configuration.manyToOne = []; 63 | DRB.Metadata.CurrentNode.data.configuration.manyToMany = []; 64 | DRB.Metadata.CurrentNode.data.configuration.setFields = []; 65 | } else { 66 | // trigger change with table logical name 67 | $("#" + DRB.DOM.Table.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName).change(); 68 | } 69 | } 70 | 71 | // Return Record 72 | $("#" + DRB.DOM.ReturnRecord.Dropdown.Id).val(returnRecordValue).change(); 73 | // #endregion 74 | } 75 | // #endregion -------------------------------------------------------------------------------- /js/drb.logic.update.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.Update 2 | /** 3 | * Update - Start 4 | */ 5 | DRB.Logic.Update.Start = function () { 6 | // default settings 7 | var columnsCriteria = "IsValidForUpdate"; 8 | var domObject = "SetColumns"; 9 | var metadataPath = "setFields"; 10 | 11 | // Metadata 12 | DRB.Metadata[metadataPath] = []; 13 | 14 | // create DOM and bindings 15 | DRB.CustomUI.AddVersion(); 16 | DRB.CustomUI.AddProcess(); 17 | DRB.CustomUI.AddTokenHeader(); 18 | DRB.CustomUI.AddSpacer(); 19 | DRB.CustomUI.AddImpersonate(); 20 | DRB.CustomUI.AddSpacer(); 21 | DRB.CustomUI.AddFormattedValues(); 22 | 23 | // #region Return Record 24 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.ReturnRecord.Span.Id, DRB.DOM.ReturnRecord.Span.Name)); 25 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.ReturnRecord.Dropdown.Id)); 26 | DRB.UI.FillDropdown(DRB.DOM.ReturnRecord.Dropdown.Id, DRB.DOM.ReturnRecord.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 27 | DRB.Logic.BindReturnRecord(DRB.DOM.ReturnRecord.Dropdown.Id); 28 | var returnRecordValue = "no"; 29 | if (DRB.Metadata.CurrentNode.data.configuration.returnRecord === true) { returnRecordValue = "yes"; } 30 | // trigger later 31 | // #endregion 32 | 33 | DRB.CustomUI.AddDetectDuplicates(); 34 | DRB.CustomUI.AddPrevent(); 35 | DRB.CustomUI.AddSpacer(); 36 | 37 | // #region Table 38 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Table.Span.Id, DRB.DOM.Table.Span.Name)); 39 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.Table.Dropdown.Id)); 40 | DRB.UI.FillDropdown(DRB.DOM.Table.Dropdown.Id, DRB.DOM.Table.Dropdown.Name, new DRB.Models.Records(DRB.Metadata.Tables).ToDropdown()); 41 | DRB.Logic.BindSetTable(DRB.DOM.Table.Dropdown.Id, columnsCriteria, domObject, metadataPath); 42 | // #endregion 43 | 44 | DRB.CustomUI.AddColumns(); 45 | DRB.CustomUI.AddSpacer(); 46 | DRB.CustomUI.AddRelationships(); 47 | DRB.CustomUI.AddUseAlternateKey(); 48 | DRB.CustomUI.AddSpacer(); 49 | DRB.CustomUI.AddTypeColumns(DRB.DOM.ConfigureContent.Id, columnsCriteria, domObject, metadataPath); 50 | DRB.CustomUI.AddSpacer(); 51 | 52 | // #region Triggers 53 | // events triggered after due to DOM connections to other elements 54 | 55 | // Table 56 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryEntity)) { 57 | // check if the table exists 58 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName); 59 | if (!DRB.Utilities.HasValue(checkTable)) { 60 | // if the table doesn't exist reset the connected values 61 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 62 | DRB.Metadata.CurrentNode.data.configuration.primaryIdField = ""; 63 | DRB.Metadata.CurrentNode.data.configuration.primaryId = ""; 64 | DRB.Metadata.CurrentNode.data.configuration.fields = []; 65 | DRB.Metadata.CurrentNode.data.configuration.oneToMany = []; 66 | DRB.Metadata.CurrentNode.data.configuration.manyToOne = []; 67 | DRB.Metadata.CurrentNode.data.configuration.manyToMany = []; 68 | DRB.Metadata.CurrentNode.data.configuration.setFields = []; 69 | 70 | $("#" + DRB.DOM.UseAlternateKey.Dropdown.Id).val("no").change(); 71 | DRB.UI.LockDropdown(DRB.DOM.UseAlternateKey.Dropdown.Id); 72 | } else { 73 | // trigger change with table logical name 74 | $("#" + DRB.DOM.Table.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName).change(); 75 | } 76 | } else { DRB.UI.LockDropdown(DRB.DOM.UseAlternateKey.Dropdown.Id); } 77 | 78 | // Return Record 79 | $("#" + DRB.DOM.ReturnRecord.Dropdown.Id).val(returnRecordValue).change(); 80 | // #endregion 81 | } 82 | // #endregion -------------------------------------------------------------------------------- /js/drb.logic.delete.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.Delete 2 | /** 3 | * Delete - After Table Loaded 4 | * @param {DRB.Models.Table} table Table 5 | */ 6 | DRB.Logic.Delete.AfterTableLoaded = function (table) { 7 | DRB.Logic.FillCurrentMetadata(table); // Fill Current Metadata 8 | DRB.Logic.FillAlternateKeys(); // Fill Alternate Keys 9 | 10 | // Fill data.configuration (primaryEntity, PrimaryIdField) 11 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = { logicalName: table.LogicalName, schemaName: table.SchemaName, label: table.Name, entitySetName: table.EntitySetName }; 12 | DRB.Metadata.CurrentNode.data.configuration.primaryIdField = table.PrimaryIdAttribute; 13 | } 14 | 15 | /** 16 | * Delete - Bind Table 17 | * @param {string} id Id 18 | */ 19 | DRB.Logic.Delete.BindTable = function (id) { 20 | $("#" + id).on("change", function (e) { 21 | var tableLogicalName = $(this).val(); 22 | var table = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 23 | if (DRB.Utilities.HasValue(table)) { 24 | if (table.ColumnsLoaded === false || table.AlternateKeysLoaded === false) { 25 | DRB.UI.ShowLoading("Retrieving Table information...
This is a long-running operation"); 26 | setTimeout(function () { 27 | DRB.Common.RetrieveTablesDetails([tableLogicalName], false, true) 28 | .done(function () { 29 | DRB.Common.SetTables(arguments, DRB.Metadata.Tables, false, true); 30 | DRB.Logic.Delete.AfterTableLoaded(table); 31 | DRB.UI.HideLoading(); 32 | }) 33 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Common.RetrieveTablesDetails Error", DRB.Common.GetErrorMessage(xhr)); }); 34 | }, DRB.Settings.TimeoutDelay); 35 | } else { 36 | DRB.Logic.Delete.AfterTableLoaded(table); 37 | } 38 | } 39 | }); 40 | } 41 | 42 | /** 43 | * Delete - Start 44 | */ 45 | DRB.Logic.Delete.Start = function () { 46 | // create DOM and bindings 47 | DRB.CustomUI.AddVersion(); 48 | DRB.CustomUI.AddProcess(); 49 | DRB.CustomUI.AddTokenHeader(); 50 | DRB.CustomUI.AddSpacer(); 51 | DRB.CustomUI.AddImpersonate(); 52 | DRB.CustomUI.AddSpacer(); 53 | 54 | // #region Table 55 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Table.Span.Id, DRB.DOM.Table.Span.Name)); 56 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.Table.Dropdown.Id)); 57 | DRB.Logic.Delete.BindTable(DRB.DOM.Table.Dropdown.Id); 58 | DRB.UI.FillDropdown(DRB.DOM.Table.Dropdown.Id, DRB.DOM.Table.Dropdown.Name, new DRB.Models.Records(DRB.Metadata.Tables).ToDropdown()); 59 | // #endregion 60 | 61 | DRB.CustomUI.AddUseAlternateKey(); 62 | DRB.CustomUI.AddSpacer(); 63 | 64 | // #region Triggers 65 | // events triggered after due to DOM connections to other elements 66 | 67 | // Table 68 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryEntity)) { 69 | // check if the table exists 70 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName); 71 | if (!DRB.Utilities.HasValue(checkTable)) { 72 | // if the table doesn't exist reset the relevant values 73 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 74 | DRB.Metadata.CurrentNode.data.configuration.primaryIdField = ""; 75 | DRB.Metadata.CurrentNode.data.configuration.primaryId = ""; 76 | 77 | $("#" + DRB.DOM.UseAlternateKey.Dropdown.Id).val("no").change(); 78 | DRB.UI.LockDropdown(DRB.DOM.UseAlternateKey.Dropdown.Id); 79 | } else { 80 | $("#" + DRB.DOM.Table.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName).change(); 81 | } 82 | } else { DRB.UI.LockDropdown(DRB.DOM.UseAlternateKey.Dropdown.Id); } 83 | // #endregion 84 | } 85 | // #endregion -------------------------------------------------------------------------------- /js/drb.utilities.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Utilities 2 | /** 3 | * Utilities - Has Value 4 | * Returns true if a parameter is not undefined, not null and not an empty string, otherwise returns false 5 | * @param {any} parameter Parameter to check 6 | */ 7 | DRB.Utilities.HasValue = function (parameter) { 8 | if (parameter !== undefined && parameter !== null && parameter !== "") { return true; } else { return false; } 9 | } 10 | 11 | /** 12 | * Utilities - Download File 13 | * Download a file (added for BE mode) 14 | */ 15 | DRB.Utilities.DownloadFile = function (blob, fileName) { 16 | try { 17 | if (!DRB.Xrm.IsBEMode()) { 18 | var customLink = document.createElement("a"); 19 | customLink.href = URL.createObjectURL(blob); 20 | customLink.download = fileName; 21 | customLink.click(); 22 | } else { 23 | parent.postMessage({ command: "be_downloadfile", blob: blob, fileName: fileName }, '*'); 24 | } 25 | } catch (e) { } 26 | } 27 | 28 | 29 | /** 30 | * Utilities - Local Storage Available 31 | * Check if localStorage is available 32 | */ 33 | DRB.Utilities.LocalStorageAvailable = function () { 34 | try { 35 | localStorage.setItem("DRB_CheckLocalStorage", "DRB"); 36 | localStorage.removeItem("DRB_CheckLocalStorage"); 37 | return true; 38 | } catch (e) { return false; } 39 | } 40 | 41 | /** 42 | * Utilities - Generate Guid 43 | * Returns a Random Guid with options to add Braces or Upper Case 44 | * @param {boolean} braces if the Guid contains braces 45 | * @param {boolean} upperCase if the Guid is returned as Upper Case 46 | */ 47 | DRB.Utilities.GenerateGuid = function (braces, upperCase) { 48 | var randomGuid = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".replace(/x/g, function (c) { 49 | var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); 50 | return v.toString(16); 51 | }); 52 | if (braces === true) { randomGuid = "{" + randomGuid + "}"; } 53 | if (upperCase === true) { randomGuid = randomGuid.toUpperCase(); } 54 | return randomGuid; 55 | } 56 | 57 | /** 58 | * Utilities - Remove Duplicates From Array 59 | * Returns a new Array without duplicates 60 | * @param {any[]} array Array to check 61 | */ 62 | DRB.Utilities.RemoveDuplicatesFromArray = function (array) { 63 | var values = array.filter(function (item, pos) { return array.indexOf(item) === pos; }); 64 | return values; 65 | } 66 | 67 | /** 68 | * Utilities - Get Record By Property 69 | * Returns a Record matching the property and the value passed 70 | * @param {any[]} records Records 71 | * @param {string} propertyName Property Name 72 | * @param {any} propertyValue Property Value 73 | */ 74 | DRB.Utilities.GetRecordByProperty = function (records, propertyName, propertyValue) { 75 | if (Array.isArray(records)) { 76 | for (var count = 0; count < records.length; count++) { 77 | if (records[count].hasOwnProperty(propertyName) && records[count][propertyName] == propertyValue) { return records[count]; } 78 | } 79 | } 80 | return null; 81 | } 82 | 83 | /** 84 | * Utilities - Get Record By Id 85 | * Returns a record matching the id 86 | * @param {any[]} records Records 87 | * @param {any} id Id 88 | */ 89 | DRB.Utilities.GetRecordById = function (records, id) { 90 | return DRB.Utilities.GetRecordByProperty(records, "Id", id); 91 | } 92 | 93 | /** 94 | * Utilities - Custom Sort 95 | * sort an array on a specific property, minus sign (-) in front of the property defines a reverse sort 96 | * @param {string} property Property Name 97 | */ 98 | DRB.Utilities.CustomSort = function (property) { 99 | var sortOrder = 1; 100 | if (property[0] === "-") { sortOrder = -1; property = property.substr(1); } 101 | 102 | return function (a, b) { 103 | var result = (a[property].toLowerCase() < b[property].toLowerCase()) ? -1 : (a[property].toLowerCase() > b[property].toLowerCase()) ? 1 : 0; 104 | return result * sortOrder; 105 | } 106 | } 107 | // #endregion -------------------------------------------------------------------------------- /js/drb.logic.order.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.Order 2 | // Order Columns Functions (used in Retrieve Multiple) 3 | 4 | /** 5 | * Logic - Bind Order Column Value 6 | * @param {string} id Id 7 | * @param {string} metadataPath Metadata Path 8 | */ 9 | DRB.Logic.BindOrderColumnValue = function (id, metadataPath) { 10 | $("#" + id).on("change", function (e) { 11 | // get control value 12 | var controlValue = $(this).val(); 13 | // extract the index from the control name 14 | var controlName = $(this).attr('id'); 15 | var elementIndex = DRB.Common.ExtractIndexFromControlName(controlName); 16 | if (elementIndex === -1) { return; } // if index not found do nothing 17 | 18 | // get full Metadata and configuration path 19 | var refMetadata = DRB.Metadata; 20 | var refConfiguration = DRB.Metadata.CurrentNode.data.configuration; 21 | // get full Metadata and configuration path 22 | metadataPath.split("_").forEach(function (path) { 23 | if (isNaN(parseInt(path))) { 24 | if (refMetadata.hasOwnProperty(path)) { refMetadata = refMetadata[path]; } 25 | if (refConfiguration.hasOwnProperty(path)) { refConfiguration = refConfiguration[path]; } 26 | } else { 27 | // is a position number 28 | var metadataIndex = parseInt(path); 29 | refMetadata.forEach(function (refItem, refItemIndex) { 30 | if (refItem.Id === metadataIndex) { 31 | // this is the correct path to follow 32 | refMetadata = refMetadata[refItemIndex]; 33 | refConfiguration = refConfiguration[refItemIndex]; 34 | } 35 | }); 36 | } 37 | }); 38 | 39 | 40 | // update DRB.Metadata.OrderColumns and configuration.orderFields with the new value 41 | refMetadata.forEach(function (column, columnIndex) { 42 | if (column.Id === elementIndex) { 43 | // save the current column properties 44 | var field = JSON.parse(JSON.stringify(column.Value)); 45 | if (controlName.indexOf("cbx_") === 0) { field.value = controlValue; } 46 | 47 | // update refMetadata and refConfiguration 48 | column.Value = field; 49 | refConfiguration[columnIndex] = field; 50 | } 51 | }); 52 | }); 53 | } 54 | 55 | /** 56 | * Logic - Bind Order Column 57 | * @param {string} id Id 58 | * @param {string} columnType Column Type 59 | * @param {string} domObject DOM Object 60 | * @param {string} metadataPath Metadata Path 61 | */ 62 | DRB.Logic.BindOrderColumn = function (id, columnType, domObject, metadataPath) { 63 | $("#" + id).on("change", function (e) { 64 | var columnLogicalName = $(this).val(); 65 | var column = DRB.Utilities.GetRecordById(DRB.Metadata.CurrentColumns, columnLogicalName); 66 | if (DRB.Utilities.HasValue(column)) { 67 | // define field 68 | var field = { logicalName: column.LogicalName, schemaName: column.SchemaName, label: column.Name, type: column.AttributeType, oDataName: column.ODataName, value: null }; 69 | // extract the index from the control name 70 | var controlName = $(this).attr('id'); 71 | var elementIndex = DRB.Common.ExtractIndexFromControlName(controlName); 72 | if (elementIndex === -1) { return; } // if index not found do nothing 73 | 74 | // get full Metadata and configuration path 75 | var refMetadata = DRB.Metadata; 76 | var refConfiguration = DRB.Metadata.CurrentNode.data.configuration; 77 | // get full Metadata and configuration path 78 | metadataPath.split("_").forEach(function (path) { 79 | if (isNaN(parseInt(path))) { 80 | if (refMetadata.hasOwnProperty(path)) { refMetadata = refMetadata[path]; } 81 | if (refConfiguration.hasOwnProperty(path)) { refConfiguration = refConfiguration[path]; } 82 | } else { 83 | // is a position number 84 | var metadataIndex = parseInt(path); 85 | refMetadata.forEach(function (refItem, refItemIndex) { 86 | if (refItem.Id === metadataIndex) { 87 | // this is the correct path to follow 88 | refMetadata = refMetadata[refItemIndex]; 89 | refConfiguration = refConfiguration[refItemIndex]; 90 | } 91 | }); 92 | } 93 | }); 94 | 95 | // update Metadata and configuration 96 | for (var i = 0; i < refMetadata.length; i++) { 97 | if (refMetadata[i].Id === elementIndex) { 98 | refMetadata[i].Value = field; 99 | refConfiguration[i] = field; 100 | break; 101 | } 102 | } 103 | 104 | var uniqueIndex = metadataPath + "_" + elementIndex; 105 | $("#" + DRB.DOM[domObject].TdValue.Id + uniqueIndex).html(""); // empty the cell 106 | var divValue = DRB.UI.CreateEmptyDiv(DRB.DOM[domObject].DivValue.Id + uniqueIndex); 107 | $("#" + DRB.DOM[domObject].TdValue.Id + uniqueIndex).append(divValue); 108 | 109 | var currentId = "cbx_" + DRB.DOM[domObject].ControlValue.Id + uniqueIndex; 110 | divValue.append(DRB.UI.CreateSimpleDropdown(currentId)); 111 | DRB.UI.FillDropdown(currentId, "Select Value", new DRB.Models.Records(DRB.Settings.OptionsOrder).ToDropdown()); 112 | DRB.Logic.BindOrderColumnValue("cbx_" + DRB.DOM[domObject].ControlValue.Id + uniqueIndex, metadataPath); 113 | $("#" + currentId).val(DRB.Settings.OptionsOrder[0].Id).change(); 114 | 115 | } 116 | DRB.Logic.RefreshColumns(columnType, domObject, metadataPath); 117 | }); 118 | } 119 | // #endregion -------------------------------------------------------------------------------- /css/drb_custom.css: -------------------------------------------------------------------------------- 1 | /* #region drb_custom.css */ 2 | /* #region standard HTML components */ 3 | html { 4 | height: 100%; 5 | font-size: 14px; 6 | } 7 | 8 | body { 9 | min-height: 100%; 10 | } 11 | 12 | hr { 13 | border-top: 1px solid #C9C9C9; 14 | } 15 | 16 | button { 17 | margin-right: 8px; 18 | } 19 | 20 | button[disabled] { 21 | cursor: not-allowed; 22 | } 23 | 24 | td { 25 | font-size: 14px; 26 | padding: 5px 5px 5px 0; 27 | } 28 | /* #endregion */ 29 | 30 | /* #region custom classes */ 31 | .spacer { 32 | margin: 8px; 33 | } 34 | 35 | .shortdropdown { 36 | width: 100px; 37 | } 38 | 39 | .block { 40 | display: inline-block; 41 | margin-right: 10px !important; 42 | } 43 | 44 | .notice { 45 | font-size: 12px; 46 | } 47 | 48 | .notice-red { 49 | color: red; 50 | font-weight: bold; 51 | } 52 | 53 | .mapping-container { 54 | border: 1px solid #828282; 55 | padding: 10px; 56 | margin-bottom: 20px; 57 | } 58 | 59 | .mapping-container0 { 60 | border: 2px solid #828282; 61 | padding: 5px; 62 | margin: 2px; 63 | } 64 | 65 | .mapping-container3 { 66 | border: 0px solid #000000; 67 | padding: 5px; 68 | margin: 2px; 69 | } 70 | 71 | .filterspan { 72 | font-weight: bold; 73 | text-transform: uppercase; 74 | } 75 | 76 | .searchbutton { 77 | margin-left: 5px; 78 | padding: 0; 79 | background-color: transparent; 80 | border: 0; 81 | font-size: 1.5rem; 82 | font-weight: 700; 83 | line-height: 1; 84 | color: #000; 85 | text-shadow: 0 1px 0 #fff; 86 | opacity: .5; 87 | } 88 | 89 | .closebutton { 90 | padding: 0; 91 | background-color: transparent; 92 | border: 0; 93 | font-size: 1.5rem; 94 | font-weight: 700; 95 | line-height: 1; 96 | color: #000; 97 | text-shadow: 0 1px 0 #fff; 98 | opacity: .5; 99 | } 100 | 101 | .disabledclose { 102 | padding: 0; 103 | background-color: transparent; 104 | border: 0; 105 | font-size: 1.5rem; 106 | font-weight: 700; 107 | line-height: 1; 108 | color: #000; 109 | text-shadow: 0 1px 0 #fff; 110 | opacity: .0; 111 | cursor: default !important; 112 | } 113 | 114 | .sameline { 115 | display: inline; 116 | } 117 | 118 | .tablefix td { 119 | position: relative; 120 | } 121 | 122 | .centercontent { 123 | display: flex; 124 | justify-content: center; 125 | } 126 | 127 | .columnbutton { 128 | margin-left: 10px; 129 | } 130 | 131 | .checkboxinclude { 132 | margin-top: 10px; 133 | } 134 | 135 | .collectioncontroldiv { 136 | margin-bottom: 4px; 137 | } 138 | /* #endregion */ 139 | 140 | /* #region Grid */ 141 | div.griddetails { 142 | width: 1000px; 143 | white-space: nowrap; 144 | overflow-x: auto; 145 | padding-bottom: 10px; 146 | padding-right: 10px; 147 | } 148 | 149 | table.grid { 150 | font-size: 14px; 151 | border: 1px solid #cccccc; 152 | border-collapse: collapse; 153 | margin-top: 8px; 154 | } 155 | 156 | th.grid { 157 | font-size: 14px; 158 | border: 1px solid #cccccc; 159 | border-spacing: 0px; 160 | border-collapse: collapse; 161 | white-space: nowrap; 162 | text-align: left; 163 | padding: 4px; 164 | background-color: #eeeeee; 165 | color: #333333; 166 | } 167 | 168 | th.gridindex { 169 | font-size: 14px; 170 | text-align: center; 171 | border: 1px solid #cccccc; 172 | background-color: #eeeeee; 173 | } 174 | 175 | td.grid { 176 | font-size: 14px; 177 | border: 1px solid #cccccc; 178 | border-spacing: 0px; 179 | border-collapse: collapse; 180 | white-space: nowrap; 181 | padding: 8px; 182 | vertical-align: top; 183 | } 184 | 185 | td.gridindex { 186 | font-size: 14px; 187 | text-align: center; 188 | border: 1px solid #cccccc; 189 | background-color: #eeeeee; 190 | } 191 | 192 | button.gridexpand { 193 | all: unset; 194 | cursor: pointer; 195 | } 196 | /* #endregion */ 197 | 198 | /* #region bootstrap-select */ 199 | .dropdown-menu li.disabled { 200 | cursor: not-allowed; 201 | } 202 | 203 | div.bootstrap-select { 204 | margin-left: 10px !important; 205 | margin-right: 10px !important; 206 | } 207 | 208 | .block .bootstrap-select { 209 | margin-left: 0px !important; 210 | } 211 | 212 | .selected:not(.active) { 213 | font-style: italic; 214 | font-weight: bold; 215 | } 216 | 217 | .nav-link.active:not(.disabled) { 218 | font-weight: bold; 219 | } 220 | /* #endregion */ 221 | 222 | /* #region bootbox.js */ 223 | .modal-body { 224 | max-height: 500px; 225 | overflow-y: auto; 226 | } 227 | /* #endregion */ 228 | 229 | /* #region Split.js */ 230 | .split { 231 | display: flex; 232 | flex-direction: row; 233 | } 234 | 235 | .gutter { 236 | background-color: #eee; 237 | background-repeat: no-repeat; 238 | background-position: 50%; 239 | } 240 | 241 | .gutter.gutter-horizontal { 242 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg=='); 243 | cursor: col-resize; 244 | } 245 | /* #endregion */ 246 | 247 | /* #region Main Layout (connected to Split.js) */ 248 | .mainlayout { 249 | display: flex; 250 | flex-flow: column; 251 | height: 100%; 252 | } 253 | 254 | .mainlayout .topborder { 255 | border-top: 1px solid #C9C9C9; 256 | } 257 | 258 | .mainlayout .topborder.mainheader { 259 | flex: 0 1 auto; 260 | } 261 | 262 | .mainlayout .topborder.maincontent { 263 | flex: 1 1 auto; 264 | } 265 | 266 | .mainlayout .topborder.mainfooter { 267 | flex: 0 1 30px; 268 | } 269 | /* #endregion */ 270 | 271 | /* #region jsTree */ 272 | .jstree-anchor { 273 | /* https://stackoverflow.com/questions/15070859/wrapping-leaf-text-in-jstree */ 274 | white-space: normal !important; /*enable wrapping*/ 275 | height: auto !important; /*ensure lower nodes move down*/ 276 | padding-right: 24px; /*offset icon width*/ 277 | } 278 | 279 | .hide-icon { 280 | display: none !important; 281 | } 282 | /* #endregion */ 283 | 284 | /* #region Ace.js */ 285 | .code_editor { 286 | width: 100%; 287 | height: 400px; 288 | border: 1px solid #828282; 289 | } 290 | /* #endregion */ 291 | 292 | /* #region Lookup */ 293 | .lookup-results { 294 | height: 300px; 295 | } 296 | /* #endregion */ 297 | 298 | /* #endregion */ 299 | -------------------------------------------------------------------------------- /js/drb.logic.retrievesingle.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.RetrieveSingle 2 | /** 3 | * Retrieve Single - After Table Loaded 4 | * @param {DRB.Models.Table} table Table 5 | */ 6 | DRB.Logic.RetrieveSingle.AfterTableLoaded = function (table) { 7 | DRB.Logic.FillCurrentMetadata(table); // Fill Current Metadata 8 | DRB.Logic.FillRelationshipsColumns(); // Fill Relationships Columns 9 | DRB.Logic.FillColumns(); // Fill Columns 10 | DRB.Logic.FillRelationships(); // Fill Relationships 11 | DRB.Logic.FillAlternateKeys(); // Fill Alternate Keys 12 | 13 | // Fill data.configuration (primaryEntity, PrimaryIdField) 14 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = { logicalName: table.LogicalName, schemaName: table.SchemaName, label: table.Name, entitySetName: table.EntitySetName }; 15 | DRB.Metadata.CurrentNode.data.configuration.primaryIdField = table.PrimaryIdAttribute; 16 | } 17 | 18 | /** 19 | * Retrieve Single - Bind Table 20 | * @param {string} id Id 21 | */ 22 | DRB.Logic.RetrieveSingle.BindTable = function (id) { 23 | $("#" + id).on("change", function (e) { 24 | var tableLogicalName = $(this).val(); 25 | var table = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 26 | if (DRB.Utilities.HasValue(table)) { 27 | if (table.ColumnsLoaded === false || table.RelationshipsLoaded === false || table.AlternateKeysLoaded === false) { 28 | DRB.UI.ShowLoading("Retrieving Table information...
This is a long-running operation"); 29 | setTimeout(function () { 30 | // retrieve the Entity Fields 31 | DRB.Common.RetrieveTablesDetails([tableLogicalName], true, true) 32 | .done(function () { 33 | DRB.Common.SetTables(arguments, DRB.Metadata.Tables, true, true); 34 | var tableLogicalNames = []; 35 | table.OneToManyRelationships.forEach(function (relationship) { tableLogicalNames.push(relationship.SourceTable); tableLogicalNames.push(relationship.TargetTable); }); 36 | table.ManyToOneRelationships.forEach(function (relationship) { tableLogicalNames.push(relationship.SourceTable); tableLogicalNames.push(relationship.TargetTable); }); 37 | table.ManyToManyRelationships.forEach(function (relationship) { tableLogicalNames.push(relationship.SourceTable); tableLogicalNames.push(relationship.TargetTable); }); 38 | tableLogicalNames = DRB.Utilities.RemoveDuplicatesFromArray(tableLogicalNames); // remove duplicates 39 | 40 | var tablesToRetrieve = []; 41 | tableLogicalNames.forEach(function (checkTableLogicalName) { 42 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, checkTableLogicalName); 43 | if (DRB.Utilities.HasValue(checkTable) && checkTable.ColumnsLoaded === false) { tablesToRetrieve.push(checkTableLogicalName); } 44 | }); 45 | if (tablesToRetrieve.length > 0) { 46 | DRB.Common.RetrieveTablesDetails(tablesToRetrieve, false, true) 47 | .done(function () { 48 | DRB.Common.SetTables(arguments, DRB.Metadata.Tables, false, true); 49 | DRB.Logic.RetrieveSingle.AfterTableLoaded(table); 50 | DRB.UI.HideLoading(); 51 | }) 52 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Common.RetrieveTablesDetails Error", DRB.Common.GetErrorMessage(xhr)); }); 53 | } else { 54 | DRB.Logic.RetrieveSingle.AfterTableLoaded(table); 55 | DRB.UI.HideLoading(); 56 | } 57 | }) 58 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Common.RetrieveTablesDetails Error", DRB.Common.GetErrorMessage(xhr)); }); 59 | }, DRB.Settings.TimeoutDelay); 60 | } else { 61 | DRB.Logic.RetrieveSingle.AfterTableLoaded(table); 62 | } 63 | } 64 | }); 65 | } 66 | 67 | /** 68 | * Retrieve Single - Start 69 | */ 70 | DRB.Logic.RetrieveSingle.Start = function () { 71 | // create DOM and bindings 72 | DRB.CustomUI.AddVersion(); 73 | DRB.CustomUI.AddProcess(); 74 | DRB.CustomUI.AddTokenHeader(); 75 | DRB.CustomUI.AddSpacer(); 76 | DRB.CustomUI.AddImpersonate(); 77 | DRB.CustomUI.AddSpacer(); 78 | DRB.CustomUI.AddFormattedValues(); 79 | DRB.CustomUI.AddDetectChanges(); 80 | DRB.CustomUI.AddSpacer(); 81 | 82 | // #region Table 83 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Table.Span.Id, DRB.DOM.Table.Span.Name)); 84 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.Table.Dropdown.Id)); 85 | DRB.UI.FillDropdown(DRB.DOM.Table.Dropdown.Id, DRB.DOM.Table.Dropdown.Name, new DRB.Models.Records(DRB.Metadata.Tables).ToDropdown()); 86 | DRB.Logic.RetrieveSingle.BindTable(DRB.DOM.Table.Dropdown.Id); 87 | // #endregion 88 | 89 | DRB.CustomUI.AddColumns(); 90 | DRB.CustomUI.AddSpacer(); 91 | DRB.CustomUI.AddRelationships(); 92 | DRB.CustomUI.AddUseAlternateKey(); 93 | DRB.CustomUI.AddSpacer(); 94 | 95 | // #region Triggers 96 | // events triggered after due to DOM connections to other elements 97 | 98 | // Table 99 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryEntity)) { 100 | // check if the table exists, if not we set the alternate key to No if was yes 101 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName); 102 | if (!DRB.Utilities.HasValue(checkTable)) { 103 | // if the table doesn't exist reset the relevant values 104 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 105 | DRB.Metadata.CurrentNode.data.configuration.primaryIdField = ""; 106 | DRB.Metadata.CurrentNode.data.configuration.primaryId = ""; 107 | DRB.Metadata.CurrentNode.data.configuration.fields = []; 108 | DRB.Metadata.CurrentNode.data.configuration.oneToMany = []; 109 | DRB.Metadata.CurrentNode.data.configuration.manyToOne = []; 110 | DRB.Metadata.CurrentNode.data.configuration.manyToMany = []; 111 | // end reset 112 | $("#" + DRB.DOM.UseAlternateKey.Dropdown.Id).val("no").change(); 113 | DRB.UI.LockDropdown(DRB.DOM.UseAlternateKey.Dropdown.Id); 114 | } else { 115 | $("#" + DRB.DOM.Table.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName).change(); 116 | } 117 | } else { DRB.UI.LockDropdown(DRB.DOM.UseAlternateKey.Dropdown.Id); } 118 | // #endregion 119 | } 120 | // #endregion -------------------------------------------------------------------------------- /js/drb.xrm.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Xrm 2 | /** 3 | * Xrm - Get Xrm Object 4 | */ 5 | DRB.Xrm.GetXrmObject = function () { 6 | try { 7 | if (typeof parent !== "undefined") { return parent.Xrm; } else { return undefined; } 8 | } catch { return undefined; } 9 | } 10 | 11 | /** 12 | * Xrm - Is XTB Mode 13 | */ 14 | DRB.Xrm.IsXTBMode = function () { 15 | return DRB.Settings.XTBContext; 16 | } 17 | 18 | /** 19 | * Xrm - Is BE Mode 20 | */ 21 | DRB.Xrm.IsBEMode = function () { 22 | return DRB.Settings.BEContext; 23 | } 24 | 25 | /** 26 | * Xrm - Is JWT Mode 27 | */ 28 | DRB.Xrm.IsJWTMode = function () { 29 | return DRB.Settings.JWTContext; 30 | } 31 | 32 | /** 33 | * Xrm - Is DVDT Mode 34 | */ 35 | DRB.Xrm.IsDVDTMode = function () { 36 | return DRB.Settings.DVDTContext; 37 | } 38 | 39 | /** 40 | * Xrm - Is Demo Mode 41 | */ 42 | DRB.Xrm.IsDemoMode = function () { 43 | if (DRB.Xrm.IsXTBMode() || DRB.Xrm.IsBEMode() || DRB.Xrm.IsJWTMode() || DRB.Xrm.IsDVDTMode()) { return false; } 44 | return typeof DRB.Xrm.GetXrmObject() === "undefined"; 45 | } 46 | 47 | /** 48 | * Xrm - Is Instance Mode 49 | */ 50 | DRB.Xrm.IsInstanceMode = function () { 51 | if (DRB.Xrm.IsXTBMode() || DRB.Xrm.IsBEMode() || DRB.Xrm.IsJWTMode() || DRB.Xrm.IsDVDTMode() || DRB.Xrm.IsDemoMode()) { return false; } 52 | return typeof DRB.Xrm.GetXrmObject() !== "undefined"; 53 | } 54 | 55 | /** 56 | * Xrm - Get Client Url 57 | */ 58 | DRB.Xrm.GetClientUrl = function () { 59 | if (DRB.Xrm.IsXTBMode()) { return DRB.Settings.XTBUrl; } 60 | if (DRB.Xrm.IsBEMode()) { return DRB.Settings.BEUrl; } 61 | if (DRB.Xrm.IsJWTMode()) { return DRB.Settings.JWTUrl; } 62 | if (DRB.Xrm.IsDVDTMode()) { return DRB.Settings.DVDTUrl; } 63 | if (DRB.Xrm.IsInstanceMode()) { return DRB.Xrm.GetXrmObject().Utility.getGlobalContext().getClientUrl(); } 64 | if (DRB.Xrm.IsDemoMode()) { return "https://democall"; } 65 | } 66 | 67 | /** 68 | * Xrm - Get Context 69 | */ 70 | DRB.Xrm.GetContext = function () { 71 | var context = "Demo"; 72 | if (DRB.Xrm.IsXTBMode() || DRB.Xrm.IsBEMode() || DRB.Xrm.IsJWTMode() || DRB.Xrm.IsDVDTMode() || DRB.Xrm.IsInstanceMode()) { context = DRB.Xrm.GetClientUrl(); } 73 | return "(" + context + ")"; 74 | } 75 | 76 | /** 77 | * Xrm - Get Metadata Url 78 | */ 79 | DRB.Xrm.GetMetadataUrl = function () { 80 | return DRB.Xrm.GetClientUrl() + "/api/data/v9.0/$metadata"; 81 | } 82 | 83 | /** 84 | * Xrm - Get Current Access Token 85 | */ 86 | DRB.Xrm.GetCurrentAccessToken = function () { 87 | var token = ""; 88 | if (DRB.Xrm.IsXTBMode()) { token = DRB.Settings.XTBToken; } 89 | if (DRB.Xrm.IsBEMode()) { token = DRB.Settings.BEToken; } 90 | if (DRB.Xrm.IsJWTMode()) { token = DRB.Settings.JWTToken; } 91 | if (DRB.Xrm.IsDVDTMode()) { token = DRB.Settings.DVDTToken; } 92 | if (DRB.Xrm.IsDemoMode()) { token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJEUkIiLCJpYXQiOjE2NDA5OTUyMDAsImV4cCI6MTY0MDk5NTIwMCwiYXVkIjoiaHR0cHM6Ly9kZW1vY2FsbCIsInN1YiI6IkRSQiJ9.niwjJ3XiFvsJkisbrcT7P27NK9v1ZfICpw5ITHP1mHo"; } 93 | return token; 94 | } 95 | 96 | /** 97 | * Xrm - Get Version 98 | */ 99 | DRB.Xrm.GetVersion = function () { 100 | var currentVersion = ""; 101 | if (DRB.Xrm.IsXTBMode()) { currentVersion = DRB.Settings.XTBVersion; } 102 | if (DRB.Xrm.IsBEMode()) { currentVersion = DRB.Settings.BEVersion; } 103 | if (DRB.Xrm.IsJWTMode()) { currentVersion = DRB.Settings.JWTVersion; } 104 | if (DRB.Xrm.IsDVDTMode()) { currentVersion = DRB.Settings.DVDTVersion; } 105 | if (DRB.Xrm.IsInstanceMode()) { currentVersion = DRB.Xrm.GetXrmObject().Utility.getGlobalContext().getVersion(); } 106 | if (DRB.Xrm.IsDemoMode()) { currentVersion = "9.1.0.0"; } 107 | 108 | if (!DRB.Utilities.HasValue(currentVersion)) { return ""; } 109 | var versionArray = currentVersion.split("."); 110 | if (versionArray.length < 2) { return ""; } 111 | return versionArray[0] + "." + versionArray[1]; 112 | } 113 | 114 | /** 115 | * Xrm - Retrieve 116 | * @param {string} entitySetName Entity Set Name 117 | * @param {string} filters Filters 118 | */ 119 | DRB.Xrm.Retrieve = function (entitySetName, filters) { 120 | var retrieveUrl = encodeURI(DRB.Xrm.GetClientUrl() + "/api/data/v9.0/" + entitySetName + "?" + filters); 121 | 122 | if (!DRB.Xrm.IsDemoMode()) { 123 | var token = DRB.Xrm.GetCurrentAccessToken(); 124 | return $.ajax({ 125 | type: "GET", 126 | contentType: "application/json; charset=utf-8", 127 | datatype: "json", 128 | async: true, 129 | beforeSend: function (xhr) { 130 | xhr.setRequestHeader("OData-MaxVersion", "4.0"); 131 | xhr.setRequestHeader("OData-Version", "4.0"); 132 | xhr.setRequestHeader("Accept", "application/json"); 133 | xhr.setRequestHeader("Prefer", "odata.include-annotations=\"*\""); 134 | if (DRB.Utilities.HasValue(token)) { xhr.setRequestHeader("Authorization", "Bearer " + token); } 135 | }, 136 | url: retrieveUrl 137 | }); 138 | } 139 | 140 | if (DRB.Xrm.IsDemoMode()) { return $.when(DRB.Xrm.GetDemoData(entitySetName, filters)); } 141 | } 142 | 143 | /** 144 | * Xrm - Retrieve Batch 145 | * @param {any[]} queries Queries 146 | */ 147 | DRB.Xrm.RetrieveBatch = function (queries) { 148 | var batchDescription = "batch_" + DRB.Utilities.GenerateGuid(); 149 | var data = []; 150 | queries.forEach(function (query) { 151 | var retrieveUrl = DRB.Xrm.GetClientUrl() + "/api/data/v9.0/" + query.EntitySetName + "?" + query.Filters; 152 | data.push("--" + batchDescription); 153 | data.push("Content-Type: application/http"); 154 | data.push("Content-Transfer-Encoding: binary"); 155 | data.push(""); 156 | data.push("GET " + retrieveUrl + " HTTP/1.1"); 157 | data.push("Content-Type: application/json"); 158 | data.push("OData-Version: 4.0"); 159 | data.push("OData-MaxVersion: 4.0"); 160 | data.push("Prefer: odata.include-annotations=\"*\""); 161 | data.push(""); 162 | }); 163 | data.push("--" + batchDescription + "--"); 164 | var payload = data.join("\r\n"); 165 | 166 | if (!DRB.Xrm.IsDemoMode()) { 167 | var token = DRB.Xrm.GetCurrentAccessToken(); 168 | return $.ajax({ 169 | method: "POST", 170 | data: payload, 171 | async: true, 172 | beforeSend: function (xhr) { 173 | xhr.setRequestHeader("Content-Type", "multipart/mixed;boundary=" + batchDescription); 174 | xhr.setRequestHeader("OData-MaxVersion", "4.0"); 175 | xhr.setRequestHeader("OData-Version", "4.0"); 176 | xhr.setRequestHeader("Accept", "application/json"); 177 | if (DRB.Utilities.HasValue(token)) { xhr.setRequestHeader("Authorization", "Bearer " + token); } 178 | }, 179 | url: DRB.Xrm.GetClientUrl() + "/api/data/v9.0/$batch" 180 | }); 181 | } 182 | 183 | if (DRB.Xrm.IsDemoMode()) { return $.when(DRB.Xrm.GetDemoDataBatch(queries)); } 184 | } 185 | 186 | /** 187 | * Xrm - Retrieve Batches 188 | * @param {any[]} batchedQueries Batched Queries 189 | */ 190 | DRB.Xrm.RetrieveBatches = function (batchedQueries) { 191 | var xrmCalls = []; 192 | batchedQueries.forEach(function (batchedQuery) { 193 | var queries = []; 194 | batchedQuery.forEach(function (query) { queries.push(query); }); 195 | xrmCalls.push(DRB.Xrm.RetrieveBatch(queries)); 196 | }); 197 | return $.when.apply($, xrmCalls); 198 | } 199 | 200 | /** 201 | * Xrm - Retrieve Metadata 202 | * Get $metadata content (XML) 203 | */ 204 | DRB.Xrm.RetrieveMetadata = function () { 205 | if (!DRB.Xrm.IsDemoMode()) { 206 | var token = DRB.Xrm.GetCurrentAccessToken(); 207 | return $.ajax({ 208 | type: "GET", 209 | datatype: "xml", 210 | async: true, 211 | beforeSend: function (xhr) { 212 | if (DRB.Utilities.HasValue(token)) { xhr.setRequestHeader("Authorization", "Bearer " + token); } 213 | }, 214 | url: DRB.Xrm.GetMetadataUrl() 215 | }); 216 | } 217 | 218 | if (DRB.Xrm.IsDemoMode()) { return $.when(DRB.Xrm.GetDemoMetadata()); } 219 | } 220 | 221 | /** 222 | * Xrm - Get Server Version 223 | * @param {string} serverUrl Server Url 224 | * @param {string} token Token 225 | */ 226 | DRB.Xrm.GetServerVersion = function (serverUrl, token) { 227 | return $.ajax({ 228 | type: "GET", 229 | contentType: "application/json; charset=utf-8", 230 | datatype: "json", 231 | async: true, 232 | beforeSend: function (xhr) { 233 | xhr.setRequestHeader("OData-MaxVersion", "4.0"); 234 | xhr.setRequestHeader("OData-Version", "4.0"); 235 | xhr.setRequestHeader("Accept", "application/json"); 236 | xhr.setRequestHeader("Authorization", "Bearer " + token); 237 | }, 238 | url: serverUrl + "/api/data/v9.0/RetrieveVersion()" 239 | }); 240 | } 241 | // #endregion -------------------------------------------------------------------------------- /js/drb.logic.predefinedquery.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.PredefinedQuery 2 | /** 3 | * Predefined Query - After Table Loaded 4 | * @param {DRB.Models.Table} table Table 5 | */ 6 | DRB.Logic.PredefinedQuery.AfterTableLoaded = function (table) { 7 | // Fill data.configuration (primaryEntity) 8 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = { logicalName: table.LogicalName, schemaName: table.SchemaName, label: table.Name, entitySetName: table.EntitySetName }; 9 | 10 | DRB.UI.FillDropdown(DRB.DOM.PersonalViewId.Dropdown.Id, DRB.DOM.PersonalViewId.Dropdown.Name, new DRB.Models.Records(table.PersonalViews).ToDropdown(), false, false, true); 11 | $("#" + DRB.DOM.QueryType.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.queryType).change(); 12 | $("#" + DRB.DOM.PersonalViewId.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.personalViewId); 13 | DRB.UI.RefreshDropdown(DRB.DOM.PersonalViewId.Dropdown.Id); 14 | DRB.Metadata.XMLEditor.session.setValue(DRB.Metadata.CurrentNode.data.configuration.fetchXML); 15 | } 16 | 17 | /** 18 | * Predefined Query - Bind Table 19 | * @param {string} id Id 20 | */ 21 | DRB.Logic.PredefinedQuery.BindTable = function (id) { 22 | $("#" + id).on("change", function (e) { 23 | var tableLogicalName = $(this).val(); 24 | DRB.Metadata.QueryObjectTypeCode = null; 25 | var table = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 26 | if (DRB.Utilities.HasValue(table)) { 27 | DRB.UI.UnlockDropdown(DRB.DOM.QueryType.Dropdown.Id); 28 | DRB.Metadata.QueryObjectTypeCode = table.ObjectTypeCode; 29 | if (table.PersonalViewsLoaded === false) { 30 | DRB.UI.ShowLoading("Retrieving Personal Views...
This is a long-running operation"); 31 | setTimeout(function () { 32 | DRB.Common.RetrievePersonalViews() 33 | .done(function (data) { 34 | var personalViews = DRB.Common.MapPersonalViews(data, "Name"); 35 | personalViews.forEach(function (personalView) { 36 | var viewTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, personalView.TableLogicalName); 37 | if (DRB.Utilities.HasValue(viewTable)) { viewTable.PersonalViews.push(personalView); } 38 | }); 39 | // set the personal views loaded as true for all the tables 40 | DRB.Metadata.Tables.forEach(function (setTable) { setTable.PersonalViewsLoaded = true; }); 41 | DRB.Logic.PredefinedQuery.AfterTableLoaded(table); 42 | DRB.UI.HideLoading(); 43 | }) 44 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Common.RetrievePersonalViews Error", DRB.Common.GetErrorMessage(xhr)); }); 45 | }, DRB.Settings.TimeoutDelay); 46 | } else { 47 | DRB.Logic.PredefinedQuery.AfterTableLoaded(table); 48 | } 49 | } 50 | }); 51 | } 52 | 53 | /** 54 | * Predefined Query - Bind Query Type 55 | * @param {string} id Id 56 | */ 57 | DRB.Logic.PredefinedQuery.BindQueryType = function (id) { 58 | $("#" + id).on("change", function (e) { 59 | var queryTypeValue = $(this).val(); 60 | DRB.Metadata.CurrentNode.data.configuration.queryType = queryTypeValue; 61 | // hide all sections 62 | $("#" + DRB.DOM.SystemViewId.Div.Id).hide(); 63 | $("#" + DRB.DOM.PersonalViewId.Div.Id).hide(); 64 | $("#" + DRB.DOM.FetchXML.Div.Id).hide(); 65 | 66 | // show correct section based on queryTypeValue 67 | switch (queryTypeValue) { 68 | case "savedquery": $("#" + DRB.DOM.SystemViewId.Div.Id).show(); break; 69 | case "userquery": $("#" + DRB.DOM.PersonalViewId.Div.Id).show(); break; 70 | case "fetchxml": $("#" + DRB.DOM.FetchXML.Div.Id).show(); break; 71 | } 72 | }); 73 | } 74 | 75 | /** 76 | * Predefined Query - Bind System View Id 77 | * @param {string} id Id 78 | */ 79 | DRB.Logic.PredefinedQuery.BindSystemViewId = function (id) { 80 | $("#" + id).on("change", function (e) { 81 | var systemViewIdValue = $(this).val(); 82 | DRB.Metadata.CurrentNode.data.configuration.systemViewId = systemViewIdValue; 83 | }); 84 | } 85 | 86 | /** 87 | * Predefined Query - Bind Personal View Id 88 | * @param {string} id Id 89 | */ 90 | DRB.Logic.PredefinedQuery.BindPersonalViewId = function (id) { 91 | $("#" + id).on("change", function (e) { 92 | var personalViewIdValue = $(this).val(); 93 | DRB.Metadata.CurrentNode.data.configuration.personalViewId = personalViewIdValue; 94 | }); 95 | } 96 | 97 | /** 98 | * Predefined Query - Bind Personal View 99 | * @param {string} id Id 100 | */ 101 | DRB.Logic.PredefinedQuery.BindPersonalView = function (id) { 102 | $("#" + id).on("change", function (e) { 103 | var personalViewValue = $(this).val(); 104 | $("#" + DRB.DOM.PersonalViewId.Input.Id).val(personalViewValue).trigger("input").change(); 105 | }); 106 | } 107 | 108 | /** 109 | * Predefined Query - Bind FetchXML 110 | * @param {string} id Id 111 | */ 112 | DRB.Logic.PredefinedQuery.BindFetchXML = function (id) { 113 | id.getSession().on("change", function (e) { 114 | var fetchXMLValue = DRB.Metadata.XMLEditor.session.getValue(); 115 | DRB.Metadata.CurrentNode.data.configuration.fetchXML = fetchXMLValue; 116 | }); 117 | } 118 | 119 | /** 120 | * Predefined Query - Start 121 | */ 122 | DRB.Logic.PredefinedQuery.Start = function () { 123 | // Metadata 124 | DRB.Metadata.QueryObjectTypeCode = null; 125 | DRB.Metadata.XMLEditor = null; 126 | 127 | // create DOM and bindings 128 | DRB.CustomUI.AddVersion(); 129 | DRB.CustomUI.AddProcess(); 130 | DRB.CustomUI.AddTokenHeader(); 131 | DRB.CustomUI.AddSpacer(); 132 | DRB.CustomUI.AddImpersonate(); 133 | DRB.CustomUI.AddSpacer(); 134 | DRB.CustomUI.AddFormattedValues(); 135 | DRB.CustomUI.AddRetrieveCount(); 136 | DRB.CustomUI.AddSpacer(); 137 | 138 | // #region Table 139 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Table.Span.Id, DRB.DOM.Table.Span.Name)); 140 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.Table.Dropdown.Id)); 141 | DRB.UI.FillDropdown(DRB.DOM.Table.Dropdown.Id, DRB.DOM.Table.Dropdown.Name, new DRB.Models.Records(DRB.Metadata.Tables).ToDropdown()); 142 | DRB.Logic.PredefinedQuery.BindTable(DRB.DOM.Table.Dropdown.Id); 143 | // #endregion 144 | 145 | // #region Query Type 146 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.QueryType.Span.Id, DRB.DOM.QueryType.Span.Name)); 147 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.QueryType.Dropdown.Id)); 148 | DRB.UI.FillDropdown(DRB.DOM.QueryType.Dropdown.Id, DRB.DOM.QueryType.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsViews).ToDropdown()); 149 | DRB.Logic.PredefinedQuery.BindQueryType(DRB.DOM.QueryType.Dropdown.Id); 150 | // #endregion 151 | 152 | DRB.CustomUI.AddSpacer(); 153 | 154 | // #region System View Id 155 | var divSystemViewId = DRB.UI.CreateEmptyDiv(DRB.DOM.SystemViewId.Div.Id); 156 | divSystemViewId.append(DRB.UI.CreateSpan(DRB.DOM.SystemViewId.Span.Id, DRB.DOM.SystemViewId.Span.Name)); 157 | divSystemViewId.append(DRB.UI.CreateInputGuid(DRB.DOM.SystemViewId.Input.Id)); 158 | divSystemViewId.append(DRB.UI.CreateLookup(DRB.DOM.SystemViewId.Lookup.Id, DRB.UI.OpenLookup, { openView: true, textId: DRB.DOM.SystemViewId.Input.Id })); 159 | $("#" + DRB.DOM.ConfigureContent.Id).append(divSystemViewId); 160 | DRB.Logic.PredefinedQuery.BindSystemViewId(DRB.DOM.SystemViewId.Input.Id); 161 | DRB.Common.BindGuid(DRB.DOM.SystemViewId.Input.Id); 162 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.systemViewId)) { 163 | $("#" + DRB.DOM.SystemViewId.Input.Id).val(DRB.Metadata.CurrentNode.data.configuration.systemViewId).trigger("input"); 164 | } 165 | divSystemViewId.hide(); 166 | // #endregion 167 | 168 | // #region Personal View 169 | var divPersonalViewId = DRB.UI.CreateEmptyDiv(DRB.DOM.PersonalViewId.Div.Id); 170 | divPersonalViewId.append(DRB.UI.CreateSpan(DRB.DOM.PersonalViewId.SpanDropdown.Id, DRB.DOM.PersonalViewId.SpanDropdown.Name)); 171 | divPersonalViewId.append(DRB.UI.CreateDropdown(DRB.DOM.PersonalViewId.Dropdown.Id)); 172 | divPersonalViewId.append(DRB.UI.CreateSpacer()); 173 | divPersonalViewId.append(DRB.UI.CreateSpan(DRB.DOM.PersonalViewId.Span.Id, DRB.DOM.PersonalViewId.Span.Name)); 174 | divPersonalViewId.append(DRB.UI.CreateInputGuid(DRB.DOM.PersonalViewId.Input.Id)); 175 | $("#" + DRB.DOM.ConfigureContent.Id).append(divPersonalViewId); 176 | DRB.Logic.PredefinedQuery.BindPersonalViewId(DRB.DOM.PersonalViewId.Input.Id); 177 | DRB.Logic.PredefinedQuery.BindPersonalView(DRB.DOM.PersonalViewId.Dropdown.Id); 178 | DRB.Common.BindGuid(DRB.DOM.PersonalViewId.Input.Id); 179 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.personalViewId)) { 180 | $("#" + DRB.DOM.PersonalViewId.Input.Id).val(DRB.Metadata.CurrentNode.data.configuration.personalViewId).trigger("input"); 181 | } 182 | divPersonalViewId.hide(); 183 | // #endregion 184 | 185 | // #region FetchXML 186 | var divFetchXML = DRB.UI.CreateEmptyDiv(DRB.DOM.FetchXML.Div.Id); 187 | divFetchXML.append(DRB.UI.CreateSpan(DRB.DOM.FetchXML.Span.Id, DRB.DOM.FetchXML.Span.Name)); 188 | divFetchXML.append(DRB.UI.CreateEmptyDiv(DRB.DOM.FetchXML.Editor.Id, DRB.DOM.FetchXML.Editor.Class)); 189 | $("#" + DRB.DOM.ConfigureContent.Id).append(divFetchXML); 190 | 191 | DRB.Metadata.XMLEditor = ace.edit(DRB.DOM.FetchXML.Editor.Id, { useWorker: false }); 192 | DRB.Metadata.XMLEditor.session.setMode("ace/mode/xml"); 193 | DRB.Metadata.XMLEditor.setShowPrintMargin(false); 194 | DRB.Logic.PredefinedQuery.BindFetchXML(DRB.Metadata.XMLEditor); 195 | divFetchXML.hide(); 196 | // #endregion 197 | 198 | DRB.CustomUI.AddSpacer(); 199 | 200 | // #region Triggers 201 | // events triggered after due to DOM connections to other elements 202 | 203 | // Table 204 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryEntity)) { 205 | // check if the table exists 206 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName); 207 | if (!DRB.Utilities.HasValue(checkTable)) { 208 | // if the table doesn't exist reset the relevant values 209 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 210 | DRB.UI.LockDropdown(DRB.DOM.QueryType.Dropdown.Id); 211 | } else { 212 | $("#" + DRB.DOM.Table.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName).change(); 213 | } 214 | } else { DRB.UI.LockDropdown(DRB.DOM.QueryType.Dropdown.Id); } 215 | // #endregion 216 | } 217 | // #endregion -------------------------------------------------------------------------------- /js/drb.logic.association.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.Association 2 | /** 3 | * Association - Remove Child Id 4 | * @param {string} index Index 5 | */ 6 | DRB.Logic.Association.RemoveChildId = function (index) { 7 | $("#" + DRB.DOM.ChildId.DivPrefix.Id + index).remove(); 8 | 9 | var newMetadataSecondaryIds = []; 10 | var indexToRemove = -1; 11 | DRB.Metadata.SecondaryIds.forEach(function (secondaryId, secondaryIndex) { 12 | if (secondaryId.Id == index) { indexToRemove = secondaryIndex; } else { newMetadataSecondaryIds.push(secondaryId); } 13 | }); 14 | DRB.Metadata.SecondaryIds = newMetadataSecondaryIds; 15 | 16 | if (indexToRemove > -1) { 17 | var newSecondaryIds = []; 18 | DRB.Metadata.CurrentNode.data.configuration.secondaryIds.forEach(function (secondaryId, secondaryIndex) { 19 | if (secondaryIndex != indexToRemove) { newSecondaryIds.push(secondaryId); } 20 | }); 21 | DRB.Metadata.CurrentNode.data.configuration.secondaryIds = newSecondaryIds; 22 | } 23 | } 24 | 25 | /** 26 | * Association - Add Child Id 27 | * @param {string} idValue Id Value 28 | */ 29 | DRB.Logic.Association.AddChildId = function (idValue) { 30 | if (!DRB.Utilities.HasValue(idValue)) { idValue = ""; } 31 | var index = 0; 32 | if (DRB.Metadata.SecondaryIds.length > 0) { index = DRB.Metadata.SecondaryIds[DRB.Metadata.SecondaryIds.length - 1].Id + 1; } 33 | // Take Logic from Create if necessary to rearrange 34 | 35 | var divChildId_ = DRB.UI.CreateEmptyDiv(DRB.DOM.ChildId.DivPrefix.Id + index); 36 | if (index == 0) { 37 | //divChildId_.append(DRB.UI.CreateEmptyRemoveButton()); 38 | } else { 39 | divChildId_.append(DRB.UI.CreateRemoveButton(DRB.Logic.Association.RemoveChildId, index)); 40 | } 41 | divChildId_.append(DRB.UI.CreateSpan(DRB.DOM.ChildId.SpanPrefix.Id + index, DRB.DOM.ChildId.SpanPrefix.Name)); 42 | divChildId_.append(DRB.UI.CreateInputGuid(DRB.DOM.ChildId.InputPrefix.Id + index)); 43 | divChildId_.append(DRB.UI.CreateLookup(DRB.DOM.ChildId.LookupPrefix.Id + index, DRB.UI.OpenLookup, { openSecondaryEntity: true, textId: DRB.DOM.ChildId.InputPrefix.Id + index })); 44 | divChildId_.append(DRB.UI.CreateSpacer()); 45 | $("#" + DRB.DOM.ChildId.Div.Id).append(divChildId_); 46 | DRB.Common.BindGuid(DRB.DOM.ChildId.InputPrefix.Id + index); 47 | DRB.Logic.Association.BindChildId(DRB.DOM.ChildId.InputPrefix.Id + index); 48 | DRB.Metadata.SecondaryIds.push(new DRB.Models.IdValue(index, idValue)); 49 | DRB.Metadata.CurrentNode.data.configuration.secondaryIds.push(idValue); 50 | } 51 | 52 | /** 53 | * Association - After Table Loaded 54 | * @param {DRB.Models.Table} table Table 55 | */ 56 | DRB.Logic.Association.AfterTableLoaded = function (table) { 57 | DRB.Logic.FillCurrentMetadata(table); // Fill Current Metadata 58 | DRB.Logic.FillRelationshipsColumns(); // Fill Relationships Columns 59 | 60 | var tableLogicalNames = []; 61 | table.OneToManyRelationships.forEach(function (relationship) { tableLogicalNames.push(relationship.TargetTable); }); 62 | table.ManyToManyRelationships.forEach(function (relationship) { tableLogicalNames.push(relationship.TargetTable); }); 63 | tableLogicalNames = DRB.Utilities.RemoveDuplicatesFromArray(tableLogicalNames); // remove duplicates 64 | 65 | var childTables = []; 66 | tableLogicalNames.forEach(function (tableLogicalName) { 67 | var childTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 68 | if (DRB.Utilities.HasValue(childTable)) { childTables.push(childTable); } 69 | }); 70 | childTables.sort(DRB.Utilities.CustomSort("Name")); 71 | DRB.UI.FillDropdown(DRB.DOM.ChildTable.Dropdown.Id, DRB.DOM.ChildTable.Dropdown.Name, new DRB.Models.Records(childTables).ToDropdown()); 72 | 73 | var childTable = ""; 74 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.secondaryEntity)) { 75 | childTable = DRB.Metadata.CurrentNode.data.configuration.secondaryEntity.logicalName; 76 | } 77 | $("#" + DRB.DOM.ChildTable.Dropdown.Id).val(childTable).change(); 78 | 79 | // Fill data.configuration (primaryEntity) 80 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = { logicalName: table.LogicalName, schemaName: table.SchemaName, label: table.Name, entitySetName: table.EntitySetName }; 81 | } 82 | 83 | /** 84 | * Association - Bind Parent Table 85 | * @param {string} id Id 86 | */ 87 | DRB.Logic.Association.BindParentTable = function (id) { 88 | $("#" + id).on("change", function (e) { 89 | var tableLogicalName = $(this).val(); 90 | var table = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 91 | if (DRB.Utilities.HasValue(table)) { 92 | if (table.RelationshipsLoaded === false) { 93 | DRB.UI.ShowLoading("Retrieving Table information...
This is a long-running operation"); 94 | setTimeout(function () { 95 | // retrieve the Entity Fields 96 | DRB.Common.RetrieveTablesDetails([tableLogicalName], true) 97 | .done(function () { 98 | DRB.Common.SetTables(arguments, DRB.Metadata.Tables, true); 99 | var tableLogicalNames = []; 100 | table.OneToManyRelationships.forEach(function (relationship) { tableLogicalNames.push(relationship.TargetTable); }); 101 | table.ManyToManyRelationships.forEach(function (relationship) { tableLogicalNames.push(relationship.TargetTable); }); 102 | tableLogicalNames = DRB.Utilities.RemoveDuplicatesFromArray(tableLogicalNames); // remove duplicates 103 | 104 | var tablesToRetrieve = []; 105 | tableLogicalNames.forEach(function (checkTableLogicalName) { 106 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, checkTableLogicalName); 107 | if (DRB.Utilities.HasValue(checkTable) && checkTable.ColumnsLoaded === false) { tablesToRetrieve.push(checkTableLogicalName); } 108 | }); 109 | if (tablesToRetrieve.length > 0) { 110 | DRB.Common.RetrieveTablesDetails(tablesToRetrieve) 111 | .done(function () { 112 | DRB.Common.SetTables(arguments, DRB.Metadata.Tables); 113 | DRB.Logic.Association.AfterTableLoaded(table); 114 | DRB.UI.HideLoading(); 115 | }) 116 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Common.RetrieveTablesDetails Error", DRB.Common.GetErrorMessage(xhr)); }); 117 | } else { 118 | DRB.Logic.Association.AfterTableLoaded(table); 119 | DRB.UI.HideLoading(); 120 | } 121 | }) 122 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Common.RetrieveTablesDetails Error", DRB.Common.GetErrorMessage(xhr)); }); 123 | }, DRB.Settings.TimeoutDelay); 124 | } else { 125 | DRB.Logic.Association.AfterTableLoaded(table); 126 | } 127 | } 128 | }); 129 | } 130 | 131 | /** 132 | * Association - Bind Child Table 133 | * @param {string} id Id 134 | */ 135 | DRB.Logic.Association.BindChildTable = function (id) { 136 | $("#" + id).on("change", function (e) { 137 | DRB.Metadata.CurrentNode.data.configuration.secondaryEntity = null; 138 | DRB.UI.ResetDropdown(DRB.DOM.ParentRelationship.Dropdown.Id, DRB.DOM.ParentRelationship.Dropdown.Name); 139 | var parentTableLogicalName = $("#" + DRB.DOM.ParentTable.Dropdown.Id).val(); 140 | var childTableLogicalName = $(this).val(); 141 | var parentTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, parentTableLogicalName); 142 | var childTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, childTableLogicalName); 143 | if (DRB.Utilities.HasValue(parentTable) && DRB.Utilities.HasValue(childTable)) { 144 | var relationships = []; 145 | parentTable.OneToManyRelationships.forEach(function (relationship) { 146 | if (relationship.TargetTable === childTableLogicalName) { 147 | relationships.push(new DRB.Models.SimpleRelationship(relationship.SchemaName, relationship.Type, relationship.SourceTable, relationship.TargetTable, relationship.NavigationAttribute, relationship.NavigationAttributeName)); 148 | } 149 | }); 150 | parentTable.ManyToManyRelationships.forEach(function (relationship) { 151 | if (relationship.TargetTable === childTableLogicalName) { 152 | relationships.push(new DRB.Models.SimpleRelationship(relationship.SchemaName, relationship.Type, relationship.SourceTable, relationship.TargetTable, relationship.NavigationAttribute, relationship.NavigationAttributeName)); 153 | } 154 | }); 155 | DRB.UI.FillDropdownWithGroups(DRB.DOM.ParentRelationship.Dropdown.Id, DRB.DOM.ParentRelationship.Dropdown.Name, new DRB.Models.Records(relationships).ToDropdown()); 156 | var relationship = ""; 157 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.relationship)) { 158 | relationship = DRB.Metadata.CurrentNode.data.configuration.relationship; 159 | } 160 | $("#" + DRB.DOM.ParentRelationship.Dropdown.Id).val(relationship).change(); 161 | 162 | DRB.Metadata.CurrentNode.data.configuration.secondaryEntity = { logicalName: childTable.LogicalName, schemaName: childTable.SchemaName, label: childTable.Name, entitySetName: childTable.EntitySetName }; 163 | } 164 | }); 165 | } 166 | 167 | /** 168 | * Association - Bind Child Id 169 | * @param {string} id Id 170 | */ 171 | DRB.Logic.Association.BindChildId = function (id) { 172 | $("#" + id).on("change", function (e) { 173 | // get control value 174 | var controlValue = $(this).val(); 175 | // extract the index from the control name 176 | var controlName = $(this).attr('id'); 177 | var elementIndex = DRB.Common.ExtractIndexFromControlName(controlName); 178 | if (elementIndex === -1) { return; } // if index not found do nothing 179 | 180 | DRB.Metadata.SecondaryIds.forEach(function (secondaryId, secondaryIndex) { 181 | if (secondaryId.Id === elementIndex) { 182 | secondaryId.Value = controlValue; 183 | DRB.Metadata.CurrentNode.data.configuration.secondaryIds[secondaryIndex] = controlValue; 184 | } 185 | }); 186 | }); 187 | } 188 | 189 | /** 190 | * Association - Bind Parent Relationship 191 | * @param {string} id Id 192 | */ 193 | DRB.Logic.Association.BindParentRelationship = function (id) { 194 | $("#" + id).on("change", function (e) { 195 | var relationshipValue = $(this).val(); 196 | DRB.Metadata.CurrentNode.data.configuration.relationship = relationshipValue; 197 | }); 198 | } 199 | 200 | /** 201 | * Association - Start 202 | */ 203 | DRB.Logic.Association.Start = function () { 204 | // Metadata 205 | DRB.Metadata.SecondaryIds = []; 206 | 207 | // create DOM and bindings 208 | DRB.CustomUI.AddVersion(); 209 | DRB.CustomUI.AddProcess(); 210 | DRB.CustomUI.AddTokenHeader(); 211 | DRB.CustomUI.AddSpacer(); 212 | DRB.CustomUI.AddImpersonate(); 213 | DRB.CustomUI.AddSpacer(); 214 | 215 | // #region Parent Table 216 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.ParentTable.Span.Id, DRB.DOM.ParentTable.Span.Name)); 217 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.ParentTable.Dropdown.Id)); 218 | DRB.UI.FillDropdown(DRB.DOM.ParentTable.Dropdown.Id, DRB.DOM.ParentTable.Dropdown.Name, new DRB.Models.Records(DRB.Metadata.Tables).ToDropdown()); 219 | DRB.Logic.Association.BindParentTable(DRB.DOM.ParentTable.Dropdown.Id); 220 | // #endregion 221 | 222 | DRB.CustomUI.AddSpacer(); 223 | DRB.CustomUI.AddPrimaryId(); 224 | DRB.CustomUI.AddSpacer(); 225 | 226 | // #region Child Table 227 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.ChildTable.Span.Id, DRB.DOM.ChildTable.Span.Name)); 228 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.ChildTable.Dropdown.Id)); 229 | DRB.UI.ResetDropdown(DRB.DOM.ChildTable.Dropdown.Id, DRB.DOM.ChildTable.Dropdown.Name); 230 | DRB.Logic.Association.BindChildTable(DRB.DOM.ChildTable.Dropdown.Id); 231 | // #endregion 232 | 233 | // #region Parent Relationship 234 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.ParentRelationship.Span.Id, DRB.DOM.ParentRelationship.Span.Name)); 235 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.ParentRelationship.Dropdown.Id)); 236 | DRB.UI.ResetDropdown(DRB.DOM.ParentRelationship.Dropdown.Id, DRB.DOM.ParentRelationship.Dropdown.Name); 237 | DRB.Logic.Association.BindParentRelationship(DRB.DOM.ParentRelationship.Dropdown.Id); 238 | // #endregion 239 | 240 | DRB.CustomUI.AddSpacer(); 241 | 242 | // #region Secondary Ids 243 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateEmptyDiv(DRB.DOM.ChildId.Div.Id)); 244 | // #endregion 245 | 246 | DRB.CustomUI.AddSpacer(); 247 | 248 | // $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateButton(DRB.DOM.ChildId.AddButton.Id, DRB.DOM.ChildId.AddButton.Name, DRB.DOM.ChildId.AddButton.Class, DRB.Logic.Association.AddChildId)); 249 | 250 | // #region Triggers 251 | // events triggered after due to DOM connections to other elements 252 | 253 | // Table 254 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryEntity)) { 255 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName); 256 | if (!DRB.Utilities.HasValue(checkTable)) { 257 | // if the table doesn't exist reset the relevant values 258 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 259 | DRB.Metadata.CurrentNode.data.configuration.primaryId = ""; 260 | DRB.Metadata.CurrentNode.data.configuration.secondaryEntity = null; 261 | DRB.Metadata.CurrentNode.data.configuration.secondaryIds = [""]; 262 | } else { 263 | $("#" + DRB.DOM.ParentTable.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName).change(); 264 | } 265 | } 266 | 267 | // Secondary Ids 268 | if (Array.isArray(DRB.Metadata.CurrentNode.data.configuration.secondaryIds)) { 269 | var secondaryIds = JSON.parse(JSON.stringify(DRB.Metadata.CurrentNode.data.configuration.secondaryIds)); 270 | DRB.Metadata.CurrentNode.data.configuration.secondaryIds = []; 271 | secondaryIds.forEach(function (secondaryId, secondaryIndex) { 272 | DRB.Logic.Association.AddChildId(secondaryId); 273 | $("#" + DRB.DOM.ChildId.InputPrefix.Id + secondaryIndex).val(secondaryId).trigger("input"); 274 | }); 275 | } 276 | // #endregion 277 | } 278 | // #endregion -------------------------------------------------------------------------------- /js/drb.common.xrm.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Common.Xrm 2 | /** 3 | * Common - Retrieve Tables 4 | */ 5 | DRB.Common.RetrieveTables = function () { 6 | return DRB.Xrm.Retrieve("EntityDefinitions", "$select=LogicalName,SchemaName,DisplayName,EntitySetName,PrimaryIdAttribute,PrimaryNameAttribute,ObjectTypeCode,IsActivity,ExternalName,ExternalCollectionName"); 7 | } 8 | 9 | /** 10 | * Common - Retrieve Users 11 | */ 12 | DRB.Common.RetrieveUsers = function () { 13 | return DRB.Xrm.Retrieve("systemusers", "$select=systemuserid,fullname,azureactivedirectoryobjectid&$filter=azureactivedirectoryobjectid ne null"); 14 | } 15 | 16 | /** 17 | * Common - Retrieve System Views 18 | * @param {string[]} tableLogicalNames Table Logical Names 19 | */ 20 | DRB.Common.RetrieveSystemViews = function (tableLogicalNames) { 21 | var queries = []; 22 | tableLogicalNames.forEach(function (tableLogicalName) { 23 | var query = {}; 24 | query.EntitySetName = "savedqueries"; 25 | query.Filters = "$select=savedqueryid,name,returnedtypecode,isdefault,layoutxml&$filter=returnedtypecode eq '" + tableLogicalName + "'"; 26 | queries.push(query); 27 | }); 28 | return DRB.Xrm.RetrieveBatch(queries); 29 | } 30 | 31 | /** 32 | * Common - Retrieve Personal Views 33 | */ 34 | DRB.Common.RetrievePersonalViews = function () { 35 | return DRB.Xrm.Retrieve("userqueries", "$select=name,returnedtypecode,userqueryid"); 36 | } 37 | 38 | /** 39 | * Common - Retrieve Custom APIs 40 | */ 41 | DRB.Common.RetrieveCustomAPIs = function () { 42 | var queries = []; 43 | // Custom APIs 44 | var queryCustomAPIs = {}; 45 | queryCustomAPIs.EntitySetName = "customapis"; 46 | queryCustomAPIs.Filters = "$select=bindingtype,boundentitylogicalname,name,uniquename,isfunction&$filter=statuscode eq 1"; 47 | queries.push(queryCustomAPIs); 48 | 49 | // Custom API Request Parameters 50 | var queryRequestParameters = {}; 51 | queryRequestParameters.EntitySetName = "customapirequestparameters"; 52 | queryRequestParameters.Filters = "$select=isoptional,name,type,uniquename,logicalentityname&$expand=CustomAPIId($select=uniquename)&$filter=statuscode eq 1"; 53 | queries.push(queryRequestParameters); 54 | 55 | // Custom API Response Properties 56 | var queryResponseProperties = {}; 57 | queryResponseProperties.EntitySetName = "customapiresponseproperties"; 58 | queryResponseProperties.Filters = "$select=name,type,uniquename,logicalentityname&$expand=CustomAPIId($select=uniquename)&$filter=statuscode eq 1"; 59 | queries.push(queryResponseProperties); 60 | 61 | return DRB.Xrm.RetrieveBatch(queries); 62 | } 63 | 64 | /** 65 | * Common - Retrieve Custom Actions 66 | */ 67 | DRB.Common.RetrieveCustomActions = function () { 68 | var queries = []; 69 | // Custom APIs 70 | var queryCustomActions = {}; 71 | queryCustomActions.EntitySetName = "workflows"; 72 | var fetchCustomActions = ` 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | `; 87 | //queryCustomActions.Filters = "$select=name,uniquename,primaryentity&$filter=category eq 3 and type eq 1 and componentstate eq 0 and statuscode eq 2"; 88 | queryCustomActions.Filters = "fetchXml=" + encodeURIComponent(fetchCustomActions); 89 | queries.push(queryCustomActions); 90 | 91 | // Custom Actions Request Parameters 92 | var queryRequestParameters = {}; 93 | queryRequestParameters.EntitySetName = "sdkmessagerequestfields"; 94 | 95 | var fetchRequestParameters = ` 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | `; 113 | 114 | queryRequestParameters.Filters = "fetchXml=" + encodeURIComponent(fetchRequestParameters); 115 | queries.push(queryRequestParameters); 116 | 117 | // Custom Actions Response Properties 118 | var queryResponseProperties = {}; 119 | queryResponseProperties.EntitySetName = "sdkmessageresponsefields"; 120 | 121 | var fetchResponseProperties = ` 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | `; 140 | 141 | queryResponseProperties.Filters = "fetchXml=" + encodeURIComponent(fetchResponseProperties); 142 | queries.push(queryResponseProperties); 143 | 144 | return DRB.Xrm.RetrieveBatch(queries); 145 | } 146 | 147 | /** 148 | * Common - Retrieve Metadata 149 | */ 150 | DRB.Common.RetrieveMetadata = function () { 151 | return DRB.Xrm.RetrieveMetadata(); 152 | } 153 | 154 | /** 155 | * Common - Retrieve Tables Details 156 | * @param {string[]} tableLogicalNames Table Logical Names 157 | * @param {boolean} includeRelationships Include Relationships 158 | * @param {boolean} includeAlternateKeys Include Alternate Keys 159 | */ 160 | DRB.Common.RetrieveTablesDetails = function (tableLogicalNames, includeRelationships, includeAlternateKeys) { 161 | var includeOptionValues = false; 162 | if (includeAlternateKeys === true) { includeOptionValues = true; } // Alternate Key supports Picklist, retrieving Option Values is required 163 | 164 | var batchedQueries = []; 165 | var tableBatchSize = 150; // 150 tables each batch request, because there are a max of 6 requests for each table (150 x 6 = 900 < 1000) 166 | 167 | batchedTableLogicalNames = []; 168 | for (var count = 0; count < tableLogicalNames.length; count++) { 169 | if (count % tableBatchSize === 0) { batchedTableLogicalNames.push([]); } 170 | batchedTableLogicalNames[batchedTableLogicalNames.length - 1].push(tableLogicalNames[count]); 171 | } 172 | 173 | batchedTableLogicalNames.forEach(function (batchedTableLogicalName) { 174 | batchedQueries.push([]); 175 | batchedTableLogicalName.forEach(function (tableLogicalName) { 176 | var queryTable = {}; 177 | queryTable.EntitySetName = "EntityDefinitions(LogicalName='" + tableLogicalName + "')"; 178 | queryTable.Filters = "$select=LogicalName&$expand=Attributes"; // retrieve all Attributes due to "Additional Properties" mapping 179 | if (includeRelationships === true) { 180 | queryTable.Filters += 181 | ",OneToManyRelationships($select=SchemaName,ReferencingEntity,ReferencedEntity,ReferencingAttribute,ReferencedAttribute,ReferencingEntityNavigationPropertyName,ReferencedEntityNavigationPropertyName,IsHierarchical)" + 182 | ",ManyToOneRelationships($select=SchemaName,ReferencingEntity,ReferencedEntity,ReferencingAttribute,ReferencedAttribute,ReferencingEntityNavigationPropertyName,ReferencedEntityNavigationPropertyName)" + 183 | ",ManyToManyRelationships($select=Entity1LogicalName,Entity2LogicalName,Entity1NavigationPropertyName,Entity2NavigationPropertyName,SchemaName,IntersectEntityName,Entity1IntersectAttribute,Entity2IntersectAttribute)"; 184 | } 185 | 186 | if (includeAlternateKeys === true) { 187 | queryTable.Filters += ",Keys($select=LogicalName,SchemaName,KeyAttributes,EntityKeyIndexStatus,DisplayName)"; 188 | } 189 | batchedQueries[batchedQueries.length - 1].push(queryTable); 190 | 191 | if (includeOptionValues === true) { 192 | var metadataAttributes = ["PicklistAttributeMetadata", "MultiSelectPicklistAttributeMetadata", "BooleanAttributeMetadata", "StateAttributeMetadata", "StatusAttributeMetadata"]; 193 | metadataAttributes.forEach(function (metadataAttribute) { 194 | var retrieveMetadataAttribute = {}; 195 | retrieveMetadataAttribute.EntitySetName = "EntityDefinitions(LogicalName='" + tableLogicalName + "')/Attributes/Microsoft.Dynamics.CRM." + metadataAttribute; 196 | retrieveMetadataAttribute.Filters = "$select=EntityLogicalName,LogicalName,AttributeType&$expand=OptionSet"; 197 | batchedQueries[batchedQueries.length - 1].push(retrieveMetadataAttribute); 198 | }); 199 | } 200 | }); 201 | }); 202 | 203 | return DRB.Xrm.RetrieveBatches(batchedQueries); 204 | } 205 | 206 | /** 207 | * Common - Set Custom API Tables 208 | * @param {any} data Data to process 209 | */ 210 | DRB.Common.SetCustomAPITables = function (data) { 211 | var dataResponses = []; 212 | // clear the response 213 | var firstRowData = data.split('\r\n', 1)[0]; 214 | var splittedData = data.split(firstRowData); 215 | splittedData.forEach(function (segment) { if (segment.indexOf("{") > -1) { dataResponses.push(segment); } }); 216 | // end clear the response 217 | var contexts = []; 218 | dataResponses.forEach(function (dataResponse) { 219 | var contextRegion = dataResponse.substring(dataResponse.indexOf('{'), dataResponse.lastIndexOf('}') + 1); 220 | contexts.push(JSON.parse(contextRegion)); 221 | }); 222 | 223 | if (contexts.length !== 3) { return []; } 224 | 225 | var customAPIs = DRB.Common.MapCustomAPIs(contexts[0]); 226 | DRB.Common.MapCustomAPIRequestParameters(contexts[1], customAPIs); 227 | DRB.Common.MapCustomAPIResponseProperties(contexts[2], customAPIs); 228 | return customAPIs; 229 | } 230 | 231 | /** 232 | * Common - Set Custom Action Tables 233 | * @param {any} data Data to process 234 | */ 235 | DRB.Common.SetCustomActionTables = function (data) { 236 | var dataResponses = []; 237 | // clear the response 238 | var firstRowData = data.split('\r\n', 1)[0]; 239 | var splittedData = data.split(firstRowData); 240 | splittedData.forEach(function (segment) { if (segment.indexOf("{") > -1) { dataResponses.push(segment); } }); 241 | // end clear the response 242 | var contexts = []; 243 | dataResponses.forEach(function (dataResponse) { 244 | var contextRegion = dataResponse.substring(dataResponse.indexOf('{'), dataResponse.lastIndexOf('}') + 1); 245 | contexts.push(JSON.parse(contextRegion)); 246 | }); 247 | 248 | if (contexts.length !== 3) { return []; } 249 | 250 | var customActions = DRB.Common.MapCustomActions(contexts[0], "Name"); 251 | DRB.Common.MapCustomActionRequestParameters(contexts[1], customActions); 252 | DRB.Common.MapCustomActionResponseProperties(contexts[2], customActions); 253 | return customActions; 254 | } 255 | 256 | /** 257 | * Common - Set System Views 258 | * @param {any} data Data to process 259 | */ 260 | DRB.Common.SetSystemViews = function (data, tables) { 261 | var dataResponses = []; 262 | // clear the response 263 | var firstRowData = data.split('\r\n', 1)[0]; 264 | var splittedData = data.split(firstRowData); 265 | splittedData.forEach(function (segment) { if (segment.indexOf("{") > -1) { dataResponses.push(segment); } }); 266 | // end clear the response 267 | var contexts = []; 268 | dataResponses.forEach(function (dataResponse) { 269 | var contextRegion = dataResponse.substring(dataResponse.indexOf('{'), dataResponse.lastIndexOf('}') + 1); 270 | contexts.push(JSON.parse(contextRegion)); 271 | }); 272 | 273 | contexts.forEach(function (context) { 274 | var systemViews = DRB.Common.MapSystemViews(context, "Name"); 275 | if (systemViews.length > 0) { 276 | var tableLogicalName = systemViews[0].TableLogicalName; 277 | var currentTable = DRB.Utilities.GetRecordById(tables, tableLogicalName); 278 | if (DRB.Utilities.HasValue(currentTable)) { 279 | currentTable.SystemViews = systemViews; 280 | currentTable.SystemViewsLoaded = true; 281 | } 282 | } 283 | }); 284 | } 285 | 286 | /** 287 | * Common - Set Tables 288 | * @param {any} args Data to process 289 | * @param {DRB.Models.Table[]} tables Tables 290 | * @param {boolean} mapRelationships Map Relationships 291 | * @param {boolean} mapAlternateKeys Map Alternate Keys 292 | */ 293 | DRB.Common.SetTables = function (args, tables, mapRelationships, mapAlternateKeys) { 294 | var mapOptionValues = false; 295 | if (mapAlternateKeys === true) { mapOptionValues = true; } // if map Alternate Keys map also Option Values (Alternate Key supports Picklist) 296 | 297 | var datas = []; 298 | if (Array.isArray(args[0])) { 299 | // multiple batches 300 | for (var count = 0; count < args.length; count++) { datas.push(args[count][0]); } 301 | } else { 302 | // single batch 303 | datas.push(args[0]); 304 | } 305 | 306 | datas.forEach(function (data) { 307 | var dataResponses = []; 308 | // clear the response 309 | var firstRowData = data.split('\r\n', 1)[0]; 310 | var splittedData = data.split(firstRowData); 311 | splittedData.forEach(function (segment) { if (segment.indexOf("{") > -1) { dataResponses.push(segment); } }); 312 | // end clear the response 313 | var contexts = []; 314 | dataResponses.forEach(function (dataResponse) { 315 | var contextRegion = dataResponse.substring(dataResponse.indexOf('{'), dataResponse.lastIndexOf('}') + 1); 316 | contexts.push(JSON.parse(contextRegion)); 317 | }); 318 | var contextsToCheckOptionValues = []; 319 | contexts.forEach(function (context) { 320 | var tableLogicalName = context.LogicalName; 321 | // if LogicalName is present assume it's a query of columns, relationships, keys 322 | if (DRB.Utilities.HasValue(tableLogicalName)) { 323 | var currentTable = DRB.Utilities.GetRecordById(tables, tableLogicalName); 324 | if (DRB.Utilities.HasValue(currentTable)) { 325 | currentTable.Columns = DRB.Common.MapColumns(context.Attributes, currentTable.PrimaryIdAttribute, currentTable.PrimaryNameAttribute, "Name"); 326 | currentTable.ColumnsLoaded = true; 327 | if (mapRelationships === true) { 328 | currentTable.OneToManyRelationships = DRB.Common.MapRelationships(context.OneToManyRelationships, "OneToMany", "Name", tableLogicalName); 329 | currentTable.ManyToOneRelationships = DRB.Common.MapRelationships(context.ManyToOneRelationships, "ManyToOne", "Name", tableLogicalName); 330 | currentTable.ManyToManyRelationships = DRB.Common.MapRelationships(context.ManyToManyRelationships, "ManyToMany", "Name", tableLogicalName); 331 | currentTable.RelationshipsLoaded = true; 332 | 333 | // check Hierarchy 334 | for (var countRel = 0; countRel < currentTable.OneToManyRelationships.length; countRel++) { 335 | if (currentTable.OneToManyRelationships[countRel].IsHierarchical === true) { 336 | currentTable.HasHierarchy = true; 337 | break; 338 | } 339 | } 340 | } 341 | 342 | if (mapAlternateKeys === true) { 343 | currentTable.AlternateKeys = DRB.Common.MapAlternateKeys(context.Keys, "Name"); 344 | currentTable.AlternateKeysLoaded = true; 345 | } 346 | } 347 | } else { contextsToCheckOptionValues.push(context); } 348 | }); 349 | 350 | if (mapOptionValues === true) { 351 | contextsToCheckOptionValues.forEach(function (context) { 352 | if (DRB.Utilities.HasValue(context.value)) { DRB.Common.MapOptionValues(context.value); } 353 | }); 354 | } 355 | }); 356 | } 357 | // #endregion -------------------------------------------------------------------------------- /js/drb.customui.js: -------------------------------------------------------------------------------- 1 | // #region DRB.CustomUI 2 | /** 3 | * Add Spacer 4 | */ 5 | DRB.CustomUI.AddSpacer = function () { 6 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpacer()); 7 | } 8 | 9 | /** 10 | * Add Version 11 | */ 12 | DRB.CustomUI.AddVersion = function () { 13 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Version.Span.Id, DRB.DOM.Version.Span.Name)); 14 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.Version.Dropdown.Id)); 15 | DRB.UI.FillDropdown(DRB.DOM.Version.Dropdown.Id, DRB.DOM.Version.Dropdown.Name, new DRB.Models.Records(DRB.Settings.Versions).ToDropdown()); 16 | DRB.Logic.BindPropertyValue(DRB.DOM.Version.Dropdown.Id, "version"); 17 | var selectedVersion = DRB.Settings.Versions[DRB.Settings.Versions.length - 1].Id; 18 | var versionExists = DRB.Utilities.GetRecordById(DRB.Settings.Versions, DRB.Metadata.CurrentNode.data.configuration.version); 19 | if (DRB.Utilities.HasValue(versionExists)) { selectedVersion = versionExists.Id; } 20 | $("#" + DRB.DOM.Version.Dropdown.Id).val(selectedVersion).change(); 21 | } 22 | 23 | /** 24 | * Add Process 25 | */ 26 | DRB.CustomUI.AddProcess = function () { 27 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Process.Span.Id, DRB.DOM.Process.Span.Name)); 28 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.Process.Dropdown.Id)); 29 | DRB.UI.FillDropdown(DRB.DOM.Process.Dropdown.Id, DRB.DOM.Process.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsAyncSync).ToDropdown()); 30 | DRB.Logic.BindPropertyBooleanValue(DRB.DOM.Process.Dropdown.Id, "async"); 31 | var processValue = "yes"; 32 | if (DRB.Metadata.CurrentNode.data.configuration.async === false) { processValue = "no"; } 33 | $("#" + DRB.DOM.Process.Dropdown.Id).val(processValue).change(); 34 | } 35 | 36 | /** 37 | * Add Token Header 38 | */ 39 | DRB.CustomUI.AddTokenHeader = function () { 40 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.TokenHeader.Span.Id, DRB.DOM.TokenHeader.Span.Name)); 41 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.TokenHeader.Dropdown.Id)); 42 | DRB.UI.FillDropdown(DRB.DOM.TokenHeader.Dropdown.Id, DRB.DOM.TokenHeader.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 43 | DRB.Logic.BindPropertyBooleanValue(DRB.DOM.TokenHeader.Dropdown.Id, "tokenHeader"); 44 | var tokenHeaderValue = "no"; 45 | if (DRB.Metadata.CurrentNode.data.configuration.tokenHeader === true) { tokenHeaderValue = "yes"; } 46 | $("#" + DRB.DOM.TokenHeader.Dropdown.Id).val(tokenHeaderValue).change(); 47 | } 48 | 49 | /** 50 | * Add Impersonate Dropdown 51 | */ 52 | DRB.CustomUI.AddImpersonate = function () { 53 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Impersonate.Span.Id, DRB.DOM.Impersonate.Span.Name)); 54 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.Impersonate.Dropdown.Id)); 55 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateEmptyDiv(DRB.DOM.ImpersonateId.Div.Id, DRB.DOM.ImpersonateId.Div.Class)); 56 | $("#" + DRB.DOM.ImpersonateId.Div.Id).append(DRB.UI.CreateSpan(DRB.DOM.ImpersonateId.TypeSpan.Id, DRB.DOM.ImpersonateId.TypeSpan.Name)); 57 | $("#" + DRB.DOM.ImpersonateId.Div.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.ImpersonateId.Dropdown.Id)); 58 | $("#" + DRB.DOM.ImpersonateId.Div.Id).append(DRB.UI.CreateSpan(DRB.DOM.ImpersonateId.Span.Id, DRB.DOM.ImpersonateId.Span.Name)); 59 | $("#" + DRB.DOM.ImpersonateId.Div.Id).append(DRB.UI.CreateInputGuid(DRB.DOM.ImpersonateId.Input.Id)); 60 | $("#" + DRB.DOM.ImpersonateId.Div.Id).append(DRB.UI.CreateLookup(DRB.DOM.ImpersonateId.Lookup.Id, DRB.UI.OpenLookup, { openUser: true, textId: DRB.DOM.ImpersonateId.Input.Id })); 61 | $("#" + DRB.DOM.ImpersonateId.Div.Id).hide(); 62 | 63 | DRB.UI.FillDropdown(DRB.DOM.Impersonate.Dropdown.Id, DRB.DOM.Impersonate.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 64 | DRB.Logic.BindImpersonate(DRB.DOM.Impersonate.Dropdown.Id); 65 | DRB.UI.FillDropdown(DRB.DOM.ImpersonateId.Dropdown.Id, DRB.DOM.ImpersonateId.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsImpersonation).ToDropdown()); 66 | DRB.Logic.BindImpersonateType(DRB.DOM.ImpersonateId.Dropdown.Id); 67 | DRB.Logic.BindImpersonateId(DRB.DOM.ImpersonateId.Input.Id); 68 | DRB.Common.BindGuid(DRB.DOM.ImpersonateId.Input.Id); 69 | var impersonateValue = "no"; 70 | if (DRB.Metadata.CurrentNode.data.configuration.impersonate === true) { impersonateValue = "yes"; } 71 | $("#" + DRB.DOM.Impersonate.Dropdown.Id).val(impersonateValue).change(); 72 | 73 | var impersonateType = "mscrmcallerid"; 74 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.impersonateType)) { impersonateType = DRB.Metadata.CurrentNode.data.configuration.impersonateType; } 75 | $("#" + DRB.DOM.ImpersonateId.Dropdown.Id).val(impersonateType).change(); 76 | 77 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.impersonateId)) { 78 | $("#" + DRB.DOM.ImpersonateId.Input.Id).val(DRB.Metadata.CurrentNode.data.configuration.impersonateId).trigger("input"); 79 | } 80 | } 81 | 82 | /** 83 | * Add Formatted Values 84 | */ 85 | DRB.CustomUI.AddFormattedValues = function () { 86 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.FormattedValues.Span.Id, DRB.DOM.FormattedValues.Span.Name)); 87 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.FormattedValues.Dropdown.Id)); 88 | DRB.UI.FillDropdown(DRB.DOM.FormattedValues.Dropdown.Id, DRB.DOM.FormattedValues.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 89 | DRB.Logic.BindPropertyBooleanValue(DRB.DOM.FormattedValues.Dropdown.Id, "formattedValues"); 90 | var formattedValuesValue = "yes"; 91 | if (DRB.Metadata.CurrentNode.data.configuration.formattedValues === false) { formattedValuesValue = "no"; } 92 | $("#" + DRB.DOM.FormattedValues.Dropdown.Id).val(formattedValuesValue).change(); 93 | } 94 | 95 | /** 96 | * Add Detect Changes 97 | */ 98 | DRB.CustomUI.AddDetectChanges = function () { 99 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.DetectChanges.Span.Id, DRB.DOM.DetectChanges.Span.Name)); 100 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.DetectChanges.Dropdown.Id)); 101 | DRB.UI.FillDropdown(DRB.DOM.DetectChanges.Dropdown.Id, DRB.DOM.DetectChanges.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 102 | DRB.Logic.BindPropertyBooleanValue(DRB.DOM.DetectChanges.Dropdown.Id, "detectChanges"); 103 | var detectChangesValue = "no"; 104 | if (DRB.Metadata.CurrentNode.data.configuration.detectChanges === true) { detectChangesValue = "yes"; } 105 | $("#" + DRB.DOM.DetectChanges.Dropdown.Id).val(detectChangesValue).change(); 106 | } 107 | 108 | /** 109 | * Add Detect Duplicates 110 | */ 111 | DRB.CustomUI.AddDetectDuplicates = function () { 112 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.DetectDuplicates.Span.Id, DRB.DOM.DetectDuplicates.Span.Name)); 113 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.DetectDuplicates.Dropdown.Id)); 114 | DRB.UI.FillDropdown(DRB.DOM.DetectDuplicates.Dropdown.Id, DRB.DOM.DetectDuplicates.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 115 | DRB.Logic.BindPropertyBooleanValue(DRB.DOM.DetectDuplicates.Dropdown.Id, "detectDuplicates"); 116 | var detectDuplicatesValue = "no"; 117 | if (DRB.Metadata.CurrentNode.data.configuration.detectDuplicates === true) { detectDuplicatesValue = "yes"; } 118 | $("#" + DRB.DOM.DetectDuplicates.Dropdown.Id).val(detectDuplicatesValue).change(); 119 | } 120 | 121 | /** 122 | * Add Retrieve Count 123 | */ 124 | DRB.CustomUI.AddRetrieveCount = function () { 125 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.RetrieveCount.Span.Id, DRB.DOM.RetrieveCount.Span.Name)); 126 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.RetrieveCount.Dropdown.Id)); 127 | DRB.UI.FillDropdown(DRB.DOM.RetrieveCount.Dropdown.Id, DRB.DOM.RetrieveCount.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 128 | DRB.Logic.BindPropertyBooleanValue(DRB.DOM.RetrieveCount.Dropdown.Id, "retrieveCount"); 129 | var retrieveCountValue = "no"; 130 | if (DRB.Metadata.CurrentNode.data.configuration.retrieveCount === true) { retrieveCountValue = "yes"; } 131 | $("#" + DRB.DOM.RetrieveCount.Dropdown.Id).val(retrieveCountValue).change(); 132 | } 133 | 134 | /** 135 | * Add Prevent 136 | */ 137 | DRB.CustomUI.AddPrevent = function () { 138 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Prevent.Span.Id, DRB.DOM.Prevent.Span.Name)); 139 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.Prevent.Dropdown.Id)); 140 | DRB.UI.FillDropdown(DRB.DOM.Prevent.Dropdown.Id, DRB.DOM.Prevent.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsPrevent).ToDropdown()); 141 | DRB.Logic.BindPropertyValue(DRB.DOM.Prevent.Dropdown.Id, "prevent"); 142 | var preventValue = "none"; 143 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.prevent)) { preventValue = DRB.Metadata.CurrentNode.data.configuration.prevent; } 144 | $("#" + DRB.DOM.Prevent.Dropdown.Id).val(preventValue).change(); 145 | } 146 | 147 | /** 148 | * Add Top Count 149 | */ 150 | DRB.CustomUI.AddTopCount = function () { 151 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.TopCount.Span.Id, DRB.DOM.TopCount.Span.Name)); 152 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateInputTopCount(DRB.DOM.TopCount.Input.Id)); 153 | DRB.Logic.BindPropertyValue(DRB.DOM.TopCount.Input.Id, "topCount"); 154 | DRB.Common.BindTopCountNumber(DRB.DOM.TopCount.Input.Id); 155 | var topCountValue = ""; 156 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.topCount)) { topCountValue = DRB.Metadata.CurrentNode.data.configuration.topCount; } 157 | $("#" + DRB.DOM.TopCount.Input.Id).val(topCountValue).change(); 158 | } 159 | 160 | /** 161 | * Add Use Alternate Key 162 | */ 163 | DRB.CustomUI.AddUseAlternateKey = function () { 164 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.UseAlternateKey.Span.Id, DRB.DOM.UseAlternateKey.Span.Name)); 165 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSimpleDropdown(DRB.DOM.UseAlternateKey.Dropdown.Id)); 166 | DRB.UI.FillDropdown(DRB.DOM.UseAlternateKey.Dropdown.Id, DRB.DOM.UseAlternateKey.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsYesNo).ToDropdown()); 167 | DRB.Logic.BindUseAlternateKey(DRB.DOM.UseAlternateKey.Dropdown.Id); 168 | DRB.CustomUI.AddSpacer(); 169 | DRB.CustomUI.AddPrimaryId(true); 170 | 171 | var divAlternateKey = DRB.UI.CreateEmptyDiv(DRB.DOM.AlternateKey.Div.Id); 172 | divAlternateKey.append(DRB.UI.CreateSpan(DRB.DOM.AlternateKey.Span.Id, DRB.DOM.AlternateKey.Span.Name)); 173 | divAlternateKey.append(DRB.UI.CreateDropdown(DRB.DOM.AlternateKey.Dropdown.Id)); 174 | divAlternateKey.append(DRB.UI.CreateEmptyDiv(DRB.DOM.AlternateKey.DivColumns.Id)); 175 | $("#" + DRB.DOM.ConfigureContent.Id).append(divAlternateKey); 176 | DRB.UI.ResetDropdown(DRB.DOM.AlternateKey.Dropdown.Id, DRB.DOM.AlternateKey.Dropdown.Name); 177 | DRB.Logic.BindAlternateKey(DRB.DOM.AlternateKey.Dropdown.Id); 178 | divAlternateKey.hide(); 179 | 180 | var useAlternateKeyValue = "no"; 181 | if (DRB.Metadata.CurrentNode.data.configuration.useAlternateKey === true) { useAlternateKeyValue = "yes"; } 182 | if (useAlternateKeyValue === "no") { $("#" + DRB.DOM.UseAlternateKey.Dropdown.Id).val(useAlternateKeyValue).change(); } 183 | } 184 | 185 | /** 186 | * Add Primary Id 187 | */ 188 | DRB.CustomUI.AddPrimaryId = function (hide, container) { 189 | if (!DRB.Utilities.HasValue(container)) { container = DRB.DOM.ConfigureContent.Id }; 190 | var divPrimaryId = DRB.UI.CreateEmptyDiv(DRB.DOM.PrimaryId.Div.Id); 191 | divPrimaryId.append(DRB.UI.CreateSpan(DRB.DOM.PrimaryId.Span.Id, DRB.DOM.PrimaryId.Span.Name)); 192 | divPrimaryId.append(DRB.UI.CreateInputGuid(DRB.DOM.PrimaryId.Input.Id)); 193 | divPrimaryId.append(DRB.UI.CreateLookup(DRB.DOM.PrimaryId.Lookup.Id, DRB.UI.OpenLookup, { openPrimaryEntity: true, textId: DRB.DOM.PrimaryId.Input.Id })); 194 | $("#" + container).append(divPrimaryId); 195 | DRB.Logic.BindPropertyValue(DRB.DOM.PrimaryId.Input.Id, "primaryId"); 196 | DRB.Common.BindGuid(DRB.DOM.PrimaryId.Input.Id); 197 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryId)) { 198 | $("#" + DRB.DOM.PrimaryId.Input.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryId).trigger("input"); 199 | } 200 | if (hide === true) { divPrimaryId.hide(); } 201 | } 202 | 203 | /** 204 | * Add Columns 205 | */ 206 | DRB.CustomUI.AddColumns = function () { 207 | var divColumns = DRB.UI.CreateEmptyDiv(DRB.DOM.Columns.Div.Id, DRB.DOM.Columns.Div.Class); 208 | divColumns.append(DRB.UI.CreateSpan(DRB.DOM.Columns.Span.Id, DRB.DOM.Columns.Span.Name)); 209 | divColumns.append(DRB.UI.CreateDropdown(DRB.DOM.Columns.Dropdown.Id, true)); 210 | $("#" + DRB.DOM.ConfigureContent.Id).append(divColumns); 211 | DRB.UI.ResetDropdown(DRB.DOM.Columns.Dropdown.Id, DRB.DOM.Columns.Dropdown.Name); 212 | DRB.Logic.BindColumns(DRB.DOM.Columns.Dropdown.Id); 213 | } 214 | 215 | /** 216 | * Add Relationships 217 | */ 218 | DRB.CustomUI.AddRelationships = function () { 219 | var divRelationships = DRB.UI.CreateEmptyDiv(DRB.DOM.DivRelationship.Id); 220 | $("#" + DRB.DOM.ConfigureContent.Id).append(divRelationships); 221 | Object.keys(DRB.DOM.Relationship).forEach(function (relationshipType) { 222 | var relDOM = DRB.DOM.Relationship[relationshipType]; 223 | divRelationships.append(DRB.UI.CreateSpan(relDOM.Span.Id, relDOM.Span.Name)); 224 | divRelationships.append(DRB.UI.CreateDropdown(relDOM.Dropdown.Id, true)); 225 | divRelationships.append(DRB.UI.CreateButton(relDOM.Button.Id, relDOM.Button.Name, relDOM.Button.Class, DRB.Logic.ClickSelectRelationshipColumns, relationshipType)); 226 | divRelationships.append(DRB.UI.CreateSpacer()); 227 | $("#" + relDOM.Button.Id).hide(); 228 | DRB.UI.ResetDropdown(relDOM.Dropdown.Id, relDOM.Dropdown.Name); 229 | }); 230 | } 231 | 232 | /** 233 | * Add Workflow Id 234 | */ 235 | DRB.CustomUI.AddWorkflowId = function () { 236 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.WorkflowId.Span.Id, DRB.DOM.WorkflowId.Span.Name)); 237 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateInputGuid(DRB.DOM.WorkflowId.Input.Id)); 238 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateLookup(DRB.DOM.WorkflowId.Lookup.Id, DRB.UI.OpenLookup, { openWorkflow: true, textId: DRB.DOM.WorkflowId.Input.Id })); 239 | DRB.Logic.BindPropertyValue(DRB.DOM.WorkflowId.Input.Id, "workflowId"); 240 | DRB.Common.BindGuid(DRB.DOM.WorkflowId.Input.Id); 241 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.workflowId)) { 242 | $("#" + DRB.DOM.WorkflowId.Input.Id).val(DRB.Metadata.CurrentNode.data.configuration.workflowId).trigger("input"); 243 | } 244 | } 245 | 246 | /** 247 | * Add Type Columns 248 | */ 249 | DRB.CustomUI.AddTypeColumns = function (container, columnType, domObject, metadataPath) { 250 | // create main div, span title 251 | $("#" + container).append(DRB.UI.CreateEmptyDiv(DRB.DOM[domObject].MainDiv.Id + metadataPath, DRB.DOM[domObject].MainDiv.Class)); 252 | $("#" + DRB.DOM[domObject].MainDiv.Id + metadataPath).append(DRB.UI.CreateSpan(DRB.DOM[domObject].MainSpan.Id, DRB.DOM[domObject].MainSpan.Name)); 253 | 254 | // create the div and the table inside 255 | $("#" + DRB.DOM[domObject].MainDiv.Id + metadataPath).append(DRB.UI.CreateEmptyDiv(DRB.DOM[domObject].Div.Id + metadataPath)); 256 | $("#" + DRB.DOM[domObject].Div.Id + metadataPath).append(DRB.UI.CreateTable(DRB.DOM[domObject].Table.Id + metadataPath)); 257 | $("#" + DRB.DOM[domObject].Table.Id + metadataPath).append(DRB.UI.CreateTr(DRB.DOM[domObject].Tr.Id + metadataPath)); 258 | $("#" + DRB.DOM[domObject].Tr.Id + metadataPath).hide(); 259 | $("#" + DRB.DOM[domObject].Tr.Id + metadataPath).append(DRB.UI.CreateTd(DRB.DOM[domObject].TdColumn.Id + metadataPath)); 260 | $("#" + DRB.DOM[domObject].TdColumn.Id + metadataPath).html(DRB.DOM[domObject].TdColumn.Name); 261 | 262 | if (columnType === "IsValidForFilter") { 263 | $("#" + DRB.DOM[domObject].Tr.Id + metadataPath).append(DRB.UI.CreateTd(DRB.DOM[domObject].TdOperator.Id + metadataPath)); 264 | $("#" + DRB.DOM[domObject].TdOperator.Id + metadataPath).html(DRB.DOM[domObject].TdOperator.Name); 265 | } 266 | 267 | $("#" + DRB.DOM[domObject].Tr.Id + metadataPath).append(DRB.UI.CreateTd(DRB.DOM[domObject].TdValue.Id + metadataPath)); 268 | $("#" + DRB.DOM[domObject].TdValue.Id + metadataPath).html(DRB.DOM[domObject].TdValue.Name); 269 | $("#" + DRB.DOM[domObject].MainDiv.Id + metadataPath).append(DRB.UI.CreateSpacer()); 270 | 271 | // "Add" button 272 | $("#" + DRB.DOM[domObject].MainDiv.Id + metadataPath).append(DRB.UI.CreateButton(DRB.DOM[domObject].AddButton.Id + metadataPath, DRB.DOM[domObject].AddButton.Name, DRB.DOM[domObject].AddButton.Class, DRB.Logic.AddColumn, columnType, domObject, metadataPath)); 273 | 274 | if (columnType === "IsValidForFilter") { 275 | $("#" + DRB.DOM[domObject].MainDiv.Id + metadataPath).append(DRB.UI.CreateButton(DRB.DOM[domObject].AddLookupButton.Id + metadataPath, DRB.DOM[domObject].AddLookupButton.Name, DRB.DOM[domObject].AddLookupButton.Class, DRB.Logic.AddColumn, columnType, domObject, metadataPath, true)); 276 | } 277 | 278 | // hide by default 279 | $("#" + DRB.DOM[domObject].MainDiv.Id + metadataPath).hide(); 280 | } 281 | // #endregion -------------------------------------------------------------------------------- /js/drb.logic.column.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.Column 2 | // Columns Functions, used by Set Columns (Create, Update) Order Columns (Retrieve Multiple), Filter Columns (Retrieve Multiple) 3 | 4 | /** 5 | * Logic - Refresh Arrows 6 | * @param {string} metadataPath Metadata Path 7 | */ 8 | DRB.Logic.RefreshArrows = function (metadataPath) { 9 | var refMetadata = DRB.Metadata; 10 | // get full Metadata and configuration path 11 | metadataPath.split("_").forEach(function (path) { 12 | if (isNaN(parseInt(path))) { 13 | if (refMetadata.hasOwnProperty(path)) { refMetadata = refMetadata[path]; } 14 | } else { 15 | // is a position number 16 | var metadataIndex = parseInt(path); 17 | refMetadata.forEach(function (refItem, refItemIndex) { 18 | if (refItem.Id === metadataIndex) { 19 | // this is the correct path to follow 20 | refMetadata = refMetadata[refItemIndex]; 21 | } 22 | }); 23 | } 24 | }); 25 | 26 | 27 | if (refMetadata.length > 0) { 28 | // set the arrow for the first and the last column 29 | var firstIndex = metadataPath + "_" + refMetadata[0].Id; 30 | var lastIndex = metadataPath + "_" + refMetadata[refMetadata.length - 1].Id; 31 | 32 | $("#" + DRB.DOM.ArrowUp.Id + lastIndex).show(); 33 | $("#" + DRB.DOM.ArrowDown.Id + firstIndex).show(); 34 | $("#" + DRB.DOM.ArrowUp.Id + firstIndex).hide(); 35 | $("#" + DRB.DOM.ArrowDown.Id + lastIndex).hide(); 36 | 37 | $("#" + DRB.DOM.ArrowBeforeUp.Id + firstIndex).show(); 38 | $("#" + DRB.DOM.ArrowAfterDown.Id + firstIndex).hide(); 39 | $("#" + DRB.DOM.ArrowBeforeUp.Id + lastIndex).hide(); 40 | $("#" + DRB.DOM.ArrowAfterDown.Id + lastIndex).show(); 41 | 42 | // set the arrows for the columns in the middle (exclude first and exclude last) 43 | for (var count = 1; count < refMetadata.length - 1; count++) { 44 | var uniqueIndex = metadataPath + "_" + refMetadata[count].Id; 45 | $("#" + DRB.DOM.ArrowUp.Id + uniqueIndex).show(); 46 | $("#" + DRB.DOM.ArrowDown.Id + uniqueIndex).show(); 47 | $("#" + DRB.DOM.ArrowBeforeUp.Id + uniqueIndex).hide(); 48 | $("#" + DRB.DOM.ArrowAfterDown.Id + uniqueIndex).hide(); 49 | } 50 | } 51 | } 52 | 53 | /** 54 | * Logic - Move Column 55 | * @param {number} index Index 56 | * @param {string} direction Direction ("up" or "down") 57 | * @param {string} domObject DOM Object 58 | * @param {string} metadataPath Metadata Path 59 | */ 60 | DRB.Logic.MoveColumn = function (index, direction, domObject, metadataPath) { 61 | 62 | // get full Metadata and configuration path 63 | var refMetadata = DRB.Metadata; 64 | var refConfiguration = DRB.Metadata.CurrentNode.data.configuration; 65 | // get full Metadata and configuration path 66 | metadataPath.split("_").forEach(function (path) { 67 | if (isNaN(parseInt(path))) { 68 | if (refMetadata.hasOwnProperty(path)) { refMetadata = refMetadata[path]; } 69 | if (refConfiguration.hasOwnProperty(path)) { refConfiguration = refConfiguration[path]; } 70 | } else { 71 | // is a position number 72 | var metadataIndex = parseInt(path); 73 | refMetadata.forEach(function (refItem, refItemIndex) { 74 | if (refItem.Id === metadataIndex) { 75 | // this is the correct path to follow 76 | refMetadata = refMetadata[refItemIndex]; 77 | refConfiguration = refConfiguration[refItemIndex]; 78 | } 79 | }); 80 | } 81 | }); 82 | 83 | // if DRB.Metadata[metadataPath] is empty do nothing 84 | if (refMetadata.length === 0) { return; } 85 | 86 | // variables, default is up 87 | var positionToCheck = 0; 88 | var countStart = 1; 89 | var countEnd = refMetadata.length; 90 | var diff = -1; 91 | if (direction === "down") { 92 | positionToCheck = refMetadata.length - 1; 93 | countStart = 0; 94 | countEnd = refMetadata.length - 1; 95 | diff = 1; 96 | } 97 | 98 | // check if it's not the first position (if up) or the last position (if down) 99 | if (refMetadata[positionToCheck].Id != index) { 100 | 101 | // find the position of the passed index 102 | var posIndex = -1; 103 | for (var count = countStart; count < countEnd; count++) { if (refMetadata[count].Id == index) { posIndex = count; break; } } 104 | 105 | // index not found, do nothing 106 | if (posIndex === -1) { return; } 107 | 108 | // swap DRB.Metadata 109 | var currentElementMetadata = refMetadata[posIndex]; 110 | refMetadata[posIndex] = refMetadata[posIndex + diff]; 111 | refMetadata[posIndex + diff] = currentElementMetadata; 112 | 113 | // swap data.configuration 114 | var currentElementNode = refConfiguration[posIndex]; 115 | refConfiguration[posIndex] = refConfiguration[posIndex + diff]; 116 | refConfiguration[posIndex + diff] = currentElementNode; 117 | 118 | // swap tr 119 | if (direction === "down") { $("#" + DRB.DOM[domObject].Tr.Id + metadataPath + "_" + index).next().after($("#" + DRB.DOM[domObject].Tr.Id + metadataPath + "_" + index)); } 120 | else { $("#" + DRB.DOM[domObject].Tr.Id + metadataPath + "_" + index).prev().before($("#" + DRB.DOM[domObject].Tr.Id + metadataPath + "_" + index)); } 121 | 122 | // refresh arrows 123 | DRB.Logic.RefreshArrows(metadataPath); 124 | } 125 | } 126 | 127 | /** 128 | * Logic - Refresh Columns 129 | * @param {string} columnType Column Type 130 | * @param {string} domObject DOM Object 131 | * @param {string} metadataPath Metadata Path 132 | */ 133 | DRB.Logic.RefreshColumns = function (columnType, domObject, metadataPath) { 134 | // get logicalName of used columns 135 | var usedColumnsNames = []; 136 | var refMetadata = DRB.Metadata; 137 | // get full Metadata and configuration path 138 | metadataPath.split("_").forEach(function (path) { 139 | if (isNaN(parseInt(path))) { 140 | if (refMetadata.hasOwnProperty(path)) { refMetadata = refMetadata[path]; } 141 | } else { 142 | // is a position number 143 | var metadataIndex = parseInt(path); 144 | refMetadata.forEach(function (refItem, refItemIndex) { 145 | if (refItem.Id === metadataIndex) { 146 | // this is the correct path to follow 147 | refMetadata = refMetadata[refItemIndex]; 148 | } 149 | }); 150 | } 151 | }); 152 | 153 | refMetadata.forEach(function (column) { 154 | if (DRB.Utilities.HasValue(column.Value) && DRB.Utilities.HasValue(column.Value.logicalName)) { 155 | usedColumnsNames.push(column.Value.logicalName); 156 | } 157 | }); 158 | 159 | // check for the logic operator at column level for filtering 160 | 161 | if (columnType === "IsValidForFilter") { 162 | if (refMetadata.length > 1) { 163 | $("#" + DRB.DOM[domObject].DivLogic.Id + metadataPath).show(); 164 | } else { 165 | $("#" + DRB.DOM[domObject].DropdownLogic.Id + metadataPath).val(DRB.Settings.OptionsAndOr[0].Id).change(); 166 | $("#" + DRB.DOM[domObject].DivLogic.Id + metadataPath).hide(); 167 | } 168 | } 169 | 170 | // refresh all the dropdowns 171 | refMetadata.forEach(function (metadataColumn) { 172 | var uniqueIndex = metadataPath + "_" + metadataColumn.Id; 173 | var originalColumnName = $("#" + DRB.DOM[domObject].Dropdown.Id + uniqueIndex).val(); 174 | 175 | // create the columns to fill the dropdown 176 | var availableColumns = []; 177 | if (columnType !== "IsValidForFilter") { 178 | // add the column already selected for this dropdown 179 | DRB.Metadata.CurrentColumns.forEach(function (currentColumn) { 180 | if ((currentColumn[columnType] === true && usedColumnsNames.indexOf(currentColumn.LogicalName) === -1) 181 | || currentColumn.LogicalName === originalColumnName) { 182 | availableColumns.push(currentColumn); 183 | } 184 | }); 185 | } else { 186 | // For Filtering all the columns enabled for filtering must be shown, regardeless if they were used before 187 | if ($("#" + DRB.DOM[domObject].LookupRelationshipDropdown.Id + uniqueIndex).length === 0) { 188 | DRB.Metadata.CurrentColumns.forEach(function (currentColumn) { 189 | if (currentColumn[columnType] === true) { availableColumns.push(currentColumn); } 190 | }); 191 | } 192 | } 193 | // #region Relationships 194 | if (columnType === "IsValidForFilter" && $("#" + DRB.DOM[domObject].LookupRelationshipDropdown.Id + uniqueIndex).length > 0) { 195 | var relationshipName = $("#" + DRB.DOM[domObject].LookupRelationshipDropdown.Id + uniqueIndex).val(); 196 | // create the relationships to fill the dropdown 197 | var availableRelationships = []; 198 | DRB.Metadata.CurrentManyToOne.forEach(function (currentRelationship) { availableRelationships.push(new DRB.Models.RelationshipLookup(currentRelationship)); }); 199 | availableRelationships.sort(DRB.Utilities.CustomSort("NavigationAttribute")); 200 | // fill dropdown 201 | DRB.UI.FillDropdown(DRB.DOM[domObject].LookupRelationshipDropdown.Id + uniqueIndex, DRB.DOM[domObject].LookupRelationshipDropdown.Name, new DRB.Models.Records(availableRelationships).ToDropdown()); 202 | // set the previous value 203 | $("#" + DRB.DOM[domObject].LookupRelationshipDropdown.Id + uniqueIndex).val(relationshipName); 204 | // refresh dropdown 205 | DRB.UI.RefreshDropdown(DRB.DOM[domObject].LookupRelationshipDropdown.Id + uniqueIndex); 206 | 207 | var relationship = DRB.Utilities.GetRecordById(DRB.Metadata.CurrentManyToOne, relationshipName); 208 | if (DRB.Utilities.HasValue(relationship)) { 209 | var table = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, relationship.TargetTable); 210 | if (DRB.Utilities.HasValue(table)) { 211 | table.Columns.forEach(function (currentColumn) { 212 | if (currentColumn[columnType] === true) { availableColumns.push(currentColumn); } 213 | }); 214 | } 215 | } 216 | } 217 | // #endregion 218 | 219 | // fill dropdown 220 | DRB.UI.FillDropdown(DRB.DOM[domObject].Dropdown.Id + uniqueIndex, DRB.DOM[domObject].Dropdown.Name, new DRB.Models.Records(availableColumns).ToDropdown()); 221 | // set the previous value 222 | $("#" + DRB.DOM[domObject].Dropdown.Id + uniqueIndex).val(originalColumnName); 223 | // refresh dropdown 224 | DRB.UI.RefreshDropdown(DRB.DOM[domObject].Dropdown.Id + uniqueIndex); 225 | 226 | // if no columns available (for example relationship dropdown has not been selected) disable the dropdown 227 | if (availableColumns.length === 0) { 228 | DRB.UI.ResetDropdown(DRB.DOM[domObject].Dropdown.Id + uniqueIndex, DRB.DOM[domObject].Dropdown.Name); 229 | } 230 | }); 231 | } 232 | 233 | /** 234 | * Logic - Remove Column 235 | * @param {number} index Index 236 | * @param {string} columnType Column Type 237 | * @param {string} domObject DOM Object 238 | * @param {string} metadataPath Metadata Path 239 | */ 240 | DRB.Logic.RemoveColumn = function (index, columnType, domObject, metadataPath) { 241 | // remove tr 242 | $("#" + DRB.DOM[domObject].Tr.Id + metadataPath + "_" + index).remove(); 243 | 244 | // get full Metadata and configuration path 245 | var refMetadata = DRB.Metadata; 246 | var refConfiguration = DRB.Metadata.CurrentNode.data.configuration; 247 | // get full Metadata and configuration path 248 | metadataPath.split("_").forEach(function (path) { 249 | if (isNaN(parseInt(path))) { 250 | if (refMetadata.hasOwnProperty(path)) { refMetadata = refMetadata[path]; } 251 | if (refConfiguration.hasOwnProperty(path)) { refConfiguration = refConfiguration[path]; } 252 | } else { 253 | // is a position number 254 | var metadataIndex = parseInt(path); 255 | refMetadata.forEach(function (refItem, refItemIndex) { 256 | if (refItem.Id === metadataIndex) { 257 | // this is the correct path to follow 258 | refMetadata = refMetadata[refItemIndex]; 259 | refConfiguration = refConfiguration[refItemIndex]; 260 | } 261 | }); 262 | } 263 | }); 264 | 265 | // refresh DRB.Metadata[metadataPath] with all columns except the one removed 266 | var newMetadataColumns = []; 267 | var indexToRemove = -1; 268 | refMetadata.forEach(function (column, columnIndex) { 269 | if (column.Id == index) { indexToRemove = columnIndex; } else { newMetadataColumns.push(column); } 270 | }); 271 | 272 | refMetadata.length = 0; 273 | newMetadataColumns.forEach(function (newMetadataColumn) { refMetadata.push(newMetadataColumn); }); 274 | 275 | // refresh data.configuration using indexToRemove found in the previous for cycle 276 | if (indexToRemove > -1) { 277 | var newFields = []; 278 | refConfiguration.forEach(function (field, fieldIndex) { 279 | if (fieldIndex !== indexToRemove) { newFields.push(field); } 280 | }); 281 | refConfiguration.length = 0; 282 | newFields.forEach(function (newField) { refConfiguration.push(newField); }); 283 | } 284 | 285 | // hide the first tr (header) if there are no columns 286 | if (refMetadata.length === 0) { $("#" + DRB.DOM[domObject].Tr.Id + metadataPath).hide(); } 287 | 288 | // Refresh arrows 289 | DRB.Logic.RefreshArrows(metadataPath); 290 | 291 | // Refresh Columns 292 | DRB.Logic.RefreshColumns(columnType, domObject, metadataPath); 293 | } 294 | 295 | /** 296 | * Logic - Add Column 297 | * @param {string} columnType Column Type 298 | * @param {string} domObject DOM Object 299 | * @param {string} metadataPath Metadata Path 300 | */ 301 | DRB.Logic.AddColumn = function (columnType, domObject, metadataPath, fromRelationship) { 302 | // show the first tr (header) 303 | $("#" + DRB.DOM[domObject].Tr.Id + metadataPath).show(); 304 | 305 | // initialize index 306 | var index = 0; 307 | 308 | // get full Metadata and configuration path 309 | var refMetadata = DRB.Metadata; 310 | var refConfiguration = DRB.Metadata.CurrentNode.data.configuration; 311 | // get full Metadata and configuration path 312 | metadataPath.split("_").forEach(function (path) { 313 | if (isNaN(parseInt(path))) { 314 | if (refMetadata.hasOwnProperty(path)) { refMetadata = refMetadata[path]; } 315 | if (refConfiguration.hasOwnProperty(path)) { refConfiguration = refConfiguration[path]; } 316 | } else { 317 | // is a position number 318 | var metadataIndex = parseInt(path); 319 | refMetadata.forEach(function (refItem, refItemIndex) { 320 | if (refItem.Id === metadataIndex) { 321 | // this is the correct path to follow 322 | refMetadata = refMetadata[refItemIndex]; 323 | refConfiguration = refConfiguration[refItemIndex]; 324 | } 325 | }); 326 | } 327 | }); 328 | 329 | // if DRB.Metadata[metadataPath] has values get the higher index and add 1 330 | if (refMetadata.length > 0) { 331 | var maxValue = 0; 332 | refMetadata.forEach(function (setColumn) { if (setColumn.Id > maxValue) { maxValue = setColumn.Id; } }); 333 | index = maxValue + 1; 334 | } 335 | var uniqueIndex = metadataPath + "_" + index; 336 | // create tr 337 | var tr = DRB.UI.CreateTr(DRB.DOM[domObject].Tr.Id + uniqueIndex); 338 | var tdColumn = DRB.UI.CreateTd(DRB.DOM[domObject].TdColumn.Id + uniqueIndex); 339 | var tdOperator = null; 340 | if (columnType === "IsValidForFilter") { tdOperator = DRB.UI.CreateTd(DRB.DOM[domObject].TdOperator.Id + uniqueIndex); } 341 | var tdValue = DRB.UI.CreateTd(DRB.DOM[domObject].TdValue.Id + uniqueIndex); 342 | $("#" + DRB.DOM[domObject].Table.Id + metadataPath).append(tr); 343 | 344 | tr.append(tdColumn); 345 | if (columnType === "IsValidForFilter") { tr.append(tdOperator); } 346 | tr.append(tdValue); 347 | 348 | // append close, arrow up and arrow down buttons (plus empty arrow button for spacing) 349 | tdColumn.append(DRB.UI.CreateRemoveButton(DRB.Logic.RemoveColumn, index, columnType, domObject, metadataPath)); 350 | tdColumn.append(DRB.UI.CreateEmptyArrowButton(DRB.DOM.ArrowBeforeUp.Id + uniqueIndex)); 351 | tdColumn.append(DRB.UI.CreateUpButton(DRB.DOM.ArrowUp.Id + uniqueIndex, DRB.Logic.MoveColumn, index, "up", domObject, metadataPath)); 352 | tdColumn.append(DRB.UI.CreateDownButton(DRB.DOM.ArrowDown.Id + uniqueIndex, DRB.Logic.MoveColumn, index, "down", domObject, metadataPath)); 353 | tdColumn.append(DRB.UI.CreateEmptyArrowButton(DRB.DOM.ArrowAfterDown.Id + uniqueIndex)); 354 | 355 | // create column dropdown selection 356 | 357 | if (fromRelationship === true) { 358 | $("#" + DRB.DOM[domObject].Tr.Id + uniqueIndex).prop("style", "background: #f0f7ff;"); 359 | tdColumn.append(DRB.UI.CreateDropdown(DRB.DOM[domObject].LookupRelationshipDropdown.Id + uniqueIndex)); 360 | tdColumn.append(DRB.UI.CreateSpacer()); 361 | tdColumn.append(DRB.UI.CreateEmptyRemoveButton("")); 362 | tdColumn.append(DRB.UI.CreateEmptyArrowButton("")); 363 | tdColumn.append(DRB.UI.CreateEmptyArrowButton("")); 364 | } 365 | 366 | tdColumn.append(DRB.UI.CreateDropdown(DRB.DOM[domObject].Dropdown.Id + uniqueIndex)); 367 | 368 | switch (columnType) { 369 | case "IsValidForOrder": 370 | DRB.Logic.BindOrderColumn(DRB.DOM[domObject].Dropdown.Id + uniqueIndex, columnType, domObject, metadataPath); 371 | break; 372 | case "IsValidForFilter": 373 | DRB.Logic.BindFilterColumn(DRB.DOM[domObject].Dropdown.Id + uniqueIndex, columnType, domObject, metadataPath); 374 | if (fromRelationship === true) { 375 | DRB.Logic.BindFilterLookupRelationship(DRB.DOM[domObject].LookupRelationshipDropdown.Id + uniqueIndex, columnType, domObject, metadataPath); 376 | } 377 | break; 378 | case "IsValidForCreate": 379 | case "IsValidForUpdate": 380 | DRB.Logic.BindSetColumn(DRB.DOM[domObject].Dropdown.Id + uniqueIndex, columnType, domObject, metadataPath); 381 | break; 382 | } 383 | 384 | // add to DRB.Metadata and to data.configuration 385 | var field = {}; 386 | refMetadata.push(new DRB.Models.IdValue(index, field)); 387 | refConfiguration.push(field); 388 | 389 | // refresh columns 390 | DRB.Logic.RefreshColumns(columnType, domObject, metadataPath); 391 | 392 | // refresh arrows 393 | DRB.Logic.RefreshArrows(metadataPath); 394 | } 395 | // #endregion -------------------------------------------------------------------------------- /js/drb.common.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Common 2 | /** 3 | * Common - Get Error Message 4 | * Get the error message from an xhr object 5 | * @param {any} xhr xhr Object 6 | */ 7 | DRB.Common.GetErrorMessage = function (xhr) { 8 | try { 9 | var printedContent = JSON.stringify(xhr.responseText, null, "!!").replace(/!!/g, "  ").replace(/(?:\r\n|\r|\n)/g, '
'); 10 | return printedContent; 11 | } 12 | catch (e) { 13 | console.log(xhr); 14 | return "Unable to parse the error, logged it inside the browser console"; 15 | } 16 | } 17 | 18 | /** 19 | * Common - Show Current Access Token 20 | */ 21 | DRB.Common.ShowCurrentAccessToken = function () { 22 | var tokenDiv = DRB.UI.CreateEmptyDiv(DRB.DOM.ShowToken.Div.Id); 23 | var title = "You can decode the token at jwt.io"; 24 | var token = DRB.Xrm.GetCurrentAccessToken(); 25 | DRB.UI.Show("Current Access Token", tokenDiv); 26 | 27 | if (DRB.Xrm.IsInstanceMode()) { title = "Current Access Token is not available when Dataverse REST Builder is launched from the Managed Solution"; } 28 | tokenDiv.append(DRB.UI.CreateSpan(DRB.DOM.ShowToken.TitleSpan.Id, title)); 29 | if (!DRB.Xrm.IsInstanceMode()) { 30 | tokenDiv.append(DRB.UI.CreateSpacer()); 31 | tokenDiv.append(DRB.UI.CreateInputToken(DRB.DOM.ShowToken.Input.Id)); 32 | $("#" + DRB.DOM.ShowToken.Input.Id).val(token); 33 | } 34 | } 35 | 36 | /** 37 | * Common - Extract Index From Control Name 38 | * @param {string} controlName Control Name 39 | */ 40 | DRB.Common.ExtractIndexFromControlName = function (controlName) { 41 | // if the string is like custom_controlname_number, return number 42 | if (!DRB.Utilities.HasValue(controlName)) { return -1; } 43 | var lastUnderscore = controlName.lastIndexOf("_"); 44 | if (lastUnderscore > -1 && lastUnderscore + 1 < controlName.length) { return parseInt(controlName.substring(lastUnderscore + 1)); } else { return -1; } 45 | } 46 | 47 | DRB.Common.ExtractPreviousIndexFromControlName = function (controlName) { 48 | // if the string is like custom_controlname_number1_number2, return number1 49 | if (!DRB.Utilities.HasValue(controlName)) { return -1; } 50 | var lastUnderscore = controlName.lastIndexOf("_"); 51 | if (lastUnderscore > -1) { 52 | var strippedControlName = controlName.substring(0, lastUnderscore); 53 | return DRB.Common.ExtractIndexFromControlName(strippedControlName); 54 | } else { return -1; } 55 | } 56 | 57 | /** 58 | * Common - Bind Guid 59 | * Bind the input event to check if it is a valid Guid 60 | * @param {string} id Element Id 61 | */ 62 | DRB.Common.BindGuid = function (id) { 63 | $("#" + id).on("input", function (e) { 64 | $(this).val(function (i, v) { 65 | var cleared = v.replace(/[^0-9AaBbCcDdEeFf]/g, "").toLowerCase(); 66 | var finalGuid = cleared; 67 | if (finalGuid.length > 8) { finalGuid = finalGuid.substring(0, 8) + "-" + finalGuid.substring(8); } 68 | if (finalGuid.length > 13) { finalGuid = finalGuid.substring(0, 13) + "-" + finalGuid.substring(13); } 69 | if (finalGuid.length > 18) { finalGuid = finalGuid.substring(0, 18) + "-" + finalGuid.substring(18); } 70 | if (finalGuid.length > 23) { finalGuid = finalGuid.substring(0, 23) + "-" + finalGuid.substring(23); } 71 | if (finalGuid.length === 36) { $(this).removeClass("is-invalid"); $(this).addClass("is-valid"); } 72 | else { 73 | if (finalGuid.length > 0) { 74 | $(this).removeClass("is-valid"); $(this).addClass("is-invalid"); 75 | } else { $(this).removeClass("is-valid"); $(this).removeClass("is-invalid"); } 76 | } 77 | return finalGuid; 78 | }); 79 | }); 80 | } 81 | 82 | /** 83 | * Common - Bind Integer 84 | * Bind the input event to check if it is a valid Integer 85 | * @param {string} id Element Id 86 | */ 87 | DRB.Common.BindInteger = function (id, minValue, maxValue) { 88 | $("#" + id).on("input", function (e) { 89 | $(this).val(function (i, v) { 90 | var finalNumber = v.replace(/[^0-9-]/g, ""); 91 | if (finalNumber.lastIndexOf("-") > 0) { 92 | finalNumber = finalNumber.charAt(0) + finalNumber.substring(1).replace(/-/g, ""); 93 | } 94 | if (finalNumber < minValue || finalNumber > maxValue || finalNumber == "-") { $(this).removeClass("is-valid"); $(this).addClass("is-invalid"); } 95 | else { $(this).removeClass("is-invalid"); $(this).addClass("is-valid"); } 96 | return finalNumber; 97 | }); 98 | }); 99 | } 100 | 101 | /** 102 | * Common - Bind Top Count Number 103 | * Bind the input event to check if it is a valid Top Count (between 1 and 5000) 104 | * @param {string} id Element Id 105 | */ 106 | DRB.Common.BindTopCountNumber = function (id) { 107 | $("#" + id).on("input", function (e) { 108 | var minValue = 1; 109 | var maxValue = 5000; 110 | $(this).val(function (i, v) { 111 | var finalNumber = v.replace(/[^0-9]/g, ""); 112 | if (DRB.Utilities.HasValue(finalNumber)) { 113 | if (finalNumber < minValue) { finalNumber = 1; } 114 | if (finalNumber > maxValue) { finalNumber = 5000; } 115 | } 116 | return finalNumber; 117 | }); 118 | }); 119 | } 120 | 121 | /** 122 | * Common - Bind File Name 123 | * Bind the input event to check if it is a valid file name 124 | * @param {string} id Element Id 125 | */ 126 | DRB.Common.BindFileName = function (id) { 127 | $("#" + id).on("input", function (e) { 128 | $(this).val(function (i, v) { 129 | // \/:*?"<>| these chars are not allowed inside a file name 130 | var finalName = v.replace(/\\/g, ""); 131 | finalName = finalName.replace(/\//g, ""); 132 | finalName = finalName.replace(/:/g, ""); 133 | finalName = finalName.replace(/\*/g, ""); 134 | finalName = finalName.replace(/\?/g, ""); 135 | finalName = finalName.replace(/"/g, ""); 136 | finalName = finalName.replace(//g, ""); 138 | finalName = finalName.replace(/\|/g, ""); 139 | return finalName; 140 | }); 141 | }); 142 | } 143 | 144 | /** 145 | * Common - Bind Number 146 | * Bind the input event to check if it is a valid Number 147 | * @param {string} id Element Id 148 | */ 149 | DRB.Common.BindNumber = function (id, minValue, maxValue) { 150 | $("#" + id).on("input", function (e) { 151 | $(this).val(function (i, v) { 152 | var finalNumber = v.replace(/[^0-9-.]/g, ""); 153 | if (finalNumber.lastIndexOf("-") > 0) { 154 | finalNumber = finalNumber.charAt(0) + finalNumber.substring(1).replace(/-/g, ""); 155 | } 156 | 157 | if (finalNumber.indexOf(".") > -1 && finalNumber.indexOf(".") !== finalNumber.lastIndexOf(".")) { 158 | finalNumber = finalNumber.substring(0, finalNumber.indexOf(".") + 1) + "" + finalNumber.substring(finalNumber.indexOf(".") + 1).replace(/\./g, ""); 159 | } 160 | 161 | if (finalNumber < minValue || finalNumber > maxValue || finalNumber == "-" || finalNumber == "." || finalNumber == "-.") { $(this).removeClass("is-valid"); $(this).addClass("is-invalid"); } 162 | else { $(this).removeClass("is-invalid"); $(this).addClass("is-valid"); } 163 | return finalNumber; 164 | }); 165 | }); 166 | } 167 | 168 | DRB.Common.LookupSelect = function (settings, tableLogicalName, recordId) { 169 | $("#" + settings.textId).val(recordId).trigger("input").change(); 170 | if (DRB.Utilities.HasValue(settings.dropdownId)) { 171 | $("#" + settings.dropdownId).val(tableLogicalName).change(); 172 | DRB.UI.RefreshDropdown(settings.dropdownId); 173 | } 174 | DRB.UI.HideLoading(); 175 | } 176 | 177 | DRB.Common.LookupSearch = function (settings) { 178 | var tableLogicalName = $("#" + DRB.DOM.Lookup.TableDropdown.Id).val(); 179 | if (!DRB.Utilities.HasValue(tableLogicalName)) { return; } 180 | 181 | 182 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 183 | if (DRB.Utilities.HasValue(checkTable)) { 184 | $("#" + DRB.DOM.Lookup.DivResults.Id).empty(); 185 | $("#" + DRB.DOM.Lookup.DivResults.Id).append(DRB.UI.CreateSpan("", "Retrieving Records...")); 186 | 187 | var text = $("#" + DRB.DOM.Lookup.Input.Id).val(); 188 | var filterText = ""; 189 | if (DRB.Utilities.HasValue(text)) { filterText = "&$filter=contains(" + checkTable.PrimaryNameAttribute + ",'" + text + "')"; } 190 | DRB.Xrm.Retrieve(checkTable.EntitySetName, "$select=" + checkTable.PrimaryNameAttribute + filterText + "&$orderby=" + checkTable.PrimaryNameAttribute + " asc&$top=5") 191 | .done(function (data) { 192 | $("#" + DRB.DOM.Lookup.DivResults.Id).empty(); 193 | if (data.value.length > 0) { 194 | // Create Table to show the results 195 | var divTable = DRB.UI.CreateTable(DRB.DOM.Lookup.Table.Id); 196 | var thHeader = DRB.UI.CreateTr(DRB.DOM.Lookup.Tr.Id + "header"); 197 | var tdLabelHeaderSelect = DRB.UI.CreateTd(DRB.DOM.Lookup.TdLabel.Id + "header_select"); 198 | var tdLabelHeaderID = DRB.UI.CreateTd(DRB.DOM.Lookup.TdLabel.Id + "header_id"); 199 | var tdLabelHeaderPrimaryColumn = DRB.UI.CreateTd(DRB.DOM.Lookup.TdLabel.Id + "header_primarycolumn"); 200 | divTable.append(thHeader); 201 | thHeader.append(tdLabelHeaderSelect); 202 | thHeader.append(tdLabelHeaderID); 203 | thHeader.append(tdLabelHeaderPrimaryColumn); 204 | tdLabelHeaderID.append(DRB.UI.CreateSpan(DRB.DOM.Lookup.HeaderIDSpan.Id, DRB.DOM.Lookup.HeaderIDSpan.Name)); 205 | tdLabelHeaderPrimaryColumn.append(DRB.UI.CreateSpan(DRB.DOM.Lookup.HeaderPrimaryColumnSpan.Id, DRB.DOM.Lookup.HeaderPrimaryColumnSpan.Name)); 206 | 207 | var searchResults = []; 208 | 209 | data.value.forEach(function (record) { 210 | searchResults.push({ Id: record[checkTable.PrimaryIdAttribute], PrimaryColumn: record[checkTable.PrimaryNameAttribute] }); 211 | }); 212 | 213 | searchResults.forEach(function (searchResult, searchResultIndex) { 214 | var tr = DRB.UI.CreateTr(DRB.DOM.Lookup.Tr.Id + searchResultIndex); 215 | var tdValueSelect = DRB.UI.CreateTd(DRB.DOM.Lookup.TdValue.Id + searchResultIndex + "_select"); 216 | var tdValueID = DRB.UI.CreateTd(DRB.DOM.Lookup.TdValue.Id + searchResultIndex + "_id"); 217 | var tdValuePrimaryColumn = DRB.UI.CreateTd(DRB.DOM.Lookup.TdValue.Id + searchResultIndex + "_primarycolumn"); 218 | 219 | divTable.append(tr); 220 | tr.append(tdValueSelect); 221 | tr.append(tdValueID); 222 | tr.append(tdValuePrimaryColumn); 223 | tdValueSelect.append(DRB.UI.CreateButton(DRB.DOM.Lookup.SelectButton.Id + searchResultIndex, DRB.DOM.Lookup.SelectButton.Name, DRB.DOM.Lookup.SelectButton.Class, DRB.Common.LookupSelect, settings, checkTable.LogicalName, searchResult.Id)); 224 | tdValueID.append(DRB.UI.CreateSpan("", searchResult.Id)); 225 | tdValuePrimaryColumn.append(DRB.UI.CreateSpan("", searchResult.PrimaryColumn)); 226 | }); 227 | $("#" + DRB.DOM.Lookup.DivResults.Id).append(divTable); 228 | } else { 229 | $("#" + DRB.DOM.Lookup.DivResults.Id).append(DRB.UI.CreateSpan("", "No Records")); 230 | } 231 | }) 232 | .fail(function (xhr) { 233 | $("#" + DRB.DOM.Lookup.DivResults.Id).empty(); 234 | $("#" + DRB.DOM.Lookup.DivResults.Id).append(DRB.UI.CreateSpan("", "Error retrieving Records")); 235 | }); 236 | } 237 | } 238 | 239 | DRB.Common.BindLookupTable = function (id) { 240 | $("#" + id).on("change", function (e) { 241 | $("#" + DRB.DOM.Lookup.DivResults.Id).empty(); 242 | }); 243 | } 244 | 245 | DRB.Common.OpenLookup = function (lookupOptions, settings) { 246 | var lookupTables = []; 247 | lookupOptions.entityTypes.forEach(function (tableLogicalName) { 248 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 249 | if (DRB.Utilities.HasValue(checkTable)) { lookupTables.push(checkTable); } 250 | }); 251 | 252 | var lookupDiv = DRB.UI.CreateEmptyDiv(DRB.DOM.Lookup.Div.Id); 253 | lookupDiv.append(DRB.UI.CreateSpan(DRB.DOM.Lookup.TableSpan.Id, DRB.DOM.Lookup.TableSpan.Name)); 254 | lookupDiv.append(DRB.UI.CreateDropdown(DRB.DOM.Lookup.TableDropdown.Id)); 255 | lookupDiv.append(DRB.UI.CreateSpan("", "NOTE: maximum 5 records are returned")); 256 | lookupDiv.append(DRB.UI.CreateSpacer()); 257 | lookupDiv.append(DRB.UI.CreateSpan(DRB.DOM.Lookup.InputSpan.Id, DRB.DOM.Lookup.InputSpan.Name)); 258 | lookupDiv.append(DRB.UI.CreateInputString(DRB.DOM.Lookup.Input.Id)); 259 | lookupDiv.append(DRB.UI.CreateSpan(null, " ")); 260 | lookupDiv.append(DRB.UI.CreateButton(DRB.DOM.Lookup.SearchButton.Id, DRB.DOM.Lookup.SearchButton.Name, DRB.DOM.Lookup.SearchButton.Class, DRB.Common.LookupSearch, settings)); 261 | lookupDiv.append(DRB.UI.CreateSpacer()); 262 | lookupDiv.append(DRB.UI.CreateEmptyDiv(DRB.DOM.Lookup.DivResults.Id, DRB.DOM.Lookup.DivResults.Class)); 263 | DRB.UI.Show("Lookup", lookupDiv, "large"); 264 | $(".modal-footer").remove(); 265 | DRB.UI.FillDropdown(DRB.DOM.Lookup.TableDropdown.Id, DRB.DOM.Lookup.TableDropdown.Name, new DRB.Models.Records(lookupTables).ToDropdown()); 266 | DRB.Common.BindLookupTable(DRB.DOM.Lookup.TableDropdown.Id); 267 | } 268 | 269 | /** 270 | * Common - Parse JWT 271 | * @param {string} token Token 272 | */ 273 | DRB.Common.ParseJWT = function (token) { 274 | try { 275 | var base64Url = token.split('.')[1]; 276 | var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); 277 | var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) { 278 | return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); 279 | }).join('')); 280 | return JSON.parse(jsonPayload); 281 | } catch (e) { 282 | return null; 283 | } 284 | } 285 | 286 | /** 287 | * Common - Refresh XTB Token 288 | * @param {string} token Token 289 | */ 290 | DRB.Common.RefreshXTBToken = function (token) { 291 | if (!DRB.Xrm.IsXTBMode()) { console.log("This method id available only with XTB Mode"); return; } 292 | if (!DRB.Utilities.HasValue(token)) { console.log("Received XTB token is not valid"); return; } 293 | DRB.Settings.XTBToken = token; 294 | console.log("Refreshed token from XTB"); 295 | } 296 | 297 | /** 298 | * Common - Refresh BE Token 299 | * @param {string} token Token 300 | */ 301 | DRB.Common.RefreshBEToken = function (token) { 302 | if (!DRB.Xrm.IsBEMode()) { console.log("This method id available only with BE Mode"); return; } 303 | if (!DRB.Utilities.HasValue(token)) { console.log("Received BE token is not valid"); return; } 304 | DRB.Settings.BEToken = token; 305 | console.log("Refreshed token from BE"); 306 | } 307 | 308 | /** 309 | * Common - Refresh DVDT Token 310 | * @param {string} token Token 311 | */ 312 | DRB.Common.RefreshDVDTToken = function (token) { 313 | if (!DRB.Xrm.IsDVDTMode()) { console.log("This method id available only with DVDT Mode"); return; } 314 | if (!DRB.Utilities.HasValue(token)) { console.log("Received DVDT token is not valid"); return; } 315 | DRB.Settings.DVDTToken = token; 316 | console.log("Refreshed token from DVDT"); 317 | } 318 | 319 | /** 320 | * Common - Listener for DVDT and BE 321 | */ 322 | window.addEventListener("message", (event) => { 323 | const message = event.data; 324 | switch (message.command) { 325 | case "dvdt_connection": 326 | var token = message.token; 327 | var parsedToken = DRB.Common.ParseJWT(token); 328 | if (DRB.Utilities.HasValue(parsedToken)) { 329 | var tokenUrl = parsedToken.aud; 330 | var tokenExpireDate = parsedToken.exp * 1000; 331 | var now = new Date().getTime(); 332 | if (DRB.Utilities.HasValue(tokenUrl) && tokenExpireDate > now) { 333 | tokenUrl = tokenUrl.replace(/\/$/, ""); // clean url from trailing slash 334 | DRB.UI.ShowLoading("Checking Token Settings..."); 335 | 336 | DRB.Xrm.GetServerVersion(tokenUrl, token) 337 | .done(function (data) { 338 | DRB.Settings.DVDTToken = token; 339 | DRB.Settings.DVDTUrl = tokenUrl; 340 | DRB.Settings.DVDTVersion = data.Version; 341 | DRB.Settings.DVDTContext = true; 342 | 343 | DRB.UI.HideLoading(); 344 | DRB.Logic.CompleteInitialize(); 345 | }) 346 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Xrm.GetServerVersion Error", DRB.Common.GetErrorMessage(xhr)); }); 347 | } else { DRB.UI.ShowError("DVDT Connection Error", "The token from DVDT is not valid"); } 348 | } else { DRB.UI.ShowError("DVDT Connection Error", "Failed to parse the token from DVDT"); } 349 | break; 350 | 351 | case "dvdt_refreshtoken": 352 | var token = message.token; 353 | DRB.Common.RefreshDVDTToken(token); 354 | break; 355 | 356 | case "be_connection": 357 | var token = message.token; 358 | var parsedToken = DRB.Common.ParseJWT(token); 359 | if (DRB.Utilities.HasValue(parsedToken)) { 360 | var tokenUrl = parsedToken.aud; 361 | var tokenExpireDate = parsedToken.exp * 1000; 362 | var now = new Date().getTime(); 363 | if (DRB.Utilities.HasValue(tokenUrl) && tokenExpireDate > now) { 364 | tokenUrl = tokenUrl.replace(/\/$/, ""); // clean url from trailing slash 365 | DRB.UI.ShowLoading("Checking Token Settings..."); 366 | 367 | DRB.Xrm.GetServerVersion(tokenUrl, token) 368 | .done(function (data) { 369 | DRB.Settings.BEToken = token; 370 | DRB.Settings.BEUrl = tokenUrl; 371 | DRB.Settings.BEVersion = data.Version; 372 | DRB.Settings.BEContext = true; 373 | 374 | DRB.UI.HideLoading(); 375 | DRB.Logic.CompleteInitialize(); 376 | }) 377 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Xrm.GetServerVersion Error", DRB.Common.GetErrorMessage(xhr)); }); 378 | } else { DRB.UI.ShowError("BE Connection Error", "The token from Browser Extension is not valid"); } 379 | } else { DRB.UI.ShowError("BE Connection Error", "Failed to parse the token from Browser Extension"); } 380 | break; 381 | 382 | case "be_refreshtoken": 383 | var token = message.token; 384 | DRB.Common.RefreshBEToken(token); 385 | break; 386 | } 387 | }); 388 | // #endregion -------------------------------------------------------------------------------- /js/drb.logic.managefileimagedata.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Logic.ManageFileImageData 2 | /** 3 | * Manage File Image Data - After Table Loaded 4 | * @param {DRB.Models.Table} table Table 5 | */ 6 | DRB.Logic.ManageFileImageData.AfterTableLoaded = function (table) { 7 | DRB.Logic.FillCurrentMetadata(table); // Fill Current Metadata 8 | 9 | var selectedColumns = []; 10 | var fileColumnDropdownName = ""; 11 | var columnAttributeType = ""; 12 | 13 | if (DRB.Metadata.ManageDataType === "managefiledata") { 14 | columnAttributeType = "File"; 15 | fileColumnDropdownName = DRB.DOM.FileColumn.Dropdown.Name; 16 | } 17 | 18 | if (DRB.Metadata.ManageDataType === "manageimagedata") { 19 | columnAttributeType = "Image"; 20 | fileColumnDropdownName = DRB.DOM.ImageColumn.Dropdown.Name; 21 | } 22 | 23 | DRB.Metadata.CurrentColumns.forEach(function (currentColumn) { 24 | if (currentColumn.AttributeType === columnAttributeType) { selectedColumns.push(currentColumn); } 25 | }); 26 | 27 | if (selectedColumns.length === 0) { 28 | DRB.UI.ResetDropdown(DRB.DOM.FileColumn.Dropdown.Id, fileColumnDropdownName); 29 | DRB.Metadata.CurrentNode.data.configuration.fileField = null; 30 | } else { 31 | DRB.UI.FillDropdown(DRB.DOM.FileColumn.Dropdown.Id, fileColumnDropdownName, new DRB.Models.Records(selectedColumns).ToDropdown()); 32 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.fileField)) { 33 | $("#" + DRB.DOM.FileColumn.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.fileField.logicalName).change(); 34 | } 35 | } 36 | 37 | // Fill data.configuration 38 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = { logicalName: table.LogicalName, schemaName: table.SchemaName, label: table.Name, entitySetName: table.EntitySetName }; 39 | } 40 | 41 | /** 42 | * Manage File Image Data - Bind File Column 43 | * @param {string} id Id 44 | */ 45 | DRB.Logic.ManageFileImageData.BindFileColumn = function (id) { 46 | $("#" + id).on("change", function (e) { 47 | var columnName = $(this).val(); 48 | var column = DRB.Utilities.GetRecordById(DRB.Metadata.CurrentColumns, columnName); 49 | if (DRB.Utilities.HasValue(column)) { 50 | DRB.Metadata.CurrentNode.data.configuration.fileField = { logicalName: column.LogicalName, schemaName: column.SchemaName, label: column.Name, type: column.AttributeType, oDataName: column.ODataName }; 51 | if (DRB.Metadata.ManageDataType === "manageimagedata") { 52 | if (column.AdditionalProperties.CanStoreFullImage !== true) { 53 | $("#" + DRB.DOM.FileFullSize.CheckBox.Id).prop('checked', false).change(); 54 | $("#" + DRB.DOM.FileFullSize.CheckBox.Id).prop("disabled", "true"); 55 | } else { 56 | $("#" + DRB.DOM.FileFullSize.CheckBox.Id).prop("disabled", ""); 57 | } 58 | } 59 | } else { 60 | DRB.Metadata.CurrentNode.data.configuration.fileField = null; 61 | if (DRB.Metadata.ManageDataType === "manageimagedata") { $("#" + DRB.DOM.FileFullSize.CheckBox.Id).prop('checked', false).change(); } 62 | } 63 | }); 64 | } 65 | 66 | /** 67 | * Manage File Image Data - Bind File Operation 68 | * @param {string} id Id 69 | */ 70 | DRB.Logic.ManageFileImageData.BindFileOperation = function (id) { 71 | $("#" + id).on("change", function (e) { 72 | var operation = $(this).val(); 73 | DRB.Metadata.CurrentNode.data.configuration.fileOperation = operation; 74 | 75 | switch (operation) { 76 | case "retrieve": 77 | $("#" + DRB.DOM.FileName.Div.Id).hide(); 78 | $("#" + DRB.DOM.FileName.Input.Id).val(""); 79 | if (DRB.Metadata.ManageDataType === "manageimagedata") { $("#" + DRB.DOM.FileFullSize.Div.Id).show(); } 80 | $("#" + DRB.DOM.FileBase64.Div.Id).show(); 81 | $("#" + DRB.DOM.FileContent.Div.Id).hide(); 82 | DRB.Metadata.CurrentNode.data.configuration.fileContent = null; 83 | break; 84 | 85 | case "upload": 86 | $("#" + DRB.DOM.FileName.Div.Id).show(); 87 | if (DRB.Metadata.ManageDataType === "manageimagedata") { 88 | $("#" + DRB.DOM.FileFullSize.Div.Id).hide(); 89 | $("#" + DRB.DOM.FileFullSize.CheckBox.Id).prop('checked', false).change(); 90 | } 91 | $("#" + DRB.DOM.FileBase64.CheckBox.Id).prop('checked', false).change(); 92 | $("#" + DRB.DOM.FileBase64.Div.Id).hide(); 93 | $("#" + DRB.DOM.FileContent.Div.Id).show(); 94 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.fileContent)) { 95 | if (DRB.Metadata.ManageDataType === "manageimagedata") { $("#" + DRB.DOM.FileContent.ShowButton.Id).show(); } 96 | $("#" + DRB.DOM.FileContent.DownloadButton.Id).show(); 97 | $("#" + DRB.DOM.FileContent.RemoveButton.Id).show(); 98 | } else { 99 | if (DRB.Metadata.ManageDataType === "manageimagedata") { $("#" + DRB.DOM.FileContent.ShowButton.Id).hide(); } 100 | $("#" + DRB.DOM.FileContent.DownloadButton.Id).hide(); 101 | $("#" + DRB.DOM.FileContent.RemoveButton.Id).hide(); 102 | } 103 | break; 104 | 105 | case "delete": 106 | $("#" + DRB.DOM.FileName.Div.Id).hide(); 107 | $("#" + DRB.DOM.FileName.Input.Id).val(""); 108 | if (DRB.Metadata.ManageDataType === "manageimagedata") { 109 | $("#" + DRB.DOM.FileFullSize.Div.Id).hide(); 110 | $("#" + DRB.DOM.FileFullSize.CheckBox.Id).prop('checked', false).change(); 111 | } 112 | $("#" + DRB.DOM.FileBase64.CheckBox.Id).prop('checked', false).change(); 113 | $("#" + DRB.DOM.FileBase64.Div.Id).hide(); 114 | $("#" + DRB.DOM.FileContent.Div.Id).hide(); 115 | DRB.Metadata.CurrentNode.data.configuration.fileContent = null; 116 | break; 117 | } 118 | 119 | if (operation === "upload") { $("#" + DRB.DOM.FileName.Div.Id).show(); } 120 | else { 121 | $("#" + DRB.DOM.FileName.Div.Id).hide(); 122 | $("#" + DRB.DOM.FileName.Input.Id).val(""); 123 | } 124 | }); 125 | } 126 | 127 | /** 128 | * Manage File Image Data - Bind File Name 129 | * @param {string} id Id 130 | */ 131 | DRB.Logic.ManageFileImageData.BindFileName = function (id) { 132 | $("#" + id).on("change", function (e) { 133 | var fileName = $(this).val(); 134 | DRB.Metadata.CurrentNode.data.configuration.fileName = fileName; 135 | }); 136 | } 137 | 138 | /** 139 | * Manage File Image Data - Bind File Full Size 140 | * @param {string} id Id 141 | */ 142 | DRB.Logic.ManageFileImageData.BindFileFullSize = function (id) { 143 | $("#" + id).on("change", function (e) { 144 | var fullSizeValue = $(this).is(':checked'); 145 | DRB.Metadata.CurrentNode.data.configuration.fileFullSize = fullSizeValue; 146 | }); 147 | } 148 | 149 | /** 150 | * Manage File Image Data - Bind File Base64 151 | * @param {string} id Id 152 | */ 153 | DRB.Logic.ManageFileImageData.BindFileBase64 = function (id) { 154 | $("#" + id).on("change", function (e) { 155 | var base64Value = $(this).is(':checked'); 156 | DRB.Metadata.CurrentNode.data.configuration.fileBase64 = base64Value; 157 | }); 158 | } 159 | 160 | /** 161 | * * Manage File Image Data - Parse File 162 | * @param {event} e Event 163 | */ 164 | DRB.Logic.ManageFileImageData.ParseFile = function (e) { 165 | var file = e.target.files[0]; 166 | if (!file) { 167 | DRB.UI.ShowError("Load File Error", "Error loading the selected file"); 168 | } else { 169 | if (DRB.Metadata.ManageDataType === "managefiledata" || /\.(jpe?g|png|gif|bmp)$/i.test(file.name)) { 170 | var reader = new FileReader(); 171 | reader.onload = function (e) { 172 | try { 173 | var fileContent = e.target.result; 174 | DRB.Metadata.CurrentNode.data.configuration.fileContent = fileContent.split(",")[1]; 175 | if (DRB.Metadata.ManageDataType === "manageimagedata") { $("#" + DRB.DOM.FileContent.ShowButton.Id).show(); } 176 | $("#" + DRB.DOM.FileContent.DownloadButton.Id).show(); 177 | $("#" + DRB.DOM.FileContent.RemoveButton.Id).show(); 178 | $("#" + DRB.DOM.FileName.Input.Id).val(file.name).change(); // File Name 179 | 180 | } catch (e) { DRB.UI.ShowError("Load File Error", "Failed to parse the selected file"); } 181 | }; 182 | reader.readAsDataURL(file); 183 | } else { 184 | DRB.UI.ShowError("Load File Error", "Supported file extensions: gif, png, bmp, jpg, jpeg"); 185 | } 186 | } 187 | // reset the File Input (necessary if we load the same file again) 188 | $(e.target).val(""); 189 | } 190 | 191 | /** 192 | * Manage File Image Data - Load File 193 | */ 194 | DRB.Logic.ManageFileImageData.LoadFile = function () { 195 | $("#" + DRB.DOM.FileContent.LoadInput.Id).trigger("click"); 196 | } 197 | 198 | /** 199 | * Manage File Image Data - Show File 200 | */ 201 | DRB.Logic.ManageFileImageData.ShowFile = function () { 202 | try { 203 | var imageContent = DRB.Metadata.CurrentNode.data.configuration.fileContent; 204 | var base64Prefix = "data:image/jpeg;base64,"; 205 | var finalImage = base64Prefix + imageContent; 206 | 207 | var showContent = DRB.UI.CreateEmptyDiv("div_showimage", "centercontent"); 208 | showContent.append(DRB.UI.CreateImage("preview", finalImage)); 209 | DRB.UI.Show("Show Image", showContent, "large"); 210 | } catch (e) { 211 | DRB.UI.ShowError("Image Error", "Unable to show the image"); 212 | } 213 | } 214 | 215 | /** 216 | * Manage File Image Data - Download File 217 | */ 218 | DRB.Logic.ManageFileImageData.DownloadFile = function () { 219 | try { 220 | var base64Content = DRB.Metadata.CurrentNode.data.configuration.fileContent; 221 | var byteCharacters = atob(base64Content); 222 | var byteNumbers = new Array(byteCharacters.length); 223 | for (var i = 0; i < byteCharacters.length; i++) { 224 | byteNumbers[i] = byteCharacters.charCodeAt(i); 225 | } 226 | var fileName = "file.bin"; 227 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.fileName)) { fileName = DRB.Metadata.CurrentNode.data.configuration.fileName; } 228 | var fileContent = new Uint8Array(byteNumbers); 229 | var saveFile = new Blob([fileContent], { type: "application/octet-stream" }); 230 | DRB.Utilities.DownloadFile(saveFile, fileName); 231 | if (!DRB.Xrm.IsBEMode()) { URL.revokeObjectURL(saveFile); } 232 | } catch (e) { 233 | DRB.UI.ShowError("Download Error", "Unable to download the file"); 234 | } 235 | } 236 | 237 | /** 238 | * Manage File Image Data - Remove File 239 | */ 240 | DRB.Logic.ManageFileImageData.RemoveFile = function () { 241 | DRB.Metadata.CurrentNode.data.configuration.fileContent = null; 242 | if (DRB.Metadata.ManageDataType === "manageimagedata") { $("#" + DRB.DOM.FileContent.ShowButton.Id).hide(); } 243 | $("#" + DRB.DOM.FileContent.DownloadButton.Id).hide(); 244 | $("#" + DRB.DOM.FileContent.RemoveButton.Id).hide(); 245 | } 246 | 247 | /** 248 | * Manage File Image Data - Bind Table 249 | * @param {string} id Id 250 | */ 251 | DRB.Logic.ManageFileImageData.BindTable = function (id) { 252 | $("#" + id).on("change", function (e) { 253 | var tableLogicalName = $(this).val(); 254 | var table = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, tableLogicalName); 255 | if (DRB.Utilities.HasValue(table)) { 256 | // Fill data.configuration (primaryEntity) 257 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = { logicalName: table.LogicalName, schemaName: table.SchemaName, label: table.Name, entitySetName: table.EntitySetName }; 258 | if (table.ColumnsLoaded === false) { 259 | DRB.UI.ShowLoading("Retrieving Table information...
This is a long-running operation"); 260 | setTimeout(function () { 261 | // retrieve the Entity Fields 262 | DRB.Common.RetrieveTablesDetails([tableLogicalName]) 263 | .done(function () { 264 | DRB.Common.SetTables(arguments, DRB.Metadata.Tables); 265 | DRB.Logic.ManageFileImageData.AfterTableLoaded(table); 266 | DRB.UI.HideLoading(); 267 | }) 268 | .fail(function (xhr) { DRB.UI.ShowError("DRB.Common.RetrieveTablesDetails Error", DRB.Common.GetErrorMessage(xhr)); }); 269 | }, DRB.Settings.TimeoutDelay); 270 | } else { 271 | DRB.Logic.ManageFileImageData.AfterTableLoaded(table); 272 | } 273 | } 274 | }); 275 | } 276 | 277 | /** 278 | * Manage File Data - Start 279 | */ 280 | DRB.Logic.ManageFileImageData.Start = function (requestType) { 281 | DRB.Metadata.ManageDataType = requestType; 282 | // create DOM and bindings 283 | DRB.CustomUI.AddVersion(); 284 | DRB.CustomUI.AddProcess(); 285 | DRB.CustomUI.AddTokenHeader(); 286 | DRB.CustomUI.AddSpacer(); 287 | DRB.CustomUI.AddImpersonate(); 288 | DRB.CustomUI.AddSpacer(); 289 | 290 | // #region Table 291 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.Table.Span.Id, DRB.DOM.Table.Span.Name)); 292 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.Table.Dropdown.Id)); 293 | DRB.UI.FillDropdown(DRB.DOM.Table.Dropdown.Id, DRB.DOM.Table.Dropdown.Name, new DRB.Models.Records(DRB.Metadata.Tables).ToDropdown()); 294 | DRB.Logic.ManageFileImageData.BindTable(DRB.DOM.Table.Dropdown.Id); 295 | // #endregion 296 | 297 | // #region File Column 298 | var divFileColumn = DRB.UI.CreateEmptyDiv(DRB.DOM.FileColumn.Div.Id, DRB.DOM.FileColumn.Div.Class); 299 | var fileColumnSpanName = ""; 300 | var fileColumnDropdownName = ""; 301 | switch (requestType) { 302 | case "managefiledata": 303 | fileColumnSpanName = DRB.DOM.FileColumn.Span.Name; 304 | fileColumnDropdownName = DRB.DOM.FileColumn.Dropdown.Name; 305 | break; 306 | case "manageimagedata": 307 | fileColumnSpanName = DRB.DOM.ImageColumn.Span.Name; 308 | fileColumnDropdownName = DRB.DOM.ImageColumn.Dropdown.Name; 309 | break; 310 | } 311 | divFileColumn.append(DRB.UI.CreateSpan(DRB.DOM.FileColumn.Span.Id, fileColumnSpanName)); 312 | divFileColumn.append(DRB.UI.CreateDropdown(DRB.DOM.FileColumn.Dropdown.Id)); 313 | $("#" + DRB.DOM.ConfigureContent.Id).append(divFileColumn); 314 | DRB.UI.ResetDropdown(DRB.DOM.FileColumn.Dropdown.Id, fileColumnDropdownName); 315 | DRB.Logic.ManageFileImageData.BindFileColumn(DRB.DOM.FileColumn.Dropdown.Id); 316 | // #endregion 317 | 318 | DRB.CustomUI.AddSpacer(); 319 | DRB.CustomUI.AddPrimaryId(); 320 | DRB.CustomUI.AddSpacer(); 321 | 322 | // #region File Operation 323 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateSpan(DRB.DOM.FileOperation.Span.Id, DRB.DOM.FileOperation.Span.Name)); 324 | $("#" + DRB.DOM.ConfigureContent.Id).append(DRB.UI.CreateDropdown(DRB.DOM.FileOperation.Dropdown.Id)); 325 | DRB.UI.FillDropdown(DRB.DOM.FileOperation.Dropdown.Id, DRB.DOM.FileOperation.Dropdown.Name, new DRB.Models.Records(DRB.Settings.OptionsManageFile).ToDropdown()); 326 | DRB.Logic.ManageFileImageData.BindFileOperation(DRB.DOM.FileOperation.Dropdown.Id); 327 | // #endregion 328 | 329 | // #region Full Size 330 | if (requestType === "manageimagedata") { 331 | var divFileFullSize = DRB.UI.CreateEmptyDiv(DRB.DOM.FileFullSize.Div.Id, DRB.DOM.FileFullSize.Div.Class); 332 | divFileFullSize.append(DRB.UI.CreateCheckbox(DRB.DOM.FileFullSize.CheckBox.Id, "", "", false)); 333 | divFileFullSize.append(DRB.UI.CreateSpan(DRB.DOM.FileFullSize.Span.Id, DRB.DOM.FileFullSize.Span.Name)); 334 | $("#" + DRB.DOM.ConfigureContent.Id).append(divFileFullSize); 335 | DRB.Logic.ManageFileImageData.BindFileFullSize(DRB.DOM.FileFullSize.CheckBox.Id); 336 | $("#" + DRB.DOM.FileFullSize.Div.Id).hide(); 337 | } 338 | // #endregion 339 | 340 | // #region Base64 341 | var divFileBase64 = DRB.UI.CreateEmptyDiv(DRB.DOM.FileBase64.Div.Id, DRB.DOM.FileBase64.Div.Class); 342 | divFileBase64.append(DRB.UI.CreateCheckbox(DRB.DOM.FileBase64.CheckBox.Id, "", "", false)); 343 | divFileBase64.append(DRB.UI.CreateSpan(DRB.DOM.FileBase64.Span.Id, DRB.DOM.FileBase64.Span.Name)); 344 | $("#" + DRB.DOM.ConfigureContent.Id).append(divFileBase64); 345 | DRB.Logic.ManageFileImageData.BindFileBase64(DRB.DOM.FileBase64.CheckBox.Id); 346 | $("#" + DRB.DOM.FileBase64.Div.Id).hide(); 347 | // #endregion 348 | 349 | DRB.CustomUI.AddSpacer(); 350 | 351 | // #region File Name 352 | var divFileName = DRB.UI.CreateEmptyDiv(DRB.DOM.FileName.Div.Id, DRB.DOM.FileName.Div.Class); 353 | divFileName.append(DRB.UI.CreateSpan(DRB.DOM.FileName.Span.Id, DRB.DOM.FileName.Span.Name)); 354 | divFileName.append(DRB.UI.CreateInputString(DRB.DOM.FileName.Input.Id, 100, DRB.DOM.FileName.Span.Name)); 355 | $("#" + DRB.DOM.ConfigureContent.Id).append(divFileName); 356 | DRB.Common.BindFileName(DRB.DOM.FileName.Input.Id); 357 | DRB.Logic.ManageFileImageData.BindFileName(DRB.DOM.FileName.Input.Id); 358 | $("#" + DRB.DOM.FileName.Div.Id).hide(); 359 | // #endregion 360 | 361 | DRB.CustomUI.AddSpacer(); 362 | 363 | // #region File Content 364 | var divFileContent = DRB.UI.CreateEmptyDiv(DRB.DOM.FileContent.Div.Id); 365 | $("#" + DRB.DOM.ConfigureContent.Id).append(divFileContent); 366 | divFileContent.append(DRB.UI.CreateInputFile(DRB.DOM.FileContent.LoadInput.Id, true, DRB.Logic.ManageFileImageData.ParseFile)); 367 | divFileContent.append(DRB.UI.CreateButton(DRB.DOM.FileContent.LoadButton.Id, DRB.DOM.FileContent.LoadButton.Name, DRB.DOM.FileContent.LoadButton.Class, DRB.Logic.ManageFileImageData.LoadFile)); 368 | if (requestType === "manageimagedata") { 369 | divFileContent.append(DRB.UI.CreateButton(DRB.DOM.FileContent.ShowButton.Id, DRB.DOM.FileContent.ShowButton.Name, DRB.DOM.FileContent.ShowButton.Class, DRB.Logic.ManageFileImageData.ShowFile)); 370 | $("#" + DRB.DOM.FileContent.ShowButton.Id).hide(); 371 | } 372 | divFileContent.append(DRB.UI.CreateButton(DRB.DOM.FileContent.DownloadButton.Id, DRB.DOM.FileContent.DownloadButton.Name, DRB.DOM.FileContent.DownloadButton.Class, DRB.Logic.ManageFileImageData.DownloadFile)); 373 | $("#" + DRB.DOM.FileContent.RemoveButton.Id).hide(); 374 | divFileContent.append(DRB.UI.CreateButton(DRB.DOM.FileContent.RemoveButton.Id, DRB.DOM.FileContent.RemoveButton.Name, DRB.DOM.FileContent.RemoveButton.Class, DRB.Logic.ManageFileImageData.RemoveFile)); 375 | $("#" + DRB.DOM.FileContent.RemoveButton.Id).hide(); 376 | $("#" + DRB.DOM.FileContent.Div.Id).hide(); 377 | // #endregion 378 | 379 | // #region Triggers 380 | // events triggered after due to DOM connections to other elements 381 | 382 | // Table 383 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.primaryEntity)) { 384 | // check if the table exists 385 | var checkTable = DRB.Utilities.GetRecordById(DRB.Metadata.Tables, DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName); 386 | if (!DRB.Utilities.HasValue(checkTable)) { 387 | // if the table doesn't exist reset the relevant values 388 | DRB.Metadata.CurrentNode.data.configuration.primaryEntity = null; 389 | DRB.Metadata.CurrentNode.data.configuration.primaryId = ""; 390 | } else { 391 | // trigger change with table logical name 392 | $("#" + DRB.DOM.Table.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.primaryEntity.logicalName).change(); 393 | } 394 | } 395 | // File Operation 396 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.fileOperation)) { 397 | $("#" + DRB.DOM.FileOperation.Dropdown.Id).val(DRB.Metadata.CurrentNode.data.configuration.fileOperation).change(); 398 | } 399 | 400 | // File Name 401 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.fileName)) { 402 | $("#" + DRB.DOM.FileName.Input.Id).val(DRB.Metadata.CurrentNode.data.configuration.fileName).change(); 403 | } 404 | 405 | // File Full Size 406 | if (requestType === "manageimagedata") { 407 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.fileFullSize)) { 408 | $("#" + DRB.DOM.FileFullSize.CheckBox.Id).prop('checked', DRB.Metadata.CurrentNode.data.configuration.fileFullSize).change(); 409 | } 410 | } 411 | 412 | // File Base64 413 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.fileBase64)) { 414 | $("#" + DRB.DOM.FileBase64.CheckBox.Id).prop('checked', DRB.Metadata.CurrentNode.data.configuration.fileBase64).change(); 415 | } 416 | 417 | // File Content 418 | if (DRB.Utilities.HasValue(DRB.Metadata.CurrentNode.data.configuration.fileContent)) { 419 | if (requestType === "manageimagedata") { $("#" + DRB.DOM.FileContent.ShowButton.Id).show(); } 420 | $("#" + DRB.DOM.FileContent.DownloadButton.Id).show(); 421 | $("#" + DRB.DOM.FileContent.RemoveButton.Id).show(); 422 | } 423 | // #endregion 424 | } 425 | // #endregion -------------------------------------------------------------------------------- /js/drb.models.js: -------------------------------------------------------------------------------- 1 | // #region DRB.Models 2 | /** 3 | * Models - Dropdown Option 4 | * @param {any} value Value 5 | * @param {string} label Label 6 | * @param {string} subText Sub Text 7 | * @param {string} subText2 Sub Text 2 8 | */ 9 | DRB.Models.DropdownOption = function (value, label, subText, subText2) { 10 | this.Value = value; 11 | this.Label = label; 12 | this.SubText = subText; 13 | this.SubText2 = subText2; 14 | } 15 | 16 | /** 17 | * Models - Records 18 | * @param {any} records Records 19 | */ 20 | DRB.Models.Records = function (records) { 21 | this.Records = records; 22 | 23 | this.ToDropdown = function () { 24 | var recordsDropdown = []; 25 | this.Records.forEach(function (record) { recordsDropdown.push(record.ToDropdownOption()); }); 26 | return recordsDropdown; 27 | } 28 | } 29 | 30 | /** 31 | * Models - Id Value 32 | * @param {any} id Id 33 | * @param {any} value Value 34 | */ 35 | DRB.Models.IdValue = function (id, value) { 36 | this.Id = id; 37 | this.Value = value; 38 | 39 | this.ToDropdownOption = function () { return new DRB.Models.DropdownOption(this.Id, this.Value); } 40 | } 41 | 42 | /** 43 | * Models - Option Set Value 44 | * @param {any} value Value 45 | * @param {string} label Label 46 | */ 47 | DRB.Models.OptionSetValue = function (value, label) { 48 | this.Value = value; 49 | this.Label = label; 50 | 51 | this.ToDropdownOption = function () { 52 | return new DRB.Models.DropdownOption(this.Value, this.Label, this.Value); 53 | } 54 | } 55 | 56 | /** 57 | * Models - Relationship 58 | * @param {string} schemaName Schema Name 59 | * @param {string} type Type 60 | * @param {string} sourceTable Source Table 61 | * @param {string} targetTable Target Table 62 | * @param {string} navigationProperty Navigation Property 63 | * @param {string} navigationAttribute Navigation Attribute 64 | */ 65 | DRB.Models.Relationship = function (schemaName, type, sourceTable, targetTable, navigationProperty, navigationAttribute, isHierarchical) { 66 | this.Id = schemaName; 67 | this.Name = schemaName; 68 | this.SchemaName = schemaName; 69 | this.Type = type; 70 | this.SourceTable = sourceTable; 71 | this.TargetTable = targetTable; 72 | this.TargetTableName = ""; 73 | this.NavigationProperty = navigationProperty; 74 | this.NavigationAttribute = navigationAttribute; 75 | this.NavigationAttributeName = ""; 76 | this.IsHierarchical = isHierarchical; 77 | 78 | this.Columns = []; 79 | this.ToDropdownOption = function () { 80 | var subText = "Table: " + this.TargetTableName + " (" + this.TargetTable + ")"; 81 | switch (this.Type) { 82 | case "OneToMany": 83 | subText += " - Target: " + this.NavigationAttributeName + " (" + this.NavigationAttribute + ")"; break; 84 | case "ManyToOne": 85 | subText += " - Source: " + this.NavigationAttributeName + " (" + this.NavigationAttribute + ")"; break; 86 | } 87 | return new DRB.Models.DropdownOption(this.Id, this.SchemaName, subText); 88 | } 89 | } 90 | 91 | /** 92 | * Models - Relationship Lookup 93 | * @param {DRB.Models.Relationship} relationship Relationship 94 | */ 95 | DRB.Models.RelationshipLookup = function (relationship) { 96 | this.Id = relationship.Id; 97 | this.Name = relationship.Name; 98 | this.SchemaName = relationship.SchemaName; 99 | this.Type = relationship.Type; 100 | this.SourceTable = relationship.SourceTable; 101 | this.TargetTable = relationship.TargetTable; 102 | this.TargetTableName = relationship.TargetTableName; 103 | this.NavigationProperty = relationship.NavigationProperty; 104 | this.NavigationAttribute = relationship.NavigationAttribute; 105 | this.NavigationAttributeName = relationship.NavigationAttributeName; 106 | this.IsHierarchical = relationship.IsHierarchical; 107 | 108 | this.Columns = relationship.Columns; 109 | this.ToDropdownOption = function () { 110 | var subText = this.NavigationAttribute + " - Table: " + this.TargetTableName + " (" + this.TargetTable + ")"; 111 | return new DRB.Models.DropdownOption(this.Id, this.NavigationAttributeName, subText); 112 | } 113 | } 114 | 115 | /** 116 | * Models - Simple Relationship 117 | * @param {string} schemaName Schema Name 118 | * @param {string} type Type 119 | * @param {string} sourceTable Source Table 120 | * @param {string} targetTable Target Table 121 | * @param {string} navigationProperty Navigation Property 122 | * @param {string} navigationAttribute Navigation Attribute 123 | * @param {string} navigationAttributeName Navigation Attribute Name 124 | */ 125 | DRB.Models.SimpleRelationship = function (schemaName, type, sourceTable, targetTable, navigationAttribute, navigationAttributeName) { 126 | this.Id = schemaName; 127 | this.Name = schemaName; 128 | this.SchemaName = schemaName; 129 | this.Type = type; 130 | this.SourceTable = sourceTable; 131 | this.TargetTable = targetTable; 132 | this.NavigationAttribute = navigationAttribute; 133 | this.NavigationAttributeName = navigationAttributeName; 134 | 135 | if (!DRB.Utilities.HasValue(this.NavigationAttribute)) { this.NavigationAttribute = ""; } 136 | 137 | this.Columns = []; 138 | this.ToDropdownOption = function () { 139 | var subText = ""; 140 | var subText2 = ""; 141 | switch (this.Type) { 142 | case "OneToMany": 143 | subText = "(1:N) One To Many Relationships"; 144 | subText2 = "(1:N) Target: " + this.NavigationAttributeName + " (" + this.NavigationAttribute + ")"; 145 | break; 146 | case "ManyToOne": 147 | subText = "(N:1) Many To One Relationships"; 148 | subText2 = "(N:1) Source: " + this.NavigationAttributeName + " (" + this.NavigationAttribute + ")"; 149 | break; 150 | case "ManyToMany": 151 | subText = "(N:N) Many To Many Relationships"; 152 | subText2 = "(N:N)"; 153 | break; 154 | } 155 | return new DRB.Models.DropdownOption(this.Id, this.SchemaName, subText, subText2); 156 | } 157 | } 158 | 159 | /** 160 | * Models - Relationship Column 161 | * @param {string} relationshipSchemaName Relationship Schema Name 162 | * @param {string} relationshipType Relationship Type 163 | * @param {string} relationshipNavigationProperty Relationship Navigation Property 164 | * @param {string} relationshipNavigationAttribute Relationship Navigation Attribute 165 | * @param {string} relationshipNavigationAttributeName Relationship Navigation Attribute Name 166 | * @param {string} targetTableLogicalName Target Table Logical Name 167 | * @param {string} targetTableName Target Table Name 168 | * @param {string} columnLogicalName Column Logical Name 169 | * @param {string} columnName Column Name 170 | * @param {string} columnSchemaName Column Schema Name 171 | * @param {string} columnAttributeType Column Attribute Type 172 | * @param {string} columnIsPrimaryIdAttribute Column Is Primary Id Attribute 173 | * @param {string} columnIsPrimaryNameAttribute Column Is Primary Name Attribute 174 | * @param {string} columnRequiredLevel Column Required Level 175 | * @param {boolean} columnIsValidForRead Column Is Valid For Read 176 | * @param {boolean} columnIsValidForCreate Column Is Valid For Create 177 | * @param {boolean} columnIsValidForUpdate Column Is Valid For Update 178 | */ 179 | DRB.Models.RelationshipColumn = function (relationshipSchemaName, relationshipType, relationshipNavigationProperty, 180 | relationshipNavigationAttribute, relationshipNavigationAttributeName, targetTableLogicalName, targetTableName, 181 | columnLogicalName, columnName, columnSchemaName, columnAttributeType, columnIsPrimaryIdAttribute, columnIsPrimaryNameAttribute, 182 | columnRequiredLevel, columnIsValidForRead, columnIsValidForCreate, columnIsValidForUpdate, columnAdditionalProperties) { 183 | this.Id = relationshipSchemaName + "|" + columnLogicalName; 184 | this.RelationshipSchemaName = relationshipSchemaName; 185 | this.RelationshipType = relationshipType; 186 | this.RelationshipNavigationProperty = relationshipNavigationProperty; 187 | this.RelationshipNavigationAttribute = relationshipNavigationAttribute; 188 | this.RelationshipNavigationAttributeName = relationshipNavigationAttributeName; 189 | this.TargetTableLogicalName = targetTableLogicalName; 190 | this.TargetTableName = targetTableName; 191 | this.ColumnLogicalName = columnLogicalName; 192 | this.Name = columnName; 193 | this.ColumnSchemaName = columnSchemaName; 194 | this.ColumnAttributeType = columnAttributeType; 195 | this.ColumnIsPrimaryIdAttribute = columnIsPrimaryIdAttribute; 196 | this.ColumnIsPrimaryNameAttribute = columnIsPrimaryNameAttribute; 197 | this.ColumnRequiredLevel = columnRequiredLevel; 198 | this.ColumnIsValidForRead = columnIsValidForRead; 199 | this.ColumnIsValidForCreate = columnIsValidForCreate; 200 | this.ColumnIsValidForUpdate = columnIsValidForUpdate; 201 | this.ColumnAdditionalProperties = columnAdditionalProperties; 202 | 203 | this.ToDropdownOption = function () { 204 | 205 | 206 | 207 | // subText renaming 208 | var renamedAttributeType = this.ColumnAttributeType; 209 | switch (this.ColumnAttributeType) { 210 | case "Uniqueidentifier": renamedAttributeType = "Guid"; break; 211 | case "Picklist": renamedAttributeType = "Choice"; break; 212 | case "MultiPicklist": renamedAttributeType = "Choices"; break; 213 | case "DateTime": renamedAttributeType = "Date Time"; break; 214 | case "Double": renamedAttributeType = "Float"; break; 215 | case "Integer": renamedAttributeType = "Whole Number"; break; 216 | case "Memo": renamedAttributeType = "Multiline Text"; break; 217 | case "String": renamedAttributeType = "Text"; break; 218 | case "Money": renamedAttributeType = "Currency"; break; 219 | case "BigInt": renamedAttributeType = "Big Integer"; break; 220 | case "EntityName": renamedAttributeType = "Entity Name"; break; 221 | case "ManagedProperty": renamedAttributeType = "Managed Property"; break; 222 | } 223 | if (this.AttributeType === "Lookup" && this.AdditionalProperties.IsPolymorphic === true) { renamedAttributeType = "Polymorphic Lookup"; } 224 | 225 | var subText = this.ColumnLogicalName + " (" + renamedAttributeType + ")"; 226 | if (this.ColumnRequiredLevel === "Recommended") { subText += " +"; } 227 | if (this.ColumnRequiredLevel === "ApplicationRequired" || this.ColumnRequiredLevel === "SystemRequired") { subText += " *"; } 228 | if (this.ColumnIsPrimaryNameAttribute === true) { subText += " (Primary Column)"; } 229 | if (this.ColumnAttributeType === "Image" && this.ColumnAdditionalProperties.CanStoreFullImage === true) { subText += " (Can Store Full Image)"; } 230 | if (this.ColumnAdditionalProperties.SourceType === 1) { subText += " (Calculated)"; } 231 | if (this.ColumnAdditionalProperties.SourceType === 2) { subText += " (Rollup)"; } 232 | 233 | var subText2 = "Relationship: " + this.RelationshipSchemaName + " - Table: " + this.TargetTableName + " (" + this.TargetTableLogicalName + ")"; 234 | switch (this.RelationshipType) { 235 | case "OneToMany": 236 | subText2 += " - Target: " + this.RelationshipNavigationAttributeName + " (" + this.RelationshipNavigationAttribute + ")"; break; 237 | case "ManyToOne": 238 | subText2 += " - Source: " + this.RelationshipNavigationAttributeName + " (" + this.RelationshipNavigationAttribute + ")"; break; 239 | } 240 | return new DRB.Models.DropdownOption(this.Id, this.Name, subText2, subText); 241 | } 242 | } 243 | 244 | /** 245 | * Models - Column 246 | * @param {string} logicalName Logical Name 247 | * @param {string} name Name 248 | * @param {string} schemaName Schema Name 249 | * @param {string} attributeType Attribute Type 250 | * @param {boolean} isValidForCreate Is Valid For Read 251 | * @param {boolean} isValidForCreate Is Valid For Create 252 | * @param {boolean} isValidForUpdate Is Valid For Update 253 | * @param {any} additionalProperties Additional Properties 254 | */ 255 | DRB.Models.Column = function (logicalName, name, schemaName, attributeType, isPrimaryIdAttribute, isPrimaryNameAttribute, requiredLevel, isValidForRead, isValidForCreate, isValidForUpdate, additionalProperties) { 256 | this.Id = logicalName; 257 | this.LogicalName = logicalName; 258 | this.Name = name; 259 | this.SchemaName = schemaName; 260 | this.AttributeType = attributeType; 261 | this.IsPrimaryIdAttribute = isPrimaryIdAttribute; 262 | this.IsPrimaryNameAttribute = isPrimaryNameAttribute; 263 | this.RequiredLevel = requiredLevel; 264 | this.IsValidForRead = isValidForRead; 265 | this.IsValidForCreate = isValidForCreate; 266 | this.IsValidForUpdate = isValidForUpdate; 267 | this.IsValidForFilter = true; 268 | this.IsValidForOrder = true; 269 | this.AdditionalProperties = additionalProperties; 270 | 271 | // additional properties 272 | this.ODataName = logicalName; 273 | this.AttributeOf = null; 274 | this.OptionValues = null; 275 | 276 | // if column is not valid for read it can't be used for filter or order 277 | if (this.IsValidForRead === false) { 278 | this.IsValidForFilter = false; 279 | this.IsValidForOrder = false; 280 | } 281 | 282 | // check attribute type for setting some specific properties 283 | switch (attributeType) { 284 | case "Lookup": 285 | case "Customer": 286 | case "Owner": 287 | this.ODataName = "_" + logicalName + "_value"; 288 | break; 289 | 290 | case "Image": 291 | case "File": 292 | this.IsValidForFilter = false; 293 | this.IsValidForOrder = false; 294 | break; 295 | 296 | case "ManagedProperty": 297 | this.OptionValues = []; 298 | this.OptionValues.push(new DRB.Models.OptionSetValue(false, "False")); 299 | this.OptionValues.push(new DRB.Models.OptionSetValue(true, "True")); 300 | break; 301 | } 302 | 303 | this.ToDropdownOption = function () { 304 | // subText renaming 305 | var renamedAttributeType = this.AttributeType; 306 | switch (this.AttributeType) { 307 | case "Uniqueidentifier": renamedAttributeType = "Guid"; break; 308 | case "Picklist": renamedAttributeType = "Choice"; break; 309 | case "MultiPicklist": renamedAttributeType = "Choices"; break; 310 | case "DateTime": renamedAttributeType = "Date Time"; break; 311 | case "Double": renamedAttributeType = "Float"; break; 312 | case "Integer": renamedAttributeType = "Whole Number"; break; 313 | case "Memo": renamedAttributeType = "Multiline Text"; break; 314 | case "String": renamedAttributeType = "Text"; break; 315 | case "Money": renamedAttributeType = "Currency"; break; 316 | case "BigInt": renamedAttributeType = "Big Integer"; break; 317 | case "EntityName": renamedAttributeType = "Entity Name"; break; 318 | case "ManagedProperty": renamedAttributeType = "Managed Property"; break; 319 | } 320 | 321 | if (this.AttributeType === "Lookup" && this.AdditionalProperties.IsPolymorphic === true) { renamedAttributeType = "Polymorphic Lookup"; } 322 | 323 | var subText = this.LogicalName + " (" + renamedAttributeType + ")"; 324 | if (this.RequiredLevel === "Recommended") { subText += " +"; } 325 | if (this.RequiredLevel === "ApplicationRequired" || this.RequiredLevel === "SystemRequired") { subText += " *"; } 326 | if (this.IsPrimaryNameAttribute === true) { subText += " (Primary Column)"; } 327 | if (this.AttributeType === "Image" && this.AdditionalProperties.CanStoreFullImage === true) { subText += " (Can Store Full Image)"; } 328 | if (this.AdditionalProperties.SourceType === 1) { subText += " (Calculated)"; } 329 | if (this.AdditionalProperties.SourceType === 2) { subText += " (Rollup)"; } 330 | return new DRB.Models.DropdownOption(this.Id, this.Name, subText); 331 | } 332 | } 333 | 334 | /** 335 | * Models - Alternate Key 336 | * @param {string} logicalName Logical Name 337 | * @param {string} name Name 338 | * @param {string} schemaName Schema Name 339 | * @param {string} keyAttributes Key Attributes 340 | * 341 | */ 342 | DRB.Models.AlternateKey = function (logicalName, name, schemaName, keyAttributes) { 343 | this.Id = logicalName; 344 | this.Name = name; 345 | this.LogicalName = logicalName; 346 | this.SchemaName = schemaName; 347 | this.KeyAttributes = keyAttributes; 348 | 349 | this.ToDropdownOption = function () { return new DRB.Models.DropdownOption(this.Id, this.Name, this.LogicalName); } 350 | } 351 | 352 | /** 353 | * Models - Table 354 | * @param {string} logicalName Logical Name 355 | * @param {string} name Name 356 | * @param {string} schemaName Schema Name 357 | * @param {string} entitySetName EtitySet Name 358 | * @param {string} primaryIdAttribute Primary Id Attribute 359 | * @param {string} primaryNameAttribute Primary Name Attribute 360 | * @param {number} objectTypeCode Object Type Code 361 | */ 362 | DRB.Models.Table = function (logicalName, name, schemaName, entitySetName, primaryIdAttribute, primaryNameAttribute, objectTypeCode, isActivity, externalName, externalCollectionName) { 363 | this.Id = logicalName; 364 | this.Name = name; 365 | this.LogicalName = logicalName; 366 | this.SchemaName = schemaName; 367 | this.EntitySetName = entitySetName; 368 | this.PrimaryIdAttribute = primaryIdAttribute; 369 | this.PrimaryNameAttribute = primaryNameAttribute; 370 | this.ObjectTypeCode = objectTypeCode; 371 | this.IsActivity = isActivity; 372 | this.IsVirtual = false; 373 | if (DRB.Utilities.HasValue(externalName) && DRB.Utilities.HasValue(externalCollectionName)) { this.IsVirtual = true; } 374 | // additional properties 375 | this.Columns = []; 376 | this.OneToManyRelationships = []; 377 | this.ManyToOneRelationships = []; 378 | this.ManyToManyRelationships = []; 379 | this.AlternateKeys = []; 380 | 381 | this.SystemViews = []; 382 | this.PersonalViews = []; 383 | this.HasHierarchy = false; 384 | 385 | this.ColumnsLoaded = false; 386 | this.RelationshipsLoaded = false; 387 | this.AlternateKeysLoaded = false; 388 | this.SystemViewsLoaded = false; 389 | this.PersonalViewsLoaded = false; 390 | 391 | var subText = this.LogicalName; 392 | if (this.IsActivity) { subText += " (Activity)"; } 393 | if (this.IsVirtual) { subText += " (Virtual)"; } 394 | this.ToDropdownOption = function () { return new DRB.Models.DropdownOption(this.Id, this.Name, subText); } 395 | } 396 | 397 | /** 398 | * Models - User 399 | * @param {string} id Id 400 | * @param {string} name Name 401 | * @param {string} aadObjectId AAD Object Id 402 | */ 403 | DRB.Models.User = function (id, name, aadObjectId) { 404 | this.Id = id; 405 | this.Name = name; 406 | this.AADObjectId = aadObjectId; 407 | } 408 | 409 | /** 410 | * Models - System View 411 | * @param {string} id Id 412 | * @param {string} name Name 413 | * @param {string} tableLogicalName Table Logical Name 414 | * @param {bool} isDefault Is Default 415 | * @param {string} layoutXml Layout XML 416 | */ 417 | DRB.Models.SystemView = function (id, name, tableLogicalName, isDefault, layoutXml) { 418 | this.Id = id; 419 | this.Name = name; 420 | this.TableLogicalName = tableLogicalName; 421 | this.IsDefault = isDefault; 422 | this.LayoutXml = layoutXml; 423 | 424 | this.ToDropdownOption = function () { return new DRB.Models.DropdownOption(this.Id, this.Name, this.TableLogicalName); } 425 | } 426 | 427 | /** 428 | * Models - Personal View 429 | * @param {string} id Id 430 | * @param {string} name Name 431 | * @param {string} tableLogicalName Table Logical Name 432 | * @param {string} layoutXml Layout XML 433 | */ 434 | DRB.Models.PersonalView = function (id, name, tableLogicalName, layoutXml) { 435 | this.Id = id; 436 | this.Name = name; 437 | this.TableLogicalName = tableLogicalName; 438 | this.LayoutXml = layoutXml; 439 | 440 | this.ToDropdownOption = function () { return new DRB.Models.DropdownOption(this.Id, this.Name, this.TableLogicalName); } 441 | } 442 | 443 | /** 444 | * Models - Dataverse Execute 445 | * @param {string} name Name 446 | * @param {boolean} isBound Is Bound 447 | * @param {string} logicalName Logical Name 448 | * @param {boolean} isCollectionBound Is Collection Bound 449 | * @param {boolean} isCustom Is Custom 450 | * @param {boolean} hasReturnType Has Return Type 451 | * @param {string} returnType Return Type 452 | * @param {boolean} returnOptional Return Optional 453 | * @param {DRB.Models.DataverseParameter[]} parameters Parameters 454 | */ 455 | DRB.Models.DataverseExecute = function (type, id, name, isBound, logicalName, isCollectionBound, isFunction, hasReturnType, returnType, parameters) { 456 | this.Type = type; 457 | this.Id = id; 458 | this.Name = name; 459 | this.IsBound = isBound; 460 | this.LogicalName = logicalName; 461 | this.IsCollectionBound = isCollectionBound; 462 | this.IsFunction = isFunction; 463 | this.HasReturnType = hasReturnType; 464 | this.ReturnType = returnType; 465 | this.Parameters = parameters; 466 | this.Properties = []; 467 | var subText = ""; 468 | if (this.Id !== this.Name) { subText = this.Id; } 469 | 470 | if (this.IsCollectionBound === true) { 471 | if (subText !== "") { subText += " "; } 472 | subText += "(Collection Bound)"; 473 | } 474 | 475 | if (this.Type === "CustomAPI" && this.IsFunction === true) { 476 | if (subText !== "") { subText += " "; } 477 | subText += "(Function)"; 478 | } 479 | this.ToDropdownOption = function () { return new DRB.Models.DropdownOption(this.Id, this.Name, subText); } 480 | } 481 | 482 | /** 483 | * Models - Dataverse Parameter 484 | * @param {string} name Name 485 | * @param {string} type Type 486 | * @param {boolean} optional Optional 487 | */ 488 | DRB.Models.DataverseParameter = function (name, type, optional, position, binding) { 489 | this.Id = name; 490 | this.Name = name; 491 | this.Type = type; 492 | this.Optional = optional; 493 | this.Position = position; 494 | this.Binding = binding; 495 | } 496 | 497 | /** 498 | * Models - Dataverse Property 499 | * @param {string} name Name 500 | * @param {string} type Type 501 | */ 502 | DRB.Models.DataverseProperty = function (name, type, position, binding) { 503 | this.Id = name; 504 | this.Name = name; 505 | this.Type = type; 506 | this.Position = position; 507 | this.Binding = binding; 508 | } 509 | 510 | /** 511 | * Models - Dataverse Complex Type 512 | * @param {string} name Name 513 | * @param {DRB.Models.DataverseProperty[]} properties Properties 514 | */ 515 | DRB.Models.DataverseComplexType = function (name, properties) { 516 | this.Id = name; 517 | this.Name = name; 518 | this.Properties = properties; 519 | } 520 | 521 | /** 522 | * Models - Dataverse Member 523 | * @param {string} name Name 524 | * @param {string} value Value 525 | */ 526 | DRB.Models.DataverseMember = function (name, value) { 527 | this.Id = value; 528 | this.Name = name; 529 | this.Value = value; 530 | 531 | this.ToDropdownOption = function () { return new DRB.Models.DropdownOption(this.Id, this.Name, this.Value); } 532 | } 533 | 534 | /** 535 | * Models - Dataverse Enum Type 536 | * @param {string} name Name 537 | * @param {DRB.Models.DataverseMember[]} members Members 538 | */ 539 | DRB.Models.DataverseEnumType = function (name, isFlags, members) { 540 | this.Id = name; 541 | this.Name = name; 542 | this.IsFlags = isFlags; 543 | this.Members = members; 544 | } 545 | 546 | /** 547 | * Models - Dataverse Table 548 | * @param {string} logicalName Logical Name 549 | * @param {string} name Name 550 | * @param {string} schemaName Schema Name 551 | * @param {string} entitySetName EtitySet Name 552 | * @param {string} primaryIdAttribute Primary Id Attribute 553 | * @param {string} primaryNameAttribute Primary Name Attribute 554 | * @param {number} objectTypeCode Object Type Code 555 | */ 556 | DRB.Models.DataverseTable = function (logicalName, name, schemaName, entitySetName, primaryIdAttribute, primaryNameAttribute, objectTypeCode) { 557 | this.Id = logicalName; 558 | this.Name = name; 559 | this.LogicalName = logicalName; 560 | this.SchemaName = schemaName; 561 | this.EntitySetName = entitySetName; 562 | this.PrimaryIdAttribute = primaryIdAttribute; 563 | this.PrimaryNameAttribute = primaryNameAttribute; 564 | this.ObjectTypeCode = objectTypeCode; 565 | 566 | // additional properties 567 | this.DataverseExecutes = []; 568 | 569 | this.ToDropdownOption = function () { return new DRB.Models.DropdownOption(this.Id, this.Name, this.LogicalName); } 570 | } 571 | // #endregion --------------------------------------------------------------------------------