Skip to content

Commit

Permalink
Initial commit of local source
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron Matus authored and Byron Matus committed Aug 19, 2021
1 parent 18e4a14 commit 23f8382
Show file tree
Hide file tree
Showing 9 changed files with 357 additions and 0 deletions.
1 change: 1 addition & 0 deletions assets/micromodal.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

87 changes: 87 additions & 0 deletions background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
console.log('hi')
browser.contextMenus.create({
id: 'showNames',
title: 'Show Control Names',
})
browser.contextMenus.create({
id: 'removeNames',
title: 'Hide Control Names',
})
browser.contextMenus.create({
id: 'retrieveRecord',
title: 'Retrieve Current Record',
})
browser.contextMenus.create({
id: 'unlockFields',
title: 'Unlock All Fields (Deprecated)',
})
browser.contextMenus.create({
id: 'showAllControls',
title: 'Show All Controls (Deprecated)',
})
browser.contextMenus.create({
id: 'getUpdateCode',
title: 'Get Update Code',
})
browser.contextMenus.onClicked.addListener((info, tab) => {
console.log('Menu clicked')
switch (info.menuItemId) {
case 'showNames':
showNames(tab.id)
break
case 'retrieveRecord':
retrieveRecord(tab.id)
break
case 'removeNames':
removeNames(tab.id)
break
case 'unlockFields':
unlockFields(tab.id)
break
case 'showAllControls':
showControls(tab.id)
break
case 'getUpdateCode':
getUpdateCode(tab.id)
break
}

})

function showNames(tabId) {
//console.log('tabId', tabId)
browser.tabs.executeScript(tabId, {
file: 'getFieldNames.js'
})
}
function removeNames(tabId) {
//console.log('tabId', tabId)
browser.tabs.executeScript(tabId, {
file: 'removeFieldNames.js'
})
}
function retrieveRecord(tabId) {
//console.log('tabId', tabId)
browser.tabs.executeScript(tabId, {
file: 'retrieveRecord.js'
})
}
function unlockFields(tabId) {
//console.log('tabId', tabId)
browser.tabs.executeScript(tabId, {
file: 'unlockFields.js'
})
}
function showControls(tabId) {
//console.log('tabId', tabId)
browser.tabs.executeScript(tabId, {
file: 'showControls.js'
})
}
function getUpdateCode(tabId) {
//console.log('tabId', tabId)
browser.tabs.executeScript(tabId, {
file: 'getUpdateCode.js'
})
}

16 changes: 16 additions & 0 deletions getFieldNames.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
console.log('Getting field names...')
var fieldLables = document.querySelectorAll('label[id*="field-label"')
//console.log(fieldLables)
fieldLables.forEach( function (l) {
// name = string in between the third last dash (-) and second last dash from element id
let idPieces = l.id.split('-')
let fieldName = idPieces[idPieces.length - 3]
let newEl = document.createElement('span')
let newContent = document.createTextNode(' [' + fieldName + ']')
newEl.className = 'D365-control-name'
newEl.appendChild(newContent)
l.appendChild(newEl)
l.title = ' [' + fieldName + ']'
})


24 changes: 24 additions & 0 deletions getUpdateCode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@


// // Get the D365 XRM object unwrapped
var Xrm = window.wrappedJSObject.Xrm
// // Rewrap the Xrm object so as not to mess with it
XPCNativeWrapper(window.wrappedJSObject.Xrm)

// Get the entity type and id from the URL
const queryString = window.location.search
const urlParams = new URLSearchParams(queryString)
let entityName = urlParams.get('etn')
let entityId = urlParams.get('id')

let updateCode = "Xrm.WebApi.updateRecord('" + entityName + "', '" + entityId + "', { }).then(r => console.log(r)).catch(e => console.log(e))"

navigator.clipboard.writeText(updateCode).then(function() {
/* clipboard successfully set */
console.log('code copied to clipboard')
}, function(e) {
/* clipboard write failed */
console.log('failed to copy code to clipboard', e)
});


19 changes: 19 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{

"manifest_version": 2,
"name": "D365 Tools",
"version": "2.3",

"description": "Adds context menu options to interface with Dynamics 365 UUI and API such as show the names of controls on a form.",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["assets/micromodal.min.js"]
}
],
"background": {
"scripts": ["background.js"]
},
"permissions": ["contextMenus", "activeTab", "clipboardWrite" ]

}
4 changes: 4 additions & 0 deletions removeFieldNames.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var addedfieldLables = document.querySelectorAll('.D365-control-name')
addedfieldLables.forEach((l) => {
l.parentNode.removeChild(l)
})
155 changes: 155 additions & 0 deletions retrieveRecord.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
var D365ToolsRetrieveRecord = new function () {
this.addModalStyles = function () {
let css = '.micro-modal {' +
'display: none;' +
'}' +
'.micro-modal.is-open {' +
'display: block;' +
'z-index: 100000;' +
'background: white;' +
'position: absolute;' +
'top: 100px;' +
'width: 100%;' +
'padding:50px;' +
'}'
let styleEl = document.createElement('style')
styleEl.appendChild(document.createTextNode(css))
document.head.appendChild(styleEl)
}
this.clearContents = function(el) {
while(el.firstChild){
el.removeChild(el.firstChild);
}
}
this.retrieveRecord = function () {
console.log('Retrieving record details...')

// Get the D365 XRM object unwrapped
var Xrm = window.wrappedJSObject.Xrm
// Rewrap the Xrm object so as not to mess with it
XPCNativeWrapper(window.wrappedJSObject.Xrm)

Xrm.Utility.showProgressIndicator()

// Get the entity type and id from the URL (to avoid using deprecated Xrm.Page)
// let currentUrl = window.location.href
// let urlParts = currentUrl.split('&')
// let etnLocation = findInArray(urlParts, 'etn=')
// let idLocation = findInArray(urlParts, 'id=')
// let etn = urlParts[etnLocation].replace('etn=', '')
// let id = urlParts[idLocation].replace('id=', '')
// console.log('etn='+etn+' id='+id)

// Get the entity type and id from the URL
const queryString = window.location.search
const urlParams = new URLSearchParams(queryString)
let etn = urlParams.get('etn')
let id = urlParams.get('id')

let globalContext = Xrm.Utility.getGlobalContext()

// Add a div to the document for our modal if not already created
if (document.getElementById('entityResultModal') == null) {
var modalElement = document.createElement('div')
modalElement.setAttribute('id', 'entityResultModal')
modalElement.setAttribute('class', 'micro-modal')
modalElement.setAttribute('aria-hidden', true)
modalElement.innerHTML =
'<div tabindex="-1" data-micromodal-close>' +
'<div role="dialog" aria-modal="true" aria-labelledby="entityResultModal-title" >' +
'<header>' +
'<h2 id="entityResultModal-title"></h2>' +
'<button aria-label="Close" data-micromodal-close style="padding:10px">Close</button>' +
'<br />' +
'<a href="#" target="_blank" id="openURLInTab">Open in tab</a>' +
'</header>' +
'<div id="entityResultModal-content"></div>' +
'</div>' +
'</div>'
document.body.appendChild(modalElement)
this.addModalStyles()
MicroModal.init()
}



// Create the HTTP Request with no filters (get everything!)
var req = new XMLHttpRequest();
// Pluralize the entity name because someone at MS made a bad decision to use plurals in the endpoints... sigh
let pluralEtn = getPluralEntityName(etn)


req.open("GET", globalContext.getClientUrl() + '/api/data/v9.0/' + pluralEtn + '(' + id + ')', true)
req.setRequestHeader("OData-MaxVersion", "4.0")
req.setRequestHeader("OData-Version", "4.0")
req.setRequestHeader("Accept", "application/json")
req.setRequestHeader("Content-Type", "application/json; charset=utf-8")
req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"")

// Handle the result
req.onreadystatechange = function() {
if (this.readyState === 4) {
req.onreadystatechange = null
if (this.status === 200) {
let result = JSON.parse(this.response)
console.log('result', result)
Xrm.Utility.closeProgressIndicator()
let modalTitle = document.getElementById('entityResultModal-title')
modalTitle.innerHTML = '' // clear past contents
modalTitle.appendChild(document.createTextNode(etn + ' ' + id))
let modalContent = document.getElementById('entityResultModal-content')
modalContent.innerHTML = '' //clear past contents
let innerContent = document.createElement('pre')
let innerContentText = document.createTextNode(JSON.stringify(result, undefined, 2))
innerContent.appendChild(innerContentText)
modalContent.appendChild(innerContent)
let openInTabLink = document.getElementById('openURLInTab')
openInTabLink.setAttribute('href', req.responseURL)
MicroModal.show('entityResultModal')
//alert(JSON.stringify(result))
} else {
alert(this.statusText)
}
}
}

console.log('req', req)

req.send()


function findInArray(a, stringToFind) {
let stringFound = false
a.forEach((el, i) => {
if(el.indexOf(stringToFind) !== -1) {
stringFound = i
}
})
return stringFound
}
}

function getPluralEntityName (etn) {
let pluralName = ''
let lastChar = etn[etn.length - 1]
let lastTwoChars = etn.substring(etn.length - 2)
let secondLastChar = etn.substring(etn.length - 2, 1)
let endingsThatTakeEs = ['s', 'ss', 'sh', 'ch', 'x', 'z']
let vowels = ['a', 'e', 'i', 'o', 'u']

if (endingsThatTakeEs.indexOf(lastChar) !== -1 || endingsThatTakeEs.indexOf(lastTwoChars) !== -1) {
pluralName = etn + 'es'
} else if (lastChar === 'y' && vowels.indexOf(secondLastChar) === -1) {
// If ends in consonant plus 'y', remove 'y' and add 'ies'
pluralName = etn.substring(0, etn.length -1) + 'ies'
} else {
pluralName = etn + 's'
}

return pluralName
}
}


//D365ToolsRetrieveRecord.addModalStyles()
D365ToolsRetrieveRecord.retrieveRecord()
32 changes: 32 additions & 0 deletions showControls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
var D365ToolsShowControls = new function () {
this.showControls = function () {
console.log('Showing all controls...')

// Get the D365 XRM object unwrapped
var UI = window.wrappedJSObject.Xrm.Page.ui
var controls = UI.controls.getAll()
var tabs = UI.tabs.getAll()

// First show all tabs and all sections
for (let i=0; i<tabs.length; i++) {
tabs[i].setVisible(true)

let sections = tabs[i].sections.getAll()
for (let si=0; si<sections.length; si++) {
sections[si].setVisible(true)
}
}

// Finally, show all controls
for (let i=0; i<controls.length; i++) {
if (typeof controls[i].setVisible !== 'undefined') {
controls[i].setVisible(true)
}
}

// // Rewrap the Xrm object so as not to mess with it
XPCNativeWrapper(window.wrappedJSObject.Xrm.Page.ui)
}
}

D365ToolsShowControls.showControls()
19 changes: 19 additions & 0 deletions unlockFields.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
var D365ToolsUnlockFields = new function () {
this.unlockFields = function () {
console.log('Unlocking fields...')

// Get the D365 XRM object unwrapped
var UI = window.wrappedJSObject.Xrm.Page.ui
var controls = UI.controls.getAll()

for (let i=0; i<controls.length; i++) {
if (typeof controls[i].setDisabled !== 'undefined') {
controls[i].setDisabled(false)
}
}
// Rewrap the Xrm object so as not to mess with it
XPCNativeWrapper(window.wrappedJSObject.Xrm.Page.ui)
}
}

D365ToolsUnlockFields.unlockFields()

0 comments on commit 23f8382

Please sign in to comment.