@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/components/List.vue
CHANGED
|
@@ -8,9 +8,17 @@
|
|
|
8
8
|
class="relative flex flex-col border-r-[1px] border-text-50 panel-400"
|
|
9
9
|
:style="sidebarStyle">
|
|
10
10
|
|
|
11
|
-
<PresetBar :config="
|
|
11
|
+
<PresetBar :config="cConfig"
|
|
12
|
+
:presets="presets"
|
|
13
|
+
:shared-presets="sharedPresets"
|
|
12
14
|
class="flex-1"
|
|
15
|
+
:can-share="!!sharingSrc"
|
|
16
|
+
:sharing-src="sharingSrc"
|
|
17
|
+
:remove-sharing-src="removeSharingSrc"
|
|
13
18
|
:enumCache="enumCache"
|
|
19
|
+
@duplicate="duplicate"
|
|
20
|
+
@remove="removePreset"
|
|
21
|
+
@remove-shared="removeShared"
|
|
14
22
|
@apply="load">
|
|
15
23
|
|
|
16
24
|
<template #toolbar>
|
|
@@ -26,7 +34,7 @@
|
|
|
26
34
|
@mousedown="(e) => $util.dragResize(e, resize1)"></div>
|
|
27
35
|
</div>
|
|
28
36
|
|
|
29
|
-
<div class="flex-1 flex flex-col">
|
|
37
|
+
<div class="flex-1 flex flex-col" v-if="preset">
|
|
30
38
|
|
|
31
39
|
<div class="flex-1 flex flex-col" :class="containerClass">
|
|
32
40
|
<slot name="head"
|
|
@@ -44,7 +52,7 @@
|
|
|
44
52
|
<small class="text-text-400 text-xs">{{ title ?? 'Untitled' }}</small>
|
|
45
53
|
<div class="flex flex-row items-baseline gap-1">
|
|
46
54
|
<h5 class="whitespace-nowrap relative top-[-2px] text-ellipsis overflow-hidden group-hover:text-primary">
|
|
47
|
-
{{ preset.name ?? 'Preset Name' }}
|
|
55
|
+
{{ preset.params.name ?? 'Preset Name' }}
|
|
48
56
|
</h5>
|
|
49
57
|
<svg width="13" height="13" class="fill-text group-hover:fill-primary relative top-[-1px]" 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 246.6l-127.1 128C176.4 380.9 168.2 384 160 384s-16.38-3.125-22.63-9.375l-127.1-128C.2244 237.5-2.516 223.7 2.438 211.8S19.07 192 32 192h255.1c12.94 0 24.62 7.781 29.58 19.75S319.8 237.5 310.6 246.6z"/></svg>
|
|
50
58
|
</div>
|
|
@@ -53,13 +61,13 @@
|
|
|
53
61
|
<div class="flex flex-col min-w-[300px] divide-y divide-text-50">
|
|
54
62
|
|
|
55
63
|
<div class="p-3 flex flex-col gap-1 bg-base-300">
|
|
56
|
-
<button v-for="(preset, idx) in
|
|
64
|
+
<button v-for="(preset, idx) in presets"
|
|
57
65
|
class="p-2 px-5 text-left flex flex-row items-center rounded-md"
|
|
58
|
-
:class="
|
|
66
|
+
:class="cConfig.params.presetIdx === preset.uid ? 'bg-primary-200 text-white' : 'hover:bg-primary-100'"
|
|
59
67
|
type="button"
|
|
60
|
-
@click="selectPreset(
|
|
68
|
+
@click="selectPreset(preset.uid)">
|
|
61
69
|
<label class="flex-1 pr-12">
|
|
62
|
-
{{ preset.name }}
|
|
70
|
+
{{ preset.params.name }}
|
|
63
71
|
</label>
|
|
64
72
|
<div class="p-1">
|
|
65
73
|
<div v-if="idx < 10"
|
|
@@ -120,57 +128,77 @@
|
|
|
120
128
|
</div>
|
|
121
129
|
</slot>
|
|
122
130
|
|
|
123
|
-
<div
|
|
124
|
-
<
|
|
125
|
-
|
|
131
|
+
<div class="flex-1 flex" ref="content">
|
|
132
|
+
<div v-if="readyState === 2" class="flex-1 flex items-center justify-center">
|
|
133
|
+
<svg class="animate-spin" width="36" height="36" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
|
134
|
+
</div>
|
|
126
135
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
<div v-else-if="presetView === 'table' || pivotEnabled" class="flex-1 flex" :class="pivotEnabled ? 'p-3 panel-400 md:p-0' : ''">
|
|
137
|
+
<VirtualTable
|
|
138
|
+
ref="table"
|
|
139
|
+
:columns="columns"
|
|
140
|
+
class="flex-1 rounded-lg panel-400"
|
|
141
|
+
:items="data.items"
|
|
142
|
+
:enumCache="enumCache"
|
|
143
|
+
@scroll-end="loadNext"
|
|
144
|
+
@item-click="onTableItemClick">
|
|
145
|
+
|
|
146
|
+
<template v-for="(_, slot) in headerSlots" #[slot]="{ item, index }">
|
|
147
|
+
<div :class="getHeader(slot.replace('col-', ''))">
|
|
148
|
+
<slot :name="slot" :item="item" :index="index"></slot>
|
|
149
|
+
</div>
|
|
150
|
+
</template>
|
|
142
151
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
<template v-for="(_, slot) in contentSlots" #[slot]="{ item, index }">
|
|
153
|
+
<slot :name="slot" :item="item" :index="index"></slot>
|
|
154
|
+
</template>
|
|
155
|
+
|
|
156
|
+
<template #end>
|
|
157
|
+
<div v-if="data?.hasNext" class="flex justify-center p-3">
|
|
158
|
+
<svg v-if="readyState === 4" class="animate-spin aspect-square w-[14px] h-[14px] fill-text-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
|
159
|
+
<button v-else type="button" class="text-text-300" @click="loadNext()">
|
|
160
|
+
{{ $t('Load More' )}}
|
|
161
|
+
</button>
|
|
162
|
+
</div>
|
|
163
|
+
</template>
|
|
146
164
|
|
|
147
|
-
|
|
148
|
-
|
|
165
|
+
</VirtualTable>
|
|
166
|
+
</div>
|
|
149
167
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
168
|
+
<VirtualGrid v-else-if="presetView === 'grid'"
|
|
169
|
+
ref="grid"
|
|
170
|
+
:items="dataItems"
|
|
171
|
+
:column="computedGridColumn"
|
|
172
|
+
:class="gridClass"
|
|
173
|
+
@scroll-end="loadNext"
|
|
174
|
+
:container-class="`${gridContainerClass}`"
|
|
175
|
+
:config="config">
|
|
176
|
+
<template #item="{ item }">
|
|
177
|
+
<slot name="gridItem" :item="item" :enumCache="enumCache" :getEnumText="getEnumText">
|
|
178
|
+
<div class="flex flex-row panel-400 rounded-lg overflow-hidden md:rounded-lg overflow-hidden p-3 gap-3">
|
|
179
|
+
<div>
|
|
180
|
+
<Image :src="item.imageUrl" class="bg-text-50 w-[64px] h-[64px] rounded-lg" />
|
|
181
|
+
</div>
|
|
182
|
+
<div class="flex-1 flex flex-col leading-tight">
|
|
183
|
+
<small>{{ item.code }}</small>
|
|
184
|
+
<strong>{{ item.name }}</strong>
|
|
185
|
+
</div>
|
|
167
186
|
</div>
|
|
187
|
+
</slot>
|
|
188
|
+
</template>
|
|
189
|
+
|
|
190
|
+
<template #end>
|
|
191
|
+
<div v-if="data?.hasNext" class="flex justify-center p-3">
|
|
192
|
+
<svg v-if="readyState === 4" class="animate-spin aspect-square w-[14px] h-[14px] fill-text-300" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
|
193
|
+
<button v-else type="button" class="text-text-300" @click="loadNext()">
|
|
194
|
+
{{ $t('Load More' )}}
|
|
195
|
+
</button>
|
|
168
196
|
</div>
|
|
169
|
-
</
|
|
170
|
-
</
|
|
171
|
-
</VirtualGrid>
|
|
197
|
+
</template>
|
|
198
|
+
</VirtualGrid>
|
|
172
199
|
|
|
173
|
-
|
|
200
|
+
<PresetSelector ref="presetSelector" :config="config" @select="load" />
|
|
201
|
+
</div>
|
|
174
202
|
</div>
|
|
175
203
|
|
|
176
204
|
<div v-if="extBar.open && pivotEnabled"
|
|
@@ -182,7 +210,7 @@
|
|
|
182
210
|
|
|
183
211
|
<VirtualTable v-else-if="presetView === 'table'"
|
|
184
212
|
ref="table"
|
|
185
|
-
:columns="preset.columns"
|
|
213
|
+
:columns="preset.params.columns"
|
|
186
214
|
class="flex-1 rounded-lg panel-400"
|
|
187
215
|
:items="data.extItems"
|
|
188
216
|
:enumCache="enumCache"
|
|
@@ -247,64 +275,167 @@
|
|
|
247
275
|
|
|
248
276
|
import VirtualTable from "./VirtualTable.vue";
|
|
249
277
|
import VirtualGrid from "./VirtualGrid.vue";
|
|
250
|
-
import throttle from "lodash/throttle";
|
|
251
278
|
import PresetSelector from "../widgets/PresetSelector.vue";
|
|
252
|
-
import
|
|
253
|
-
import { generatePivotColumns, generateTotalColumns, sortsFn } from "../utils/preset-selector.mjs";
|
|
279
|
+
import {generatePivotColumns, generateTotalColumns, setupConfig, sortsFn} from "../utils/preset-selector.mjs";
|
|
254
280
|
import PresetBar from "../widgets/PresetBar.vue";
|
|
281
|
+
import {invokeAfterIdle} from "../utils/helpers.mjs";
|
|
255
282
|
|
|
256
283
|
export default{
|
|
257
284
|
|
|
258
|
-
|
|
285
|
+
components: {PresetBar, PresetSelector, VirtualGrid, VirtualTable},
|
|
259
286
|
|
|
260
|
-
|
|
287
|
+
computed: {
|
|
261
288
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
289
|
+
columns(){
|
|
290
|
+
if((this.preset?.params.pivot ?? {}).enabled){
|
|
291
|
+
return this.preset.params.pivot.columns ?? []
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
for(let idx in this.preset?.columns){
|
|
295
|
+
if(this.preset.params.columns[idx].defaultFormat){
|
|
296
|
+
this.preset.params.columns[idx].format = this.preset.params.columns[idx].defaultFormat
|
|
297
|
+
delete this.preset.params.columns[idx].defaultFormat
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return this.preset?.params.columns
|
|
266
302
|
},
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
validator(value) {
|
|
274
|
-
return ['grid', 'table'].includes(value)
|
|
303
|
+
|
|
304
|
+
contentSlots(){
|
|
305
|
+
const slots = {}
|
|
306
|
+
for(let key in this.$slots){
|
|
307
|
+
if(!key.startsWith('col-'))
|
|
308
|
+
slots[key] = this.$slots[key]
|
|
275
309
|
}
|
|
310
|
+
return slots
|
|
276
311
|
},
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
312
|
+
|
|
313
|
+
headerSlots(){
|
|
314
|
+
const slots = {}
|
|
315
|
+
for(let key in this.$slots){
|
|
316
|
+
if(key.startsWith('col-'))
|
|
317
|
+
slots[key] = this.$slots[key]
|
|
318
|
+
}
|
|
319
|
+
return slots
|
|
281
320
|
},
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
321
|
+
|
|
322
|
+
computedGridColumn(){
|
|
323
|
+
return this.$device.type === 'mobile' ? 1 :
|
|
324
|
+
(this.gridColumn ?? 3)
|
|
285
325
|
},
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
type:
|
|
289
|
-
default: "sidebar"
|
|
326
|
+
|
|
327
|
+
computedPresetMode(){
|
|
328
|
+
return this.$device.type === 'mobile' ? 'popup' : this.presetMode
|
|
290
329
|
},
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
330
|
+
|
|
331
|
+
dataItems(){
|
|
332
|
+
if((this.preset.sorts ?? []).length > 0){
|
|
333
|
+
return (this.data.items ?? []).sort((a, b) => {
|
|
334
|
+
return sortsFn(a, b, this.preset.sorts, 0)
|
|
335
|
+
})
|
|
336
|
+
}
|
|
337
|
+
else{
|
|
338
|
+
return this.data.items ?? []
|
|
339
|
+
}
|
|
294
340
|
},
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
341
|
+
|
|
342
|
+
preset(){
|
|
343
|
+
return this.presets[0]
|
|
344
|
+
},
|
|
345
|
+
|
|
346
|
+
presets(){
|
|
347
|
+
return (this.cConfig?.presets ?? [])
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
presetView(){
|
|
351
|
+
if(!this.preset.view)
|
|
352
|
+
this.preset.view = 'table'
|
|
353
|
+
|
|
354
|
+
return this.$device.type === 'mobile' ? 'grid' :
|
|
355
|
+
(this.view ?? this.preset.view)
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
sidebar(){
|
|
359
|
+
if(!this.cConfig.sidebar || !('open' in this.cConfig.sidebar))
|
|
360
|
+
this.cConfig.sidebar = {
|
|
361
|
+
open: false,
|
|
362
|
+
width: 270
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return this.cConfig.sidebar
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
sidebarStyle(){
|
|
369
|
+
return {
|
|
370
|
+
width: !this.sidebar.open ? 0 : this.sidebar.width + 'px'
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
extBar(){
|
|
375
|
+
if(!this.cConfig.extbar)
|
|
376
|
+
this.cConfig.extbar = {
|
|
377
|
+
open: false,
|
|
378
|
+
height: Math.round(window.innerHeight / 2.2)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return this.cConfig.extbar
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
extStyle(){
|
|
385
|
+
return {
|
|
386
|
+
height: this.extBar.height + "px"
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
|
|
390
|
+
pivotEnabled(){
|
|
391
|
+
return ((this.preset ?? {}).pivot ?? {}).enabled
|
|
392
|
+
},
|
|
393
|
+
|
|
394
|
+
cConfig(){
|
|
395
|
+
return this.config ?? this._config
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
data(){
|
|
401
|
+
return {
|
|
402
|
+
readyState: 0,
|
|
403
|
+
data: {
|
|
404
|
+
itemsPerPage: 16,
|
|
405
|
+
},
|
|
406
|
+
observer: null,
|
|
407
|
+
compPrefix: '',
|
|
408
|
+
enumCache: {},
|
|
409
|
+
extItems: null,
|
|
410
|
+
lastEnumItems: null,
|
|
411
|
+
|
|
412
|
+
_config: {}
|
|
298
413
|
}
|
|
299
414
|
},
|
|
300
415
|
|
|
416
|
+
emits: [ 'after-load', 'open-preset', 'signal', 'pivot-item-click' ],
|
|
417
|
+
|
|
418
|
+
inject: [ 'socket', 'toast' ],
|
|
419
|
+
|
|
301
420
|
methods: {
|
|
302
421
|
|
|
422
|
+
calcItemsPerPage(){
|
|
423
|
+
|
|
424
|
+
if(this.$refs.content){
|
|
425
|
+
this.data.itemsPerPage = Math.round((this.$refs.content.clientHeight - 36) / 36) + 3
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
},
|
|
429
|
+
|
|
430
|
+
duplicate(){
|
|
431
|
+
this.saveConfig(false, true)
|
|
432
|
+
},
|
|
433
|
+
|
|
303
434
|
getEnumText(key, value){
|
|
304
435
|
|
|
305
436
|
let enumText
|
|
306
437
|
|
|
307
|
-
const column = this.
|
|
438
|
+
const column = this.cConfig.columns.find(_ => _.key === key)
|
|
308
439
|
|
|
309
440
|
if(Array.isArray(column.typeParams)){
|
|
310
441
|
const typeParam = (column.typeParams ?? []).filter((_) => _.value === value).pop()
|
|
@@ -329,14 +460,14 @@ export default{
|
|
|
329
460
|
},
|
|
330
461
|
|
|
331
462
|
load(){
|
|
332
|
-
if(this.src){
|
|
333
|
-
if(!this.preset.columns){
|
|
334
|
-
this.preset.columns = JSON.parse(JSON.stringify(this.config.columns))
|
|
463
|
+
if(this.src && this.preset){
|
|
464
|
+
if(!this.preset.params.columns){
|
|
465
|
+
this.preset.params.columns = JSON.parse(JSON.stringify(this.config.params.columns))
|
|
335
466
|
}
|
|
336
467
|
|
|
337
468
|
this.readyState = 2
|
|
338
469
|
return this.socket.send(this.src, {
|
|
339
|
-
...this.preset,
|
|
470
|
+
...this.preset.params,
|
|
340
471
|
itemsPerPage: this.data.itemsPerPage,
|
|
341
472
|
})
|
|
342
473
|
.then(data => {
|
|
@@ -359,57 +490,26 @@ export default{
|
|
|
359
490
|
((this.data ?? {}).hasNext !== false) &&
|
|
360
491
|
!(this.preset.pivot ?? {}).enabled) {
|
|
361
492
|
|
|
362
|
-
|
|
363
|
-
|
|
493
|
+
this.readyState = 4
|
|
364
494
|
this.socket.send(this.src, {
|
|
365
495
|
...this.preset,
|
|
366
496
|
itemsPerPage: this.data.itemsPerPage,
|
|
367
497
|
afterItem: this.data.items[this.data.items.length - 1],
|
|
368
498
|
})
|
|
369
499
|
.then(data => {
|
|
370
|
-
//console.log('next id', data.items[0].id)
|
|
371
|
-
|
|
372
500
|
this.data.items.push(...data.items)
|
|
373
501
|
this.loadEnums(data.items)
|
|
374
502
|
})
|
|
375
503
|
.catch(err => this.toast(err))
|
|
504
|
+
.finally(_ => this.readyState = 1)
|
|
376
505
|
}
|
|
377
506
|
return new Promise(resolve => resolve())
|
|
378
507
|
},
|
|
379
508
|
|
|
380
|
-
loadPreset(){
|
|
381
|
-
if(!Object.keys(this.$route.query).map(_ => _.toLowerCase()).includes('reset')){
|
|
382
|
-
if(this.presetKey){
|
|
383
|
-
return this.socket.send('user.preset', { key:this.presetKey })
|
|
384
|
-
.then(config => {
|
|
385
|
-
Object.assign(this.config, config)
|
|
386
|
-
})
|
|
387
|
-
}
|
|
388
|
-
return new Promise(resolve => resolve())
|
|
389
|
-
}
|
|
390
|
-
else{
|
|
391
|
-
return new Promise((resolve) => {
|
|
392
|
-
this.savePreset()
|
|
393
|
-
|
|
394
|
-
const query = {}
|
|
395
|
-
for(let key in this.$route.query){
|
|
396
|
-
if(key.toLowerCase() !== 'reset')
|
|
397
|
-
query[key] = this.$route.query[key]
|
|
398
|
-
}
|
|
399
|
-
this.$router.replace({
|
|
400
|
-
...this.$route,
|
|
401
|
-
query
|
|
402
|
-
})
|
|
403
|
-
|
|
404
|
-
resolve()
|
|
405
|
-
})
|
|
406
|
-
}
|
|
407
|
-
},
|
|
408
|
-
|
|
409
509
|
loadEnums(items){
|
|
410
510
|
|
|
411
|
-
for(let i in this.preset.columns){
|
|
412
|
-
const column = this.preset.columns[i]
|
|
511
|
+
for(let i in this.preset.params.columns){
|
|
512
|
+
const column = this.preset.params.columns[i]
|
|
413
513
|
|
|
414
514
|
if(column.enumSrc) {
|
|
415
515
|
|
|
@@ -431,7 +531,6 @@ export default{
|
|
|
431
531
|
columns: [
|
|
432
532
|
{ key:attr, visible:true }
|
|
433
533
|
],
|
|
434
|
-
itemsPerPage: 1000,
|
|
435
534
|
filters: [
|
|
436
535
|
{
|
|
437
536
|
key:key, value: [ { operator:'in', value:reqItems } ]
|
|
@@ -472,10 +571,10 @@ export default{
|
|
|
472
571
|
],
|
|
473
572
|
pivot: null
|
|
474
573
|
})
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
574
|
+
.then((res) => {
|
|
575
|
+
this.data.extItems = res.items
|
|
576
|
+
})
|
|
577
|
+
.finally(_ => this.readyState = 1)
|
|
479
578
|
},
|
|
480
579
|
|
|
481
580
|
loadExtNext(){
|
|
@@ -497,26 +596,78 @@ export default{
|
|
|
497
596
|
},
|
|
498
597
|
|
|
499
598
|
resize1(w){
|
|
500
|
-
if(this.
|
|
501
|
-
this.
|
|
599
|
+
if(this.cConfig.sidebar.width + w >= 270 && this.cConfig.sidebar.width + w <= 600){
|
|
600
|
+
this.cConfig.sidebar.width += w
|
|
502
601
|
}
|
|
503
602
|
},
|
|
504
603
|
|
|
505
|
-
selectPreset(
|
|
506
|
-
|
|
507
|
-
|
|
604
|
+
selectPreset(uid){
|
|
605
|
+
const preset = this.presets.find(_ => _.uid === uid)
|
|
606
|
+
|
|
607
|
+
if(preset){
|
|
608
|
+
this.cConfig.presetIdx = uid
|
|
508
609
|
this.load()
|
|
509
610
|
this.$refs.presetSelector.close()
|
|
510
611
|
this.$refs.contextMenu.close()
|
|
511
612
|
}
|
|
512
613
|
},
|
|
513
614
|
|
|
514
|
-
|
|
515
|
-
if(this.
|
|
516
|
-
|
|
517
|
-
|
|
615
|
+
async loadDefaultConfig(save = false){
|
|
616
|
+
if(typeof this.defaultConfig !== 'function') return
|
|
617
|
+
|
|
618
|
+
this._config = setupConfig(JSON.parse(JSON.stringify((await this.defaultConfig()).default)))
|
|
619
|
+
|
|
620
|
+
this.saveConfig()
|
|
621
|
+
},
|
|
622
|
+
|
|
623
|
+
async loadConfig(){
|
|
624
|
+
if(!this.presetKey || !this.presetSrc) return
|
|
625
|
+
|
|
626
|
+
if(Object.keys(this.$route.query).map(_ => _.toLowerCase()).includes('reset')){
|
|
627
|
+
await this.loadDefaultConfig(true)
|
|
628
|
+
|
|
629
|
+
this.$router.replace({ query: {
|
|
630
|
+
...this.$route.query,
|
|
631
|
+
reset: undefined
|
|
632
|
+
}})
|
|
633
|
+
}
|
|
634
|
+
else{
|
|
635
|
+
return this.socket.send(this.presetSrc, { key:this.presetKey })
|
|
636
|
+
.then(async (config) => {
|
|
637
|
+
this._config = config
|
|
638
|
+
})
|
|
639
|
+
.catch(() => {})
|
|
518
640
|
}
|
|
519
|
-
},
|
|
641
|
+
},
|
|
642
|
+
|
|
643
|
+
saveConfig: invokeAfterIdle(function(){
|
|
644
|
+
if(!this.presetKey || !this.presetSrc) return
|
|
645
|
+
|
|
646
|
+
return this.socket.send(this.presetSrc, {
|
|
647
|
+
key:this.presetKey,
|
|
648
|
+
config: this.cConfig
|
|
649
|
+
})
|
|
650
|
+
.catch(() => {})
|
|
651
|
+
}),
|
|
652
|
+
|
|
653
|
+
async removePreset(preset){
|
|
654
|
+
return this.socket.send(this.presetSrc, {
|
|
655
|
+
key: this.presetKey,
|
|
656
|
+
removePreset: preset
|
|
657
|
+
})
|
|
658
|
+
.catch(() => {})
|
|
659
|
+
},
|
|
660
|
+
|
|
661
|
+
async removeShared(uid){
|
|
662
|
+
return this.socket.send(this.presetSrc, {
|
|
663
|
+
key: this.presetKey,
|
|
664
|
+
removeShared: [ uid ]
|
|
665
|
+
})
|
|
666
|
+
.then(_ => {
|
|
667
|
+
this.sharedPresets.splice(this.sharedPresets.findIndex(_ => _.uid === uid), 1)
|
|
668
|
+
})
|
|
669
|
+
.catch(() => {})
|
|
670
|
+
},
|
|
520
671
|
|
|
521
672
|
openPreset(){
|
|
522
673
|
|
|
@@ -567,12 +718,12 @@ export default{
|
|
|
567
718
|
...this.preset,
|
|
568
719
|
[key]: items.map(item => item[key])
|
|
569
720
|
})
|
|
570
|
-
|
|
571
|
-
|
|
721
|
+
.then(({ items:nextItems }) => {
|
|
722
|
+
nextItems.forEach(item => this.$util.unshift(this.data.items, item, { highlight: true }))
|
|
572
723
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
724
|
+
const destroyedItems = items.filter(_ => !nextItems.find(i => i[key] === _[key]))
|
|
725
|
+
this.$util.remove(this.data.items, destroyedItems)
|
|
726
|
+
})
|
|
576
727
|
break
|
|
577
728
|
}
|
|
578
729
|
|
|
@@ -587,7 +738,7 @@ export default{
|
|
|
587
738
|
for(let idx in this.preset.pivot.rows){
|
|
588
739
|
const pivotRow = this.preset.pivot.rows[idx]
|
|
589
740
|
const key = pivotRow.key
|
|
590
|
-
const presetColumn = this.preset.columns.find(_ => _.key === key)
|
|
741
|
+
const presetColumn = this.preset.params.columns.find(_ => _.key === key)
|
|
591
742
|
let value = item[pivotRow.key]
|
|
592
743
|
switch(presetColumn.type){
|
|
593
744
|
|
|
@@ -669,10 +820,10 @@ export default{
|
|
|
669
820
|
let [ kk, ...vv ] = column.key.split('-')
|
|
670
821
|
vv = vv.join('-')
|
|
671
822
|
|
|
672
|
-
if(![ 'count', 'countDistinct' ].includes(vv)){
|
|
823
|
+
if(![ 'count', 'countDistinct', 'sum' ].includes(vv)){
|
|
673
824
|
|
|
674
825
|
const key = kk.substring(1)
|
|
675
|
-
const presetColumn = this.preset.columns.find(_ => _.key === key)
|
|
826
|
+
const presetColumn = this.preset.params.columns.find(_ => _.key === key)
|
|
676
827
|
let value = vv
|
|
677
828
|
switch(presetColumn.type){
|
|
678
829
|
|
|
@@ -696,6 +847,17 @@ export default{
|
|
|
696
847
|
}]
|
|
697
848
|
})
|
|
698
849
|
}
|
|
850
|
+
else if([ 'sum' ].includes(vv)){
|
|
851
|
+
const key = kk.substring(1)
|
|
852
|
+
|
|
853
|
+
filters.push({
|
|
854
|
+
key,
|
|
855
|
+
value: [{
|
|
856
|
+
operator: '>',
|
|
857
|
+
value: 0
|
|
858
|
+
}]
|
|
859
|
+
})
|
|
860
|
+
}
|
|
699
861
|
|
|
700
862
|
this.extBar.open = true
|
|
701
863
|
this.extBar.filters = filters
|
|
@@ -727,8 +889,8 @@ export default{
|
|
|
727
889
|
default:
|
|
728
890
|
if(e.code.startsWith('Digit')){
|
|
729
891
|
const idx = parseInt(e.code.substring(5)) - 1
|
|
730
|
-
if(this.
|
|
731
|
-
this.selectPreset(idx)
|
|
892
|
+
if(this.presets[idx]) {
|
|
893
|
+
this.selectPreset(this.presets[idx].uid)
|
|
732
894
|
}
|
|
733
895
|
}
|
|
734
896
|
break
|
|
@@ -739,16 +901,17 @@ export default{
|
|
|
739
901
|
|
|
740
902
|
},
|
|
741
903
|
|
|
742
|
-
components: {PresetBar, PresetSelector, VirtualGrid, VirtualTable},
|
|
743
|
-
|
|
744
904
|
mounted(){
|
|
745
905
|
this.$addResizeListener(this.$el, () => this.compPrefix = this.$util.calculateMediaPrefix(this.$el.clientWidth))
|
|
746
906
|
|
|
747
|
-
this.
|
|
907
|
+
this.loadConfig()
|
|
748
908
|
.then(() => {
|
|
749
909
|
this.readyState = 1
|
|
750
|
-
this
|
|
751
|
-
|
|
910
|
+
this.$nextTick(() => {
|
|
911
|
+
this.calcItemsPerPage()
|
|
912
|
+
this.load()
|
|
913
|
+
this.loadExt()
|
|
914
|
+
})
|
|
752
915
|
})
|
|
753
916
|
|
|
754
917
|
if(this.subscribeKey){
|
|
@@ -759,181 +922,94 @@ export default{
|
|
|
759
922
|
window.addEventListener('keydown', this.onKeyDown)
|
|
760
923
|
},
|
|
761
924
|
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
this.socket.send('user.unsubscribe', {name: this.subscribeKey})
|
|
768
|
-
this.socket.off(this.subscribeKey, this.onSignal)
|
|
769
|
-
}
|
|
770
|
-
},
|
|
771
|
-
|
|
772
|
-
computed: {
|
|
773
|
-
|
|
774
|
-
columns(){
|
|
775
|
-
if((this.preset.pivot ?? {}).enabled){
|
|
776
|
-
return this.preset.pivot.columns ?? []
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
const tableColumns = groupBy(this.preset.columns ?? this.config.columns, 'key')
|
|
780
|
-
|
|
781
|
-
const columns = []
|
|
782
|
-
|
|
783
|
-
for(let row of this.preset.pivot.rows){
|
|
784
|
-
if(!tableColumns[row.key][0].defaultFormat)
|
|
785
|
-
tableColumns[row.key][0].defaultFormat = tableColumns[row.key][0].format
|
|
786
|
-
|
|
787
|
-
switch(row.aggregrate){
|
|
788
|
-
case 'year':
|
|
789
|
-
tableColumns[row.key][0].format = 'YYYY'
|
|
790
|
-
break
|
|
791
|
-
|
|
792
|
-
case 'month':
|
|
793
|
-
tableColumns[row.key][0].format = 'MMM YYYY'
|
|
794
|
-
break
|
|
795
|
-
|
|
796
|
-
case 'date':
|
|
797
|
-
tableColumns[row.key][0].format = 'D MMM YYYY'
|
|
798
|
-
break
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
columns.push(tableColumns[row.key][0])
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
for(let value of this.preset.pivot.values){
|
|
805
|
-
const key = value.aggregrate ? `_${value.key}-${value.aggregrate}` : `_${value.key}-`
|
|
806
|
-
for(let k in tableColumns){
|
|
807
|
-
if(k.startsWith(key)){
|
|
808
|
-
columns.push(tableColumns[k][0])
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
return columns
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
for(let idx in this.preset.columns){
|
|
817
|
-
if(this.preset.columns[idx].defaultFormat){
|
|
818
|
-
this.preset.columns[idx].format = this.preset.columns[idx].defaultFormat
|
|
819
|
-
delete this.preset.columns[idx].defaultFormat
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
return this.preset.columns
|
|
824
|
-
},
|
|
825
|
-
|
|
826
|
-
contentSlots(){
|
|
827
|
-
const slots = {}
|
|
828
|
-
for(let key in this.$slots){
|
|
829
|
-
if(!key.startsWith('col-'))
|
|
830
|
-
slots[key] = this.$slots[key]
|
|
831
|
-
}
|
|
832
|
-
return slots
|
|
833
|
-
},
|
|
834
|
-
|
|
835
|
-
headerSlots(){
|
|
836
|
-
const slots = {}
|
|
837
|
-
for(let key in this.$slots){
|
|
838
|
-
if(key.startsWith('col-'))
|
|
839
|
-
slots[key] = this.$slots[key]
|
|
840
|
-
}
|
|
841
|
-
return slots
|
|
842
|
-
},
|
|
843
|
-
|
|
844
|
-
computedGridColumn(){
|
|
845
|
-
return this.$device.type === 'mobile' ? 1 :
|
|
846
|
-
(this.gridColumn ?? 3)
|
|
847
|
-
},
|
|
848
|
-
|
|
849
|
-
computedPresetMode(){
|
|
850
|
-
return this.$device.type === 'mobile' ? 'popup' : this.presetMode
|
|
925
|
+
props: {
|
|
926
|
+
presetKey: String,
|
|
927
|
+
presetSrc: {
|
|
928
|
+
type: String,
|
|
929
|
+
default: 'user.preset'
|
|
851
930
|
},
|
|
852
931
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
return this.data.items ?? []
|
|
932
|
+
subscribeKey: String,
|
|
933
|
+
src: undefined,
|
|
934
|
+
title: String,
|
|
935
|
+
view: {
|
|
936
|
+
type: String,
|
|
937
|
+
validator(value) {
|
|
938
|
+
return ['grid', 'table'].includes(value)
|
|
861
939
|
}
|
|
862
940
|
},
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
presetView(){
|
|
869
|
-
return this.$device.type === 'mobile' ? 'grid' :
|
|
870
|
-
(this.view ?? this.preset.view)
|
|
941
|
+
gridColumn: [ Number, String ],
|
|
942
|
+
gridClass: {
|
|
943
|
+
type: String,
|
|
944
|
+
default: "flex-1 md:p-3"
|
|
871
945
|
},
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
this.config.sidebar = {
|
|
876
|
-
open: false,
|
|
877
|
-
width: 270
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
return this.config.sidebar
|
|
946
|
+
gridContainerClass: {
|
|
947
|
+
type: String,
|
|
948
|
+
default: "md:gap-5"
|
|
881
949
|
},
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
}
|
|
950
|
+
headerClass: String,
|
|
951
|
+
presetMode: {
|
|
952
|
+
type: String,
|
|
953
|
+
default: "sidebar"
|
|
887
954
|
},
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
this.config.extbar = {
|
|
892
|
-
open: false,
|
|
893
|
-
height: Math.round(window.innerHeight / 2.2)
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
return this.config.extbar
|
|
955
|
+
containerClass: {
|
|
956
|
+
type: String,
|
|
957
|
+
default: "md:p-5 md:gap-3"
|
|
897
958
|
},
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
height: this.extBar.height + "px"
|
|
902
|
-
}
|
|
959
|
+
toolbar: {
|
|
960
|
+
type: [ String, Boolean ],
|
|
961
|
+
default: true
|
|
903
962
|
},
|
|
904
963
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
}
|
|
964
|
+
config: Object,
|
|
965
|
+
defaultConfig: Function,
|
|
908
966
|
|
|
967
|
+
sharingSrc: String,
|
|
968
|
+
removeSharingSrc: String,
|
|
909
969
|
},
|
|
910
970
|
|
|
911
|
-
|
|
971
|
+
provide(){
|
|
912
972
|
return {
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
itemsPerPage: 16,
|
|
916
|
-
},
|
|
917
|
-
observer: null,
|
|
918
|
-
compPrefix: '',
|
|
919
|
-
enumCache: {},
|
|
920
|
-
extItems: null,
|
|
921
|
-
lastEnumItems: null,
|
|
973
|
+
listStyle: this.$style,
|
|
974
|
+
emitRoot: () => {}
|
|
922
975
|
}
|
|
923
976
|
},
|
|
924
977
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
978
|
+
unmounted() {
|
|
979
|
+
this.$removeResizeListener(this.$el)
|
|
980
|
+
window.removeEventListener('keydown', this.onKeyDown)
|
|
981
|
+
|
|
982
|
+
if(this.subscribeKey) {
|
|
983
|
+
this.socket.send('user.unsubscribe', {name: this.subscribeKey})
|
|
984
|
+
this.socket.off(this.subscribeKey, this.onSignal)
|
|
928
985
|
}
|
|
929
986
|
},
|
|
930
987
|
|
|
931
988
|
watch: {
|
|
932
989
|
|
|
933
|
-
config
|
|
990
|
+
config(to){
|
|
991
|
+
this.$nextTick(() => {
|
|
992
|
+
this.calcItemsPerPage()
|
|
993
|
+
this.load()
|
|
994
|
+
this.loadExt()
|
|
995
|
+
})
|
|
996
|
+
},
|
|
997
|
+
|
|
998
|
+
cConfig: {
|
|
999
|
+
deep: true,
|
|
1000
|
+
handler(to, from){
|
|
1001
|
+
if(Object.keys(from ?? {}).length > 0){
|
|
1002
|
+
this.saveConfig()
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
},
|
|
1006
|
+
|
|
1007
|
+
preset: {
|
|
934
1008
|
deep: true,
|
|
935
|
-
handler(){
|
|
936
|
-
|
|
1009
|
+
handler(to, from){
|
|
1010
|
+
if(to && to.uid === from?.uid){
|
|
1011
|
+
|
|
1012
|
+
}
|
|
937
1013
|
}
|
|
938
1014
|
},
|
|
939
1015
|
|