/**
* Magic links module - adds onclick event to a document body and intercept clicks on hyperlink
*
* Hyperlink should be in form `<a href='#' data-cmd-type="commandToRun" ....>`
* In case command specified in `cmdType` data attribute is registered using `addCommand` it will be executed.
* Links samples:
* @example
<a href="#" data-cmd-type="showForm" data-entity="ubm_navshortcut", data-instance-id=332352169869385>
Edit existed shortcut with specified ID
</a>
<a href="#" data-cmd-type="setFocus" data-elm-id="ubedit-11223">
Set focus on edit
</a>
<a href="#"
data-cmd-type="showReport"
data-cmd-data='{"reportCode":"your-report-code","reportType":"html","reportParams":{"a":"b"},"reportOptions":{"allowExportToExcel":"xls"}}'
>
Show report `your-report-code` with parameters
</a>
* @module magicLinks
* @memberOf module:@unitybase/adminui-vue
*/
module.exports = {
addCommand,
install
}
const commands = {}
/**
* Adds a global onclick event listener. Called by adminui-vue.
*/
function install () {
if (document) document.addEventListener('click', checkClickOnMagicLink, false)
}
/**
* Register action for command. Command is passed as <a href="#' data-cmd-type="commandName">.
* If handler for command already exists it will be overrated
* @param {string} command
* @param {function} handler Callback what accept (dataObject: Object; EventTarget)
*/
function addCommand (command, handler) {
commands[command] = handler
}
/**
* @private
* @param {Event} e
*/
function checkClickOnMagicLink (e) {
const target = e.target
if (target.nodeName !== 'A') return
if (!target.href.endsWith('#')) return
let intercepted = false
const params = dataAttributesToObject(target.dataset)
if (!params.cmdType && params.entity && params.id) { // legacy data-entity + data-id
console.warn('Deprecated magic link format data-entity + data-id. Use <a href="#" data-cmd-type="showForm" data-entity="ubs_filter" data-instance-id=1233>')
params.cmdType = 'showForm'
params.instanceId = params.id
delete params.id
}
if (params.cmdType) {
if (commands[params.cmdType]) {
intercepted = true
commands[params.cmdType](params, target)
} else {
console.debug('Handler for magicLink command ', params.cmdType, ' is not registered')
}
}
if (intercepted) {
e.preventDefault()
}
}
/**
* Transform a dataset to the plain object.
* Nested props can be passed as stringified array or object
* @example
* // <a href='#' id="test" data-cmd-type="showList" data-id=100334 data-field-list='["ID", "code", "name']'>
* dataset = document.getElementById('test').dataset
* dataAttributesToObject(dataset) // {cmdType: 'showList', id: 100334, fieldList: ['ID', 'code', 'name']}
*
* @private
* @param dataset
*/
function dataAttributesToObject (dataset) {
const keys = Object.keys(dataset)
const result = {}
for (let i = 0, L = keys.length; i < L; i++) {
const k = keys[i]
const v = dataset[k]
if ((v.startsWith('{') && v.endsWith('}')) ||
(v.startsWith('[') && v.endsWith('}'))) {
result[k] = JSON.parse(v)
} else {
if (/^\d+$/.test(v)) {
result[k] = parseInt(v, 10)
} else {
result[k] = v
}
}
}
return result
}