Update widget expression capabilities (#1522)
- Add @ & @@ operators to insert item states. - Add `user` context object. - Allow expressions to specify the component type. - Allow HTML elements as component types to build HTML structures with components & slots. - Add 'Content' element (add the `text` config parameter inline). Signed-off-by: justin <justin.georgi@gmail.com>pull/1530/head
parent
6e9cc922fe
commit
79f5a6e730
|
@ -11,17 +11,21 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blockly/field-slider": "^2.1.10",
|
"@blockly/field-slider": "^2.1.10",
|
||||||
"@blockly/zoom-to-fit": "^2.0.24",
|
"@blockly/zoom-to-fit": "^2.0.24",
|
||||||
|
"@jsep-plugin/arrow": "^1.0.5",
|
||||||
|
"@jsep-plugin/object": "^1.2.1",
|
||||||
|
"@jsep-plugin/regex": "^1.0.3",
|
||||||
|
"@jsep-plugin/template": "^1.0.2",
|
||||||
"blockly": "^6.20210701.0",
|
"blockly": "^6.20210701.0",
|
||||||
"cronstrue": "^1.100.0",
|
"cronstrue": "^1.100.0",
|
||||||
"dayjs": "^1.9.6",
|
"dayjs": "^1.9.6",
|
||||||
"dom7": "^2.1.5",
|
"dom7": "^2.1.5",
|
||||||
"echarts": "^5.1.2",
|
"echarts": "^5.1.2",
|
||||||
"event-source-polyfill": "^1.0.22",
|
"event-source-polyfill": "^1.0.22",
|
||||||
"expression-eval": "^2.1.0",
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"framework7": "^5.7.12",
|
"framework7": "^5.7.12",
|
||||||
"framework7-icons": "^3.0.1",
|
"framework7-icons": "^3.0.1",
|
||||||
"framework7-vue": "^5.7.12",
|
"framework7-vue": "^5.7.12",
|
||||||
|
"jse-eval": "^1.5.1",
|
||||||
"jssip": "^3.9.1",
|
"jssip": "^3.9.1",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
"leaflet-providers": "^1.11.0",
|
"leaflet-providers": "^1.11.0",
|
||||||
|
@ -3407,6 +3411,50 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@jsep-plugin/arrow": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsep-plugin/arrow/-/arrow-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-4Q9/6nETEf79DQdyynPk9G5CvYGw/TyRAw6IpkiIBm1z6eyDyjhcLjYxmBCqlKIUvjS8h8hfU8MzSjQRSntK5Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.16.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"jsep": "^0.4.0||^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jsep-plugin/object": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsep-plugin/object/-/object-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-6YoZP80h2QFCuxyqj+OvoqEnTu2r5cSRpgpvGauWlvnevFP/F/dibpvXDpnHeqwT2FIzzvg47YOe3QD/UT8vJw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.16.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"jsep": "^0.4.0||^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jsep-plugin/regex": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-XfZgry4DwEZvSFtS/6Y+R48D7qJYJK6R9/yJFyUFHCIUMEEHuJ4X95TDgJp5QkmzfLYvapMPzskV5HpIDrREug==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.16.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"jsep": "^0.4.0||^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jsep-plugin/template": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsep-plugin/template/-/template-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-fGIPHL4W/YZ3YShDByfWlLEIMCLRUTZDUDii4Xat4sJ+DTYeS21RWrZkvbprICyiwmO/fRY7xdHZh7K/ng6xLg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.16.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"jsep": "^0.4.0||^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@relative-ci/agent": {
|
"node_modules/@relative-ci/agent": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@relative-ci/agent/-/agent-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@relative-ci/agent/-/agent-1.5.0.tgz",
|
||||||
|
@ -9963,14 +10011,6 @@
|
||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/expression-eval": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/expression-eval/-/expression-eval-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-FUJO/Akvl/JOWkvlqZaqbkhsEWlCJWDeZG4tzX96UH68D9FeRgYgtb55C2qtqbORC0Q6x5419EDjWu4IT9kQfg==",
|
|
||||||
"dependencies": {
|
|
||||||
"jsep": "^0.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/extend": {
|
"node_modules/extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
@ -12942,12 +12982,20 @@
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jse-eval": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jse-eval/-/jse-eval-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-wnMRaxvZUuBMxMNZd5Xs5z30c9Glb8p7hFERxrzdNKcWnqSAdvQM7+c+NCloaTniV/NtYpuQSsqEF+Twc6T71Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"jsep": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsep": {
|
"node_modules/jsep": {
|
||||||
"version": "0.3.4",
|
"version": "1.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/jsep/-/jsep-0.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.7.tgz",
|
||||||
"integrity": "sha512-ovGD9wE+wvudIIYxZGrRcZCxNyZ3Cl1N7Bzyp7/j4d/tA0BaUwcVM9bu0oZaSrefMiNwv6TwZ9X15gvZosteCQ==",
|
"integrity": "sha512-NFbZTr1t13fPKw53swmZFKwBkEDWDnno7uLJk+a+Rw9tGDTkGgnGdZJ8A/o3gR1+XaAXmSsbpfIBIBgqRBZWDA==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.10.0"
|
"node": ">= 10.16.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jsesc": {
|
"node_modules/jsesc": {
|
||||||
|
@ -25910,6 +25958,30 @@
|
||||||
"@types/yargs": "^13.0.0"
|
"@types/yargs": "^13.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@jsep-plugin/arrow": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsep-plugin/arrow/-/arrow-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-4Q9/6nETEf79DQdyynPk9G5CvYGw/TyRAw6IpkiIBm1z6eyDyjhcLjYxmBCqlKIUvjS8h8hfU8MzSjQRSntK5Q==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"@jsep-plugin/object": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsep-plugin/object/-/object-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-6YoZP80h2QFCuxyqj+OvoqEnTu2r5cSRpgpvGauWlvnevFP/F/dibpvXDpnHeqwT2FIzzvg47YOe3QD/UT8vJw==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"@jsep-plugin/regex": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-XfZgry4DwEZvSFtS/6Y+R48D7qJYJK6R9/yJFyUFHCIUMEEHuJ4X95TDgJp5QkmzfLYvapMPzskV5HpIDrREug==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"@jsep-plugin/template": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsep-plugin/template/-/template-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-fGIPHL4W/YZ3YShDByfWlLEIMCLRUTZDUDii4Xat4sJ+DTYeS21RWrZkvbprICyiwmO/fRY7xdHZh7K/ng6xLg==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"@relative-ci/agent": {
|
"@relative-ci/agent": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@relative-ci/agent/-/agent-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@relative-ci/agent/-/agent-1.5.0.tgz",
|
||||||
|
@ -31455,14 +31527,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"expression-eval": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/expression-eval/-/expression-eval-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-FUJO/Akvl/JOWkvlqZaqbkhsEWlCJWDeZG4tzX96UH68D9FeRgYgtb55C2qtqbORC0Q6x5419EDjWu4IT9kQfg==",
|
|
||||||
"requires": {
|
|
||||||
"jsep": "^0.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extend": {
|
"extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
@ -33890,10 +33954,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jse-eval": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jse-eval/-/jse-eval-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-wnMRaxvZUuBMxMNZd5Xs5z30c9Glb8p7hFERxrzdNKcWnqSAdvQM7+c+NCloaTniV/NtYpuQSsqEF+Twc6T71Q==",
|
||||||
|
"requires": {
|
||||||
|
"jsep": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"jsep": {
|
"jsep": {
|
||||||
"version": "0.3.4",
|
"version": "1.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/jsep/-/jsep-0.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.7.tgz",
|
||||||
"integrity": "sha512-ovGD9wE+wvudIIYxZGrRcZCxNyZ3Cl1N7Bzyp7/j4d/tA0BaUwcVM9bu0oZaSrefMiNwv6TwZ9X15gvZosteCQ=="
|
"integrity": "sha512-NFbZTr1t13fPKw53swmZFKwBkEDWDnno7uLJk+a+Rw9tGDTkGgnGdZJ8A/o3gR1+XaAXmSsbpfIBIBgqRBZWDA=="
|
||||||
},
|
},
|
||||||
"jsesc": {
|
"jsesc": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.2",
|
||||||
|
|
|
@ -63,17 +63,21 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blockly/field-slider": "^2.1.10",
|
"@blockly/field-slider": "^2.1.10",
|
||||||
"@blockly/zoom-to-fit": "^2.0.24",
|
"@blockly/zoom-to-fit": "^2.0.24",
|
||||||
|
"@jsep-plugin/arrow": "^1.0.5",
|
||||||
|
"@jsep-plugin/object": "^1.2.1",
|
||||||
|
"@jsep-plugin/regex": "^1.0.3",
|
||||||
|
"@jsep-plugin/template": "^1.0.2",
|
||||||
"blockly": "^6.20210701.0",
|
"blockly": "^6.20210701.0",
|
||||||
"cronstrue": "^1.100.0",
|
"cronstrue": "^1.100.0",
|
||||||
"dayjs": "^1.9.6",
|
"dayjs": "^1.9.6",
|
||||||
"dom7": "^2.1.5",
|
"dom7": "^2.1.5",
|
||||||
"echarts": "^5.1.2",
|
"echarts": "^5.1.2",
|
||||||
"event-source-polyfill": "^1.0.22",
|
"event-source-polyfill": "^1.0.22",
|
||||||
"expression-eval": "^2.1.0",
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"framework7": "^5.7.12",
|
"framework7": "^5.7.12",
|
||||||
"framework7-icons": "^3.0.1",
|
"framework7-icons": "^3.0.1",
|
||||||
"framework7-vue": "^5.7.12",
|
"framework7-vue": "^5.7.12",
|
||||||
|
"jse-eval": "^1.5.1",
|
||||||
"jssip": "^3.9.1",
|
"jssip": "^3.9.1",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
"leaflet-providers": "^1.11.0",
|
"leaflet-providers": "^1.11.0",
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { findEquipment, allEquipmentPoints, findPoints } from '../glance-helpers'
|
import { findEquipment, allEquipmentPoints, findPoints } from '../glance-helpers'
|
||||||
import expr from 'expression-eval'
|
import expr from 'jse-eval'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['element', 'type', 'badgeOverrides', 'invertColor', 'store'],
|
props: ['element', 'type', 'badgeOverrides', 'invertColor', 'store'],
|
||||||
|
@ -187,7 +187,7 @@ export default {
|
||||||
reduce () {
|
reduce () {
|
||||||
const ast = this.overrideExpression()
|
const ast = this.overrideExpression()
|
||||||
if (ast) {
|
if (ast) {
|
||||||
return this.map.filter((state) => expr.eval(ast, { state: state, Number: Number })).length
|
return this.map.filter((state) => expr.evaluate(ast, { state: state, Number: Number })).length
|
||||||
}
|
}
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'blinds':
|
case 'blinds':
|
||||||
|
|
|
@ -255,7 +255,8 @@ export default {
|
||||||
'Ctrl-Space': 'autocomplete',
|
'Ctrl-Space': 'autocomplete',
|
||||||
'\'.\'': autocomplete,
|
'\'.\'': autocomplete,
|
||||||
'\'=\'': autocomplete,
|
'\'=\'': autocomplete,
|
||||||
'Space': autocomplete
|
'Space': autocomplete,
|
||||||
|
'\'@\'': autocomplete
|
||||||
}
|
}
|
||||||
cm.state.$oh = this.$oh
|
cm.state.$oh = this.$oh
|
||||||
cm.state.originalMode = this.mode
|
cm.state.originalMode = this.mode
|
||||||
|
|
|
@ -50,7 +50,7 @@ function getWidgetDefinitions (cm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hintItems (cm, line, replaceAfterColon, addStatePropertySuffix) {
|
function hintItems (cm, line, replaceAfterColon, addStatePropertySuffix, addQuotes) {
|
||||||
const cursor = cm.getCursor()
|
const cursor = cm.getCursor()
|
||||||
const promise = (itemsCache) ? Promise.resolve(itemsCache) : cm.state.$oh.api.get('/rest/items')
|
const promise = (itemsCache) ? Promise.resolve(itemsCache) : cm.state.$oh.api.get('/rest/items')
|
||||||
return promise.then((data) => {
|
return promise.then((data) => {
|
||||||
|
@ -58,7 +58,7 @@ function hintItems (cm, line, replaceAfterColon, addStatePropertySuffix) {
|
||||||
let ret = {
|
let ret = {
|
||||||
list: data.map((item) => {
|
list: data.map((item) => {
|
||||||
return {
|
return {
|
||||||
text: item.name + ((addStatePropertySuffix ? '.state' : '')),
|
text: (addQuotes ? '\'' : '') + item.name + ((addStatePropertySuffix ? '.state' : '')) + (addQuotes ? '\'' : ''),
|
||||||
displayText: item.name,
|
displayText: item.name,
|
||||||
description: `${(item.label) ? item.label + ' ' : ''}(${item.type})<br />${item.state}`
|
description: `${(item.label) ? item.label + ' ' : ''}(${item.type})<br />${item.state}`
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,9 @@ function hintItems (cm, line, replaceAfterColon, addStatePropertySuffix) {
|
||||||
const colonPos = line.indexOf(':')
|
const colonPos = line.indexOf(':')
|
||||||
ret.from = { line: cursor.line, ch: colonPos + 2 }
|
ret.from = { line: cursor.line, ch: colonPos + 2 }
|
||||||
ret.to = { line: cursor.line, ch: line.length }
|
ret.to = { line: cursor.line, ch: line.length }
|
||||||
|
} else if (addQuotes) {
|
||||||
|
const lastAtOp = line.substring(0, cursor.ch).replace(/@[A-Za-z0-9_-]*$/, '@')
|
||||||
|
ret.to = { line: cursor.line, ch: lastAtOp.length }
|
||||||
} else {
|
} else {
|
||||||
const lastDot = line.substring(0, cursor.ch).replace(/\.[A-Za-z0-9_-]*$/, '.')
|
const lastDot = line.substring(0, cursor.ch).replace(/\.[A-Za-z0-9_-]*$/, '.')
|
||||||
ret.to = { line: cursor.line, ch: lastDot.length }
|
ret.to = { line: cursor.line, ch: lastDot.length }
|
||||||
|
@ -110,11 +113,16 @@ function hintExpression (cm, line) {
|
||||||
{ text: 'theme', displayText: 'theme', description: 'The current theme: aurora, ios, or md' },
|
{ text: 'theme', displayText: 'theme', description: 'The current theme: aurora, ios, or md' },
|
||||||
{ text: 'themeOptions', displayText: 'themeOptions', description: 'Object with current theme options' },
|
{ text: 'themeOptions', displayText: 'themeOptions', description: 'Object with current theme options' },
|
||||||
{ text: 'device', displayText: 'device', description: 'Object with information about the current device & browser' },
|
{ text: 'device', displayText: 'device', description: 'Object with information about the current device & browser' },
|
||||||
|
{ text: 'user', displayText: 'user', description: 'Access the username and roles of the logged in user' },
|
||||||
{ text: 'screen', displayText: 'screen', description: 'Object with information about the screen and available view area' },
|
{ text: 'screen', displayText: 'screen', description: 'Object with information about the screen and available view area' },
|
||||||
{ text: 'dayjs', displayText: 'dayjs', description: 'Access to the Day.js object for date manipulation & formatting' }
|
{ text: 'dayjs', displayText: 'dayjs', description: 'Access to the Day.js object for date manipulation & formatting' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
const lastAtOp = line.substring(0, cursor.ch).replace(/@[A-Za-z0-9_-]*$/, '@')
|
||||||
|
if (lastAtOp.endsWith('@')) {
|
||||||
|
return hintItems(cm, line, false, false, true)
|
||||||
|
}
|
||||||
const lastDot = line.substring(0, cursor.ch).replace(/\.[A-Za-z0-9_-]*$/, '.')
|
const lastDot = line.substring(0, cursor.ch).replace(/\.[A-Za-z0-9_-]*$/, '.')
|
||||||
if (lastDot.endsWith('items.')) {
|
if (lastDot.endsWith('items.')) {
|
||||||
return hintItems(cm, line, false, true)
|
return hintItems(cm, line, false, true)
|
||||||
|
|
|
@ -31,7 +31,7 @@ export function remove (node) {
|
||||||
export function filterPartialCompletions (cm, line, completions, property = 'text') {
|
export function filterPartialCompletions (cm, line, completions, property = 'text') {
|
||||||
const cursor = cm.getCursor()
|
const cursor = cm.getCursor()
|
||||||
const lineBeforeCursor = line.substring(0, cursor.ch)
|
const lineBeforeCursor = line.substring(0, cursor.ch)
|
||||||
const completionBeginPos = Math.max(lineBeforeCursor.lastIndexOf(' '), lineBeforeCursor.lastIndexOf('.'))
|
const completionBeginPos = Math.max(lineBeforeCursor.lastIndexOf(' '), lineBeforeCursor.lastIndexOf('.'), lineBeforeCursor.lastIndexOf('@'))
|
||||||
const partialCompletion = lineBeforeCursor.substring(completionBeginPos + 1)
|
const partialCompletion = lineBeforeCursor.substring(completionBeginPos + 1)
|
||||||
return completions.filter((c) => c[property] && c[property].toLowerCase().indexOf(partialCompletion.toLowerCase()) >= 0)
|
return completions.filter((c) => c[property] && c[property].toLowerCase().indexOf(partialCompletion.toLowerCase()) >= 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,21 @@
|
||||||
<div v-else-if="componentType && componentType === 'Label' && visible" :class="config.class" :style="config.style">
|
<div v-else-if="componentType && componentType === 'Label' && visible" :class="config.class" :style="config.style">
|
||||||
{{ config.text }}
|
{{ config.text }}
|
||||||
</div>
|
</div>
|
||||||
|
<fragment v-else-if="componentType && componentType === 'Content'">
|
||||||
|
{{ config.text }}
|
||||||
|
</fragment>
|
||||||
<pre v-else-if="componentType && componentType === 'Error' && visible" class="text-color-red" style="white-space: pre-wrap">{{ config.error }}</pre>
|
<pre v-else-if="componentType && componentType === 'Error' && visible" class="text-color-red" style="white-space: pre-wrap">{{ config.error }}</pre>
|
||||||
|
<component v-else-if="visible" :is="componentType" v-bind="config">
|
||||||
|
{{ config.content }}
|
||||||
|
<template v-if="context.component.slots && context.component.slots.default">
|
||||||
|
<generic-widget-component :context="childContext(slotComponent)" v-for="(slotComponent, idx) in context.component.slots.default" :key="'default-' + idx" />
|
||||||
|
</template>
|
||||||
|
</component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { Fragment } from 'vue-fragment'
|
||||||
|
|
||||||
import mixin from './widget-mixin'
|
import mixin from './widget-mixin'
|
||||||
|
|
||||||
import * as SystemWidgets from './system/index'
|
import * as SystemWidgets from './system/index'
|
||||||
|
@ -28,6 +39,7 @@ import * as LayoutWidgets from './layout/index'
|
||||||
export default {
|
export default {
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
components: {
|
components: {
|
||||||
|
Fragment,
|
||||||
...SystemWidgets,
|
...SystemWidgets,
|
||||||
...StandardWidgets,
|
...StandardWidgets,
|
||||||
...StandardListWidgets,
|
...StandardListWidgets,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Import into widget components as a mixin!
|
// Import into widget components as a mixin!
|
||||||
|
|
||||||
import expr from 'expression-eval'
|
import expr from 'jse-eval'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
import calendar from 'dayjs/plugin/calendar'
|
import calendar from 'dayjs/plugin/calendar'
|
||||||
|
@ -10,6 +10,22 @@ import isToday from 'dayjs/plugin/isToday'
|
||||||
import isYesterday from 'dayjs/plugin/isYesterday'
|
import isYesterday from 'dayjs/plugin/isYesterday'
|
||||||
import isTomorrow from 'dayjs/plugin/isTomorrow'
|
import isTomorrow from 'dayjs/plugin/isTomorrow'
|
||||||
import scope from 'scope-css'
|
import scope from 'scope-css'
|
||||||
|
import store from '@/js/store'
|
||||||
|
|
||||||
|
import jsepRegex from '@jsep-plugin/regex'
|
||||||
|
import jsepArrow from '@jsep-plugin/arrow'
|
||||||
|
import jsepObject from '@jsep-plugin/object'
|
||||||
|
import jsepTemplate from '@jsep-plugin/template'
|
||||||
|
expr.jsep.plugins.register(jsepRegex, jsepArrow, jsepObject, jsepTemplate)
|
||||||
|
|
||||||
|
expr.addUnaryOp('@', (itemName) => {
|
||||||
|
const itemState = store.getters.trackedItems[itemName]
|
||||||
|
if (itemState.displayState === undefined) return itemState.state
|
||||||
|
return itemState.displayState
|
||||||
|
})
|
||||||
|
expr.addUnaryOp('@@', (itemName) => {
|
||||||
|
return store.getters.trackedItems[itemName].state
|
||||||
|
})
|
||||||
|
|
||||||
dayjs.extend(relativeTime)
|
dayjs.extend(relativeTime)
|
||||||
dayjs.extend(calendar)
|
dayjs.extend(calendar)
|
||||||
|
@ -30,7 +46,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
componentType () {
|
componentType () {
|
||||||
return this.context.component.component
|
return this.evaluateExpression('type', this.context.component.component)
|
||||||
},
|
},
|
||||||
childWidgetComponentType () {
|
childWidgetComponentType () {
|
||||||
if (!this.componentType.startsWith('widget:')) return null
|
if (!this.componentType.startsWith('widget:')) return null
|
||||||
|
@ -112,7 +128,7 @@ export default {
|
||||||
if (!this.exprAst[key] || ctx.editmode) {
|
if (!this.exprAst[key] || ctx.editmode) {
|
||||||
this.exprAst[key] = expr.parse(value.substring(1))
|
this.exprAst[key] = expr.parse(value.substring(1))
|
||||||
}
|
}
|
||||||
return expr.eval(this.exprAst[key], {
|
return expr.evaluate(this.exprAst[key], {
|
||||||
items: ctx.store,
|
items: ctx.store,
|
||||||
props: this.props,
|
props: this.props,
|
||||||
vars: ctx.vars,
|
vars: ctx.vars,
|
||||||
|
@ -124,7 +140,8 @@ export default {
|
||||||
device: this.$device,
|
device: this.$device,
|
||||||
screen: this.getScreenInfo(),
|
screen: this.getScreenInfo(),
|
||||||
JSON: JSON,
|
JSON: JSON,
|
||||||
dayjs: dayjs
|
dayjs: dayjs,
|
||||||
|
user: this.$store.getters.user
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return e
|
return e
|
||||||
|
|
Loading…
Reference in New Issue