@mixd-id/web-scaffold 0.2.240702 → 0.2.240704
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/schema/user-action.json +266 -0
- package/package.json +6 -2
- package/public/assets/dashboard/bar.png +0 -0
- package/public/assets/dashboard/doughnut.png +0 -0
- package/public/assets/dashboard/metric.png +0 -0
- package/public/assets/dashboard/pie.png +0 -0
- package/public/assets/dashboard/polar-area.png +0 -0
- package/public/assets/dashboard/virtual-table.png +0 -0
- package/public/static/dashboard/bar.png +0 -0
- package/public/static/dashboard/doughnut.png +0 -0
- package/public/static/dashboard/metric.png +0 -0
- package/public/static/dashboard/pie.png +0 -0
- package/public/static/dashboard/polar-area.png +0 -0
- package/public/static/dashboard/virtual-table.png +0 -0
- package/src/components/Button.vue +179 -160
- package/src/components/Checkbox.vue +0 -1
- package/src/components/Datepicker.vue +8 -6
- package/src/components/GHeatMaps.vue +317 -0
- package/src/components/GmapsDirection.vue +191 -0
- package/src/components/Grid.vue +2 -0
- package/src/components/HTMLEditor.vue +2 -2
- package/src/components/List.vue +384 -308
- package/src/components/Modal.vue +2 -3
- package/src/components/PresetSelectorFilterItem.vue +15 -2
- package/src/components/Switch.vue +3 -0
- package/src/components/Tabs.vue +1 -1
- package/src/components/TextWithTag.vue +67 -25
- package/src/components/Textbox.vue +5 -0
- package/src/components/VirtualGrid.vue +224 -228
- package/src/components/VirtualTable.vue +46 -28
- package/src/configs/dashboard/bar.js +10 -0
- package/src/configs/dashboard/collection-1.js +5 -0
- package/src/configs/dashboard/doughnut.js +7 -0
- package/src/configs/dashboard/gheatmaps.js +9 -0
- package/src/configs/dashboard/grid-2.js +34 -0
- package/src/configs/dashboard/grid-3.js +34 -0
- package/src/configs/dashboard/grid-4.js +34 -0
- package/src/configs/dashboard/grid.js +15 -0
- package/src/configs/dashboard/metric.js +10 -0
- package/src/configs/dashboard/pie.js +7 -0
- package/src/configs/dashboard/polar-area.js +7 -0
- package/src/configs/dashboard/virtual-table.js +9 -0
- package/src/defs/dashboard-preset.js +22 -0
- package/src/index.js +37 -23
- package/src/mixin/ready-state.js +37 -0
- package/src/stores/datasource.js +11 -0
- package/src/themes/default/index.js +1 -1
- package/src/utils/dashboard.js +1080 -0
- package/src/utils/event-bus.js +8 -0
- package/src/utils/helpers.js +56 -8
- package/src/utils/helpers.mjs +35 -1
- package/src/utils/preset-selector.js +5 -2
- package/src/utils/preset-selector.mjs +23 -13
- package/src/widgets/BotEditor/BotEditorActions.vue +162 -0
- package/src/widgets/BotEditor.vue +228 -0
- package/src/widgets/Dashboard/BarChart.vue +330 -0
- package/src/widgets/Dashboard/BarChartSetting.vue +317 -0
- package/src/widgets/Dashboard/DatasourceFilterSharing.vue +93 -0
- package/src/widgets/Dashboard/DatasourcePreview.vue +93 -0
- package/src/widgets/Dashboard/DatasourceSelector.vue +122 -0
- package/src/widgets/Dashboard/Doughnut.vue +157 -0
- package/src/widgets/Dashboard/DoughnutSetting.vue +196 -0
- package/src/widgets/Dashboard/GHeatMapsSetting.vue +108 -0
- package/src/widgets/Dashboard/InteractionEdit.vue +228 -0
- package/src/widgets/Dashboard/Metric.vue +76 -0
- package/src/widgets/Dashboard/MetricSetting.vue +174 -0
- package/src/widgets/Dashboard/Pie.vue +139 -0
- package/src/widgets/Dashboard/PieSetting.vue +247 -0
- package/src/widgets/Dashboard/PolarArea.vue +159 -0
- package/src/widgets/Dashboard/PolarAreaSetting.vue +195 -0
- package/src/widgets/Dashboard/SharingModal.vue +116 -0
- package/src/widgets/Dashboard/ViewSelector.vue +183 -0
- package/src/widgets/Dashboard/VirtualColumnEdit.vue +97 -0
- package/src/widgets/Dashboard/VirtualTableSetting.vue +234 -0
- package/src/widgets/Dashboard.vue +1773 -0
- package/src/widgets/PresetBar.vue +136 -175
- package/src/widgets/PresetBarPivot.vue +186 -0
- package/src/widgets/PresetSelector.vue +2 -2
- package/src/widgets/UserActionBuilder/UserActionCondition.vue +99 -0
- package/src/widgets/UserActionBuilder/UserActionConsole.vue +77 -0
- package/src/widgets/UserActionBuilder/UserActionItem.vue +166 -58
- package/src/widgets/UserActionBuilder/UserActionOutput.vue +35 -9
- package/src/widgets/UserActionBuilder/UserActionOutputDelay.vue +27 -0
- package/src/widgets/UserActionBuilder/UserActionOutputLog.vue +28 -0
- package/src/widgets/UserActionBuilder/UserActionOutputReply.vue +135 -0
- package/src/widgets/UserActionBuilder/UserActionProps.vue +213 -0
- package/src/widgets/UserActionBuilder.vue +68 -199
- package/src/widgets/WebPageBuilder4/GridSetting.vue +123 -73
- package/src/widgets/WebPageBuilder4/HeightSetting.vue +14 -11
- package/src/widgets/WebPageBuilder4/MarginSetting.vue +4 -1
- package/src/widgets/WebPageBuilder4/MultiValueSetting.vue +12 -4
- package/src/widgets/WebPageBuilder4/PaddingSetting.vue +4 -0
- package/src/widgets/WebPageBuilder4/TreeView.vue +6 -3
- package/src/widgets/WebPageBuilder4/TreeViewItem.vue +32 -58
- package/tailwind.config.js +2 -2
package/src/utils/helpers.js
CHANGED
|
@@ -3,6 +3,7 @@ const fs = require("fs");
|
|
|
3
3
|
const { Op } = require('sequelize')
|
|
4
4
|
const axios = require('axios')
|
|
5
5
|
const dayjs = require('dayjs')
|
|
6
|
+
const { camelCase } = require('lodash')
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
const ceil = (num, precision = 0) => {
|
|
@@ -140,13 +141,14 @@ const strSlug = (title, separator) => {
|
|
|
140
141
|
return title.replace(new RegExp('^[' + separator + '\\s]+|[' + separator + '\\s]+$', 'g'),'');
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
const strVars = (text, vars, opt = { emptyUndefined:true }) => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
const strVars = (text, vars = {}, opt = { emptyUndefined:true }) => {
|
|
145
|
+
if(text){
|
|
146
|
+
(text.match(/\{.*?(?=\})\}/gi) ?? []).forEach((match) => {
|
|
147
|
+
const key = match.substring(1, match.length - 1)
|
|
148
|
+
const value = vars[key] ?? (opt?.emptyUndefined ? '' : `{${key}}`)
|
|
149
|
+
text = text.replace(match, value)
|
|
150
|
+
})
|
|
151
|
+
}
|
|
150
152
|
|
|
151
153
|
return text
|
|
152
154
|
}
|
|
@@ -260,7 +262,7 @@ const unflatten = (flatObject) => {
|
|
|
260
262
|
}
|
|
261
263
|
|
|
262
264
|
const accessNestedObject = function(obj, path) {
|
|
263
|
-
if(!obj || typeof path !== 'string') return
|
|
265
|
+
if(!obj || typeof path !== 'string') return
|
|
264
266
|
|
|
265
267
|
const keys = path.split('.');
|
|
266
268
|
let nestedObj = obj;
|
|
@@ -277,6 +279,43 @@ const accessNestedObject = function(obj, path) {
|
|
|
277
279
|
return nestedObj;
|
|
278
280
|
}
|
|
279
281
|
|
|
282
|
+
const accessNestedSequelize = async(obj, path, opt = { defaultValue:'' }) => {
|
|
283
|
+
if(!obj || typeof path !== 'string') return
|
|
284
|
+
|
|
285
|
+
const keys = path.split('.');
|
|
286
|
+
let value = obj;
|
|
287
|
+
|
|
288
|
+
for (let i in keys) {
|
|
289
|
+
const key = keys[i]
|
|
290
|
+
const hasNext = i < keys.length - 1
|
|
291
|
+
|
|
292
|
+
if(hasNext){
|
|
293
|
+
|
|
294
|
+
if(!value[key]){
|
|
295
|
+
try{
|
|
296
|
+
value = await value[camelCase(`get-${key}`)]()
|
|
297
|
+
}
|
|
298
|
+
catch(e){}
|
|
299
|
+
}
|
|
300
|
+
else{
|
|
301
|
+
value = value[key]
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if(!value){
|
|
305
|
+
return
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
else{
|
|
310
|
+
value = key in value.dataValues ?
|
|
311
|
+
value[key] :
|
|
312
|
+
opt.defaultValue
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return value;
|
|
317
|
+
}
|
|
318
|
+
|
|
280
319
|
const createObjectFromPath = (obj, path, value) => {
|
|
281
320
|
const keys = path.split('.');
|
|
282
321
|
|
|
@@ -524,8 +563,16 @@ const dayTimeRange = (params, value) => {
|
|
|
524
563
|
})
|
|
525
564
|
}
|
|
526
565
|
|
|
566
|
+
function capitalize(str) {
|
|
567
|
+
return (str ?? '')
|
|
568
|
+
.toString()
|
|
569
|
+
.split(' ')
|
|
570
|
+
.map(_ => _.charAt(0).toUpperCase() + _.slice(1).toLowerCase())
|
|
571
|
+
.join(' ')
|
|
572
|
+
}
|
|
527
573
|
|
|
528
574
|
module.exports = {
|
|
575
|
+
capitalize,
|
|
529
576
|
ceil,
|
|
530
577
|
floor,
|
|
531
578
|
ftWildcard,
|
|
@@ -544,6 +591,7 @@ module.exports = {
|
|
|
544
591
|
getPresetSortWhereParams,
|
|
545
592
|
unflatten,
|
|
546
593
|
accessNestedObject,
|
|
594
|
+
accessNestedSequelize,
|
|
547
595
|
createObjectFromPath,
|
|
548
596
|
generateStylesheet,
|
|
549
597
|
hexToRgb,
|
package/src/utils/helpers.mjs
CHANGED
|
@@ -360,7 +360,40 @@ function applyDatasourceReplacer(value, datasource){
|
|
|
360
360
|
return value
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
function capitalize(str) {
|
|
364
|
+
return str.replace(/\b\w/g, function(char) {
|
|
365
|
+
return char.toUpperCase();
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const round = (num, precision = 0) => {
|
|
370
|
+
var p = Math.pow(10, precision)
|
|
371
|
+
var n = (num * p) * (1 + Number.EPSILON)
|
|
372
|
+
return Math.round(n) / p
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
let invokeAfterIdleStore = []
|
|
376
|
+
const invokeAfterIdle = (callback, delay = 1300) => {
|
|
377
|
+
let timeoutId
|
|
378
|
+
|
|
379
|
+
return function(){
|
|
380
|
+
if(invokeAfterIdleStore.includes(callback))
|
|
381
|
+
return
|
|
382
|
+
|
|
383
|
+
invokeAfterIdleStore.push(callback)
|
|
384
|
+
|
|
385
|
+
window.clearTimeout(timeoutId)
|
|
386
|
+
timeoutId = window.setTimeout(() => {
|
|
387
|
+
callback.apply(this, arguments)
|
|
388
|
+
invokeAfterIdleStore.splice(invokeAfterIdleStore.indexOf(callback), 1)
|
|
389
|
+
}, delay)
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
|
|
363
394
|
export {
|
|
395
|
+
capitalize,
|
|
396
|
+
round,
|
|
364
397
|
downsizeImage,
|
|
365
398
|
hexToRgb,
|
|
366
399
|
rgbToHex,
|
|
@@ -382,7 +415,8 @@ export {
|
|
|
382
415
|
createFormData,
|
|
383
416
|
unslugAndCapitalize,
|
|
384
417
|
applyDatasourceReplacer,
|
|
385
|
-
strVars
|
|
418
|
+
strVars,
|
|
419
|
+
invokeAfterIdle
|
|
386
420
|
}
|
|
387
421
|
|
|
388
422
|
function observeInit(){
|
|
@@ -925,9 +925,11 @@ const presetToSequelizeList = async(preset = {}, {
|
|
|
925
925
|
order:initialOrder
|
|
926
926
|
}) => {
|
|
927
927
|
|
|
928
|
+
const updatedAtField = model.rawAttributes['updatedAt'] ?? model.rawAttributes['updated_at']
|
|
929
|
+
|
|
928
930
|
if(!initialOrder){
|
|
929
931
|
initialOrder = [
|
|
930
|
-
[
|
|
932
|
+
...(updatedAtField ? [[ updatedAtField.fieldName, 'desc' ]] : []),
|
|
931
933
|
[ 'id', 'desc' ],
|
|
932
934
|
]
|
|
933
935
|
}
|
|
@@ -1036,7 +1038,8 @@ const presetToSequelizeList = async(preset = {}, {
|
|
|
1036
1038
|
...replacements,
|
|
1037
1039
|
...filterReplacements,
|
|
1038
1040
|
...searchReplacements
|
|
1039
|
-
]
|
|
1041
|
+
],
|
|
1042
|
+
itemsPerPage
|
|
1040
1043
|
}
|
|
1041
1044
|
}
|
|
1042
1045
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import md5 from "md5";
|
|
2
|
+
|
|
1
3
|
const sortsFn = function(a, b, sorts, index){
|
|
2
4
|
|
|
3
5
|
const sort = sorts[index]
|
|
@@ -31,24 +33,31 @@ const pickColumns = function(columns, keys){
|
|
|
31
33
|
return picked
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
const getPresetUid = function(extra = ''){
|
|
37
|
+
return md5('preset-' + new Date().getTime() + extra)
|
|
38
|
+
}
|
|
39
|
+
|
|
34
40
|
const setupConfig = (config) => {
|
|
35
41
|
|
|
36
42
|
if(Array.isArray(config.presets)){
|
|
37
43
|
for(let idx in config.presets){
|
|
38
|
-
if(!Array.isArray(config.presets[idx].columns)){
|
|
39
|
-
config.presets[idx].columns = []
|
|
44
|
+
if(!Array.isArray(config.presets[idx].params.columns)){
|
|
45
|
+
config.presets[idx].params.columns = []
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
if(config.presets[idx].columns[0] && typeof config.presets[idx].columns[0] === 'string'){
|
|
43
|
-
config.presets[idx].columns = pickColumns(config.columns ?? [], config.presets[idx].columns)
|
|
48
|
+
if(config.presets[idx].params.columns[0] && typeof config.presets[idx].params.columns[0] === 'string'){
|
|
49
|
+
config.presets[idx].params.columns = pickColumns(config.params.columns ?? [], config.presets[idx].params.columns)
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
if(!config.presets[idx].view)
|
|
47
|
-
config.presets[idx].view = 'table'
|
|
52
|
+
if(!config.presets[idx].params.view)
|
|
53
|
+
config.presets[idx].params.view = 'table'
|
|
54
|
+
|
|
55
|
+
if(!config.presets[idx].uid)
|
|
56
|
+
config.presets[idx].uid = getPresetUid(idx)
|
|
48
57
|
}
|
|
49
58
|
|
|
50
|
-
if(!config.presetIdx && config.presets.length > 0){
|
|
51
|
-
config.presetIdx = 0
|
|
59
|
+
if(!config.params.presetIdx && config.presets.length > 0){
|
|
60
|
+
config.params.presetIdx = config.presets[0].uid
|
|
52
61
|
}
|
|
53
62
|
}
|
|
54
63
|
|
|
@@ -147,11 +156,11 @@ const generatePivotColumns = (preset, items) => {
|
|
|
147
156
|
}
|
|
148
157
|
}
|
|
149
158
|
|
|
150
|
-
(preset.pivot.columns ?? []).filter(_ => !pivotColumns.find(i => i.key === _.key))
|
|
159
|
+
/*(preset.pivot.columns ?? []).filter(_ => !pivotColumns.find(i => i.key === _.key))
|
|
151
160
|
.forEach(_ => {
|
|
152
161
|
_.visible = false
|
|
153
162
|
pivotColumns.push(_)
|
|
154
|
-
})
|
|
163
|
+
})*/
|
|
155
164
|
|
|
156
165
|
preset.pivot.columns = pivotColumns
|
|
157
166
|
|
|
@@ -177,9 +186,10 @@ const generateTotalColumns = (preset, items) => {
|
|
|
177
186
|
}
|
|
178
187
|
|
|
179
188
|
export {
|
|
180
|
-
|
|
189
|
+
getPresetUid,
|
|
190
|
+
generatePivotColumns,
|
|
191
|
+
generateTotalColumns,
|
|
181
192
|
pickColumns,
|
|
182
193
|
setupConfig,
|
|
183
|
-
|
|
184
|
-
generateTotalColumns
|
|
194
|
+
sortsFn,
|
|
185
195
|
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="!action" :class="$style.comp" class="flex items-center justify-center">
|
|
3
|
+
<p class="text-text-400">No action selected</p>
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
<div v-else class="flex-1 flex flex-col">
|
|
7
|
+
|
|
8
|
+
<div class="flex flex-row items-center p-2 pt-3 px-6 bg-base-300 border-b-[1px] border-text-50">
|
|
9
|
+
<div class="flex-1">
|
|
10
|
+
<strong>{{ action.name }}</strong>
|
|
11
|
+
</div>
|
|
12
|
+
<Button ref="saveBtn" :state="canSave ? 1 : -1" class="w-[80px] rounded-full" @click="save">Save</Button>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div class="flex-1 flex flex-row">
|
|
16
|
+
<div class="flex-1 p-12 overflow-auto">
|
|
17
|
+
<UserActionItem :config="config"
|
|
18
|
+
:item="action"
|
|
19
|
+
:removable="false"
|
|
20
|
+
@select="(item) => config.selectedUid = item.uid" />
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div :style="sidebarStyle"
|
|
24
|
+
class="relative flex flex-col border-l-[1px] border-text-50 panel-400 overflow-hidden">
|
|
25
|
+
<div :class="$style.resize1"
|
|
26
|
+
@mousedown="(e) => $util.dragResize(e, resize1)"></div>
|
|
27
|
+
|
|
28
|
+
<UserActionProps ref="userActionProps" :instance="selectedItem" />
|
|
29
|
+
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script>
|
|
38
|
+
|
|
39
|
+
import UserActionItem from "../UserActionBuilder/UserActionItem.vue";
|
|
40
|
+
import UserActionProps from "../UserActionBuilder/UserActionProps.vue";
|
|
41
|
+
|
|
42
|
+
const findComponents = (items, uid) => {
|
|
43
|
+
for (let item of items) {
|
|
44
|
+
if (item.uid === uid)
|
|
45
|
+
return item
|
|
46
|
+
|
|
47
|
+
if (item.items) {
|
|
48
|
+
const component = findComponents(item.items, uid)
|
|
49
|
+
if (component)
|
|
50
|
+
return component
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default{
|
|
56
|
+
components: {UserActionProps, UserActionItem},
|
|
57
|
+
|
|
58
|
+
computed: {
|
|
59
|
+
|
|
60
|
+
canSave(){
|
|
61
|
+
return JSON.stringify(this.action) !== this.initialAction
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
selectedItem(){
|
|
65
|
+
if (!this.config.selectedUid) return
|
|
66
|
+
if (!this.action) return
|
|
67
|
+
|
|
68
|
+
if(this.action.uid === this.config.selectedUid)
|
|
69
|
+
return this.action
|
|
70
|
+
return findComponents(this.action.items ?? [], this.config.selectedUid)
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
sidebar(){
|
|
74
|
+
if (!this.config.actionSidebar)
|
|
75
|
+
this.config.actionSidebar = {
|
|
76
|
+
open: true,
|
|
77
|
+
width: 300
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return this.config.actionSidebar
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
sidebarStyle() {
|
|
84
|
+
return {
|
|
85
|
+
width: this.sidebar.width + 'px'
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
data(){
|
|
92
|
+
return {
|
|
93
|
+
action: null,
|
|
94
|
+
initialAction: null,
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
inject: [ 'socket' ],
|
|
99
|
+
|
|
100
|
+
props: {
|
|
101
|
+
|
|
102
|
+
config: Object,
|
|
103
|
+
controller: String,
|
|
104
|
+
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
methods: {
|
|
108
|
+
|
|
109
|
+
load(uid){
|
|
110
|
+
if(!uid) return
|
|
111
|
+
|
|
112
|
+
this.socket.send(`${this.controller}.open-action`, { uid })
|
|
113
|
+
.then(_ => {
|
|
114
|
+
this.action = _.item
|
|
115
|
+
this.initialAction = JSON.stringify(this.action)
|
|
116
|
+
})
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
resize1(w) {
|
|
120
|
+
if (this.sidebar.width - w >= 200 && this.sidebar.width - w <= 600) {
|
|
121
|
+
this.sidebar.width -= w
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
save(){
|
|
126
|
+
this.$refs.saveBtn.setState(2)
|
|
127
|
+
this.socket.send(`${this.controller}.save-action`, {
|
|
128
|
+
item: this.action
|
|
129
|
+
})
|
|
130
|
+
.then(_ => this.initialAction = JSON.stringify(this.action))
|
|
131
|
+
.catch(err => this.alert(err))
|
|
132
|
+
.finally(_ => this.$refs.saveBtn?.resetState())
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
watch: {
|
|
138
|
+
|
|
139
|
+
'$route.query.actionUid': {
|
|
140
|
+
immediate: true,
|
|
141
|
+
handler(to){
|
|
142
|
+
this.load(to)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
</script>
|
|
151
|
+
|
|
152
|
+
<style module>
|
|
153
|
+
|
|
154
|
+
.comp{
|
|
155
|
+
@apply flex-1;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.resize1 {
|
|
159
|
+
@apply w-[3px] cursor-ew-resize absolute top-0 left-0 bottom-0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
</style>
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="cConfig" :class="$style.comp">
|
|
3
|
+
|
|
4
|
+
<div :style="sidebarStyle"
|
|
5
|
+
class="relative flex flex-col border-r-[1px] border-text-50 panel-400 overflow-hidden">
|
|
6
|
+
|
|
7
|
+
<div v-if="page !== 'Actions'" class="flex-1 flex flex-col">
|
|
8
|
+
<div class="p-5">
|
|
9
|
+
<h5>Bot Settings</h5>
|
|
10
|
+
<br />
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div class="flex-1">
|
|
14
|
+
|
|
15
|
+
<div class="flex flex-col divide-y divide-text-50 border-y-[1px] border-text-50">
|
|
16
|
+
<router-link :to="{ query:{ t:'actions' } }" type="button" class="p-3 px-5 text-left">Actions</router-link>
|
|
17
|
+
<router-link :to="{ query:{ t:'knowledge' } }" type="button" class="p-3 px-5 text-left">Knowledge</router-link>
|
|
18
|
+
<router-link :to="{ query:{ t:'classifications' } }" type="button" class="p-3 px-5 text-left">Classifications</router-link>
|
|
19
|
+
<router-link :to="{ query:{ t:'settings' } }" type="button" class="p-3 px-5 text-left">Settings</router-link>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div v-else-if="page === 'Actions'" class="flex-1 flex flex-col">
|
|
26
|
+
<div class="p-5 flex flex-row gap-2">
|
|
27
|
+
<button type="button" @click="$router.replace({ query:{} })">
|
|
28
|
+
<svg width="16" height="16" class="fill-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M447.1 256C447.1 273.7 433.7 288 416 288H109.3l105.4 105.4c12.5 12.5 12.5 32.75 0 45.25C208.4 444.9 200.2 448 192 448s-16.38-3.125-22.62-9.375l-160-160c-12.5-12.5-12.5-32.75 0-45.25l160-160c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25L109.3 224H416C433.7 224 447.1 238.3 447.1 256z"/></svg>
|
|
29
|
+
</button>
|
|
30
|
+
<h5>Actions</h5>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<br />
|
|
34
|
+
|
|
35
|
+
<ListItem :items="actions"
|
|
36
|
+
container-class="divide-y divide-text-50"
|
|
37
|
+
@reorder="(from, to) => { actions.splice(to, 0, actions.splice(from, 1)[0]); }">
|
|
38
|
+
<template v-slot="{ item }">
|
|
39
|
+
<div class="p-3 hover:bg-base-500 flex flex-row gap-3 items-center">
|
|
40
|
+
<div data-reorder>
|
|
41
|
+
<svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M496 288H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm0-128H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16z"/></svg>
|
|
42
|
+
</div>
|
|
43
|
+
<label class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap"
|
|
44
|
+
@click="$router.push({ query:{ t:'actions', actionUid:item.uid } })">
|
|
45
|
+
{{ item.name }}
|
|
46
|
+
</label>
|
|
47
|
+
<button type="button" @click="">
|
|
48
|
+
<svg width="14" height="14" class="fill-text-300 hover:fill-red-600" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"/></svg>
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
</ListItem>
|
|
53
|
+
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div class="flex flex-col border-t-[1px] border-text-50 relative" :style="bottombarStyle">
|
|
57
|
+
<div :class="$style.resize2"
|
|
58
|
+
@mousedown="(e) => $util.dragResize(e, resize2)"></div>
|
|
59
|
+
|
|
60
|
+
<UserActionConsole class="flex-1"
|
|
61
|
+
ref="console"
|
|
62
|
+
@test-message="testMessage"
|
|
63
|
+
@test-reset="testReset" />
|
|
64
|
+
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div :class="$style.resize1"
|
|
68
|
+
@mousedown="(e) => $util.dragResize(e, resize1)"></div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div v-if="page" class="flex-1 overflow-y-auto flex flex-col">
|
|
72
|
+
|
|
73
|
+
<component :is="`BotEditor${page}`"
|
|
74
|
+
:config="config"
|
|
75
|
+
:controller="controller" />
|
|
76
|
+
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
81
|
+
|
|
82
|
+
<script>
|
|
83
|
+
|
|
84
|
+
import {capitalize} from "../utils/helpers.mjs";
|
|
85
|
+
import BotEditorActions from "./BotEditor/BotEditorActions.vue";
|
|
86
|
+
import VirtualGrid from "../components/VirtualGrid.vue";
|
|
87
|
+
import UserActionConsole from "./UserActionBuilder/UserActionConsole.vue";
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
export default{
|
|
91
|
+
|
|
92
|
+
components: {
|
|
93
|
+
UserActionConsole,
|
|
94
|
+
VirtualGrid,
|
|
95
|
+
BotEditorActions,
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
inject: [ 'alert', 'confirm', 'socket', 'toast' ],
|
|
99
|
+
|
|
100
|
+
computed: {
|
|
101
|
+
|
|
102
|
+
bottombar(){
|
|
103
|
+
if (!this.cConfig.bottombar)
|
|
104
|
+
this.cConfig.bottombar = {
|
|
105
|
+
open: true,
|
|
106
|
+
height: 240
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return this.cConfig.bottombar
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
bottombarStyle(){
|
|
113
|
+
return {
|
|
114
|
+
height: !this.bottombar.open ? 0 : this.bottombar.height + 'px'
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
cConfig(){
|
|
119
|
+
return this.config
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
sidebar() {
|
|
123
|
+
if (!this.cConfig.sidebar || !('open' in this.cConfig.sidebar))
|
|
124
|
+
this.cConfig.sidebar = {
|
|
125
|
+
open: true,
|
|
126
|
+
width: 360
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return this.cConfig.sidebar
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
sidebarStyle() {
|
|
133
|
+
return {
|
|
134
|
+
width: !this.sidebar.open ? 0 : this.sidebar.width + 'px'
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
data(){
|
|
141
|
+
return {
|
|
142
|
+
actions: null,
|
|
143
|
+
page: '',
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
methods: {
|
|
148
|
+
|
|
149
|
+
load(){
|
|
150
|
+
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
loadActions(){
|
|
154
|
+
this.socket.send(`${this.controller}.load-actions`, {})
|
|
155
|
+
.then(_ => {
|
|
156
|
+
this.actions = _.items
|
|
157
|
+
})
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
resize1(w) {
|
|
161
|
+
if (this.sidebar.width + w >= 200 && this.sidebar.width + w <= 600) {
|
|
162
|
+
this.sidebar.width += w
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
resize2(_, h) {
|
|
167
|
+
if (this.bottombar.height - h >= 200 && this.bottombar.height - h <= 400) {
|
|
168
|
+
this.bottombar.height -= h
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
testMessage(){
|
|
173
|
+
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
testReset(){
|
|
177
|
+
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
props: {
|
|
183
|
+
|
|
184
|
+
config: Object,
|
|
185
|
+
configSrc: String,
|
|
186
|
+
|
|
187
|
+
controller: String,
|
|
188
|
+
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
watch: {
|
|
192
|
+
|
|
193
|
+
'$route.query.t': {
|
|
194
|
+
immediate: true,
|
|
195
|
+
handler(to){
|
|
196
|
+
this.page = to ? capitalize(to) : ''
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
page: {
|
|
201
|
+
immediate: true,
|
|
202
|
+
handler(to){
|
|
203
|
+
if(this[`load${to}`])
|
|
204
|
+
this[`load${to}`]()
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
</script>
|
|
213
|
+
|
|
214
|
+
<style module>
|
|
215
|
+
|
|
216
|
+
.comp{
|
|
217
|
+
@apply flex flex-row;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.resize1 {
|
|
221
|
+
@apply w-[3px] cursor-ew-resize absolute top-0 right-0 bottom-0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.resize2 {
|
|
225
|
+
@apply h-[3px] cursor-n-resize absolute top-0 right-0 left-0 bg-red-500;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
</style>
|