@mixd-id/web-scaffold 0.1.240411093 → 0.1.240411095
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/package.json +1 -1
- package/src/components/List.vue +33 -84
- package/src/utils/wss.js +87 -14
- package/src/widgets/Dashboard/SharingModal.vue +53 -22
- package/src/widgets/PresetBar.vue +143 -116
package/package.json
CHANGED
package/src/components/List.vue
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
:controller="controller"
|
|
15
15
|
:preset-key="presetKey"
|
|
16
16
|
:use-assistant="useAssistant"
|
|
17
|
+
:use-sharing="useSharing"
|
|
17
18
|
@apply="load">
|
|
18
19
|
|
|
19
20
|
<template #toolbar>
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
<slot name="toolbar"></slot>
|
|
88
89
|
</div>
|
|
89
90
|
|
|
90
|
-
<div class="flex flex-row gap-
|
|
91
|
+
<div class="flex flex-row gap-1" v-if="Boolean(toolbar)">
|
|
91
92
|
<Textbox v-if="canSearch"
|
|
92
93
|
class="flex-1 md:w-[240px] bg-base-400 border-text-50"
|
|
93
94
|
placeholder="Search..."
|
|
@@ -103,25 +104,6 @@
|
|
|
103
104
|
</template>
|
|
104
105
|
</Textbox>
|
|
105
106
|
|
|
106
|
-
<div v-if="false && $slots.gridItem"
|
|
107
|
-
class="hidden md:grid grid-cols-2 gap-[1px] border-[1px] border-text-50 rounded-lg">
|
|
108
|
-
<Radio v-model="preset.view"
|
|
109
|
-
name="view"
|
|
110
|
-
value="table"
|
|
111
|
-
:custom="true"
|
|
112
|
-
class="p-2 px-3 rounded-lg rounded-r-none"
|
|
113
|
-
:class="preset.view === 'table' ? 'bg-primary-500' : 'bg-base-500'">
|
|
114
|
-
<svg width="14" height="14" :class="preset.view === 'table' ? 'fill-white' : 'fill-text'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M448 32H64.05C28.7 32 .0492 60.65 .0492 96v320c0 35.35 28.65 64 64 64h383.1c35.35 0 64-28.65 64-64V96C512 60.65 483.4 32 448 32zM224 416H64v-96h160V416zM224 256H64V160h160V256zM448 416h-160v-96h160V416zM448 256h-160V160h160V256z"/></svg>
|
|
115
|
-
</Radio>
|
|
116
|
-
<Radio v-model="preset.view"
|
|
117
|
-
name="view"
|
|
118
|
-
value="grid"
|
|
119
|
-
:custom="true"
|
|
120
|
-
class="p-2 px-3 bg-base-500 rounded-lg rounded-l-none"
|
|
121
|
-
:class="preset.view === 'grid' ? 'bg-primary-500' : 'bg-base-500'">
|
|
122
|
-
<svg width="14" height="14" :class="preset.view === 'grid' ? 'fill-white' : 'fill-text'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M144 288h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96C176 302.3 161.7 288 144 288zM368 288h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96C400 302.3 385.7 288 368 288zM592 288h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96C624 302.3 609.7 288 592 288zM144 64h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32V96C176 78.33 161.7 64 144 64zM368 64h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32V96C400 78.33 385.7 64 368 64zM592 64h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32V96C624 78.33 609.7 64 592 64z"/></svg>
|
|
123
|
-
</Radio>
|
|
124
|
-
</div>
|
|
125
107
|
</div>
|
|
126
108
|
|
|
127
109
|
</div>
|
|
@@ -179,7 +161,7 @@
|
|
|
179
161
|
:config="cConfig">
|
|
180
162
|
<template #item="{ item }">
|
|
181
163
|
<slot name="gridItem" :item="item" :enumCache="enumCache" :getEnumText="getEnumText">
|
|
182
|
-
<div class="flex flex-row panel-400 rounded-lg overflow-hidden
|
|
164
|
+
<div class="flex flex-row panel-400 rounded-lg overflow-hidden p-3 gap-3">
|
|
183
165
|
<div>
|
|
184
166
|
<Image :src="item.imageUrl" class="bg-text-50 w-[64px] h-[64px] rounded-lg" />
|
|
185
167
|
</div>
|
|
@@ -242,7 +224,7 @@
|
|
|
242
224
|
:config="cConfig">
|
|
243
225
|
<template #item="{ item }">
|
|
244
226
|
<slot name="gridItem" :item="item" :getEnumText="getEnumText">
|
|
245
|
-
<div class="flex flex-row panel-400 rounded-lg overflow-hidden
|
|
227
|
+
<div class="flex flex-row panel-400 rounded-lg overflow-hidden p-3 gap-3">
|
|
246
228
|
<div>
|
|
247
229
|
<Image :src="item.imageUrl" class="bg-text-50 w-[64px] h-[64px] rounded-lg" />
|
|
248
230
|
</div>
|
|
@@ -282,7 +264,7 @@ import VirtualGrid from "./VirtualGrid.vue";
|
|
|
282
264
|
import PresetSelector from "../widgets/PresetSelector.vue";
|
|
283
265
|
import {generatePivotColumns, generateTotalColumns, setupConfig, sortsFn} from "../utils/preset-selector.mjs";
|
|
284
266
|
import PresetBar from "../widgets/PresetBar.vue";
|
|
285
|
-
import {
|
|
267
|
+
import {invokeAfterIdle, queueForLater} from "../utils/helpers.mjs";
|
|
286
268
|
|
|
287
269
|
export default{
|
|
288
270
|
|
|
@@ -342,6 +324,10 @@ export default{
|
|
|
342
324
|
useAssistant: {
|
|
343
325
|
type: undefined,
|
|
344
326
|
default: false
|
|
327
|
+
},
|
|
328
|
+
useSharing: {
|
|
329
|
+
type: undefined,
|
|
330
|
+
default: false
|
|
345
331
|
}
|
|
346
332
|
},
|
|
347
333
|
|
|
@@ -407,7 +393,7 @@ export default{
|
|
|
407
393
|
})
|
|
408
394
|
.finally(_ => this.readyState = 1)
|
|
409
395
|
}
|
|
410
|
-
return
|
|
396
|
+
return Promise.resolve()
|
|
411
397
|
},
|
|
412
398
|
|
|
413
399
|
loadNext(){
|
|
@@ -436,7 +422,7 @@ export default{
|
|
|
436
422
|
.catch(err => this.toast(err))
|
|
437
423
|
.finally(_ => this.readyState = 1)
|
|
438
424
|
}
|
|
439
|
-
return
|
|
425
|
+
return Promise.resolve()
|
|
440
426
|
},
|
|
441
427
|
|
|
442
428
|
async loadPreset(){
|
|
@@ -464,25 +450,21 @@ export default{
|
|
|
464
450
|
const defaultConfig = setupConfig(typeof this.defaultConfig === 'function' ? await this.defaultConfig() : {})
|
|
465
451
|
Object.assign(this.cConfig, defaultConfig)
|
|
466
452
|
|
|
467
|
-
return
|
|
453
|
+
return Promise.resolve()
|
|
468
454
|
}
|
|
469
455
|
}
|
|
470
456
|
else{
|
|
471
457
|
const defaultConfig = setupConfig(typeof this.defaultConfig === 'function' ? await this.defaultConfig() : {})
|
|
472
458
|
Object.assign(this.cConfig, defaultConfig)
|
|
473
459
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
this.$
|
|
481
|
-
|
|
482
|
-
query
|
|
483
|
-
})
|
|
484
|
-
|
|
485
|
-
resolve()
|
|
460
|
+
const query = {}
|
|
461
|
+
for(let key in this.$route.query){
|
|
462
|
+
if(key.toLowerCase() !== 'reset')
|
|
463
|
+
query[key] = this.$route.query[key]
|
|
464
|
+
}
|
|
465
|
+
this.$router.replace({
|
|
466
|
+
...this.$route,
|
|
467
|
+
query
|
|
486
468
|
})
|
|
487
469
|
}
|
|
488
470
|
},
|
|
@@ -526,9 +508,9 @@ export default{
|
|
|
526
508
|
}
|
|
527
509
|
})
|
|
528
510
|
|
|
529
|
-
for(let
|
|
530
|
-
if(!this.enumCache[column.key][
|
|
531
|
-
this.enumCache[column.key][
|
|
511
|
+
for(let cacheKey in this.enumCache[column.key]){
|
|
512
|
+
if(!this.enumCache[column.key][cacheKey].text)
|
|
513
|
+
this.enumCache[column.key][cacheKey].text = cacheKey
|
|
532
514
|
}
|
|
533
515
|
|
|
534
516
|
this.lastEnumItems = reqItems
|
|
@@ -634,7 +616,9 @@ export default{
|
|
|
634
616
|
|
|
635
617
|
sortItems(items){
|
|
636
618
|
|
|
637
|
-
if(typeof this.sorts === 'function'){
|
|
619
|
+
if(typeof this.sorts === 'function'){
|
|
620
|
+
return (items ?? []).sort(this.sorts)
|
|
621
|
+
}
|
|
638
622
|
else if((this.sorts ?? []).length > 0){
|
|
639
623
|
return (items ?? []).sort((a, b) => {
|
|
640
624
|
return sortsFn(a, b, this.sorts, 0)
|
|
@@ -946,42 +930,6 @@ export default{
|
|
|
946
930
|
columns(){
|
|
947
931
|
if((this.preset.pivot ?? {}).enabled){
|
|
948
932
|
return this.preset.pivot.columns ?? []
|
|
949
|
-
|
|
950
|
-
const tableColumns = groupBy(this.preset.columns ?? this.cConfig.columns, 'key')
|
|
951
|
-
|
|
952
|
-
const columns = []
|
|
953
|
-
|
|
954
|
-
for(let row of this.preset.pivot.rows){
|
|
955
|
-
if(!tableColumns[row.key][0].defaultFormat)
|
|
956
|
-
tableColumns[row.key][0].defaultFormat = tableColumns[row.key][0].format
|
|
957
|
-
|
|
958
|
-
switch(row.aggregrate){
|
|
959
|
-
case 'year':
|
|
960
|
-
tableColumns[row.key][0].format = 'YYYY'
|
|
961
|
-
break
|
|
962
|
-
|
|
963
|
-
case 'month':
|
|
964
|
-
tableColumns[row.key][0].format = 'MMM YYYY'
|
|
965
|
-
break
|
|
966
|
-
|
|
967
|
-
case 'date':
|
|
968
|
-
tableColumns[row.key][0].format = 'D MMM YYYY'
|
|
969
|
-
break
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
columns.push(tableColumns[row.key][0])
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
for(let value of this.preset.pivot.values){
|
|
976
|
-
const key = value.aggregrate ? `_${value.key}-${value.aggregrate}` : `_${value.key}-`
|
|
977
|
-
for(let k in tableColumns){
|
|
978
|
-
if(k.startsWith(key)){
|
|
979
|
-
columns.push(tableColumns[k][0])
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
return columns
|
|
985
933
|
}
|
|
986
934
|
|
|
987
935
|
for(let idx in this.preset.columns){
|
|
@@ -1029,7 +977,7 @@ export default{
|
|
|
1029
977
|
const items = this.sortItems(this.data.items)
|
|
1030
978
|
|
|
1031
979
|
if(typeof this.itemsFn === 'function'){
|
|
1032
|
-
return this.itemsFn(
|
|
980
|
+
return this.itemsFn(items)
|
|
1033
981
|
}
|
|
1034
982
|
|
|
1035
983
|
return items
|
|
@@ -1040,6 +988,8 @@ export default{
|
|
|
1040
988
|
this.configSharedPresets.find(_ => _.uid === this.configParams.presetIdx)
|
|
1041
989
|
|
|
1042
990
|
if(preset){
|
|
991
|
+
if(!preset.columns)
|
|
992
|
+
preset.columns = JSON.parse(JSON.stringify(this.cConfig.columns))
|
|
1043
993
|
if(!preset.search) preset.search = ''
|
|
1044
994
|
preset.search = this.$route.query?.search ? this.$route.query.search : preset.search
|
|
1045
995
|
}
|
|
@@ -1055,7 +1005,7 @@ export default{
|
|
|
1055
1005
|
|
|
1056
1006
|
presetView(){
|
|
1057
1007
|
return this.$device.type === 'mobile' ? 'grid' :
|
|
1058
|
-
(this.view ?? this.preset.view)
|
|
1008
|
+
(this.view ?? this.preset.view ?? 'table')
|
|
1059
1009
|
},
|
|
1060
1010
|
|
|
1061
1011
|
configParams(){
|
|
@@ -1064,7 +1014,8 @@ export default{
|
|
|
1064
1014
|
|
|
1065
1015
|
if(this.configPresets.length > 0 &&
|
|
1066
1016
|
(!this.cConfig.params.presetIdx ||
|
|
1067
|
-
!this.configPresets.find(_ => _.uid === this.cConfig.params.presetIdx)
|
|
1017
|
+
(!this.configPresets.find(_ => _.uid === this.cConfig.params.presetIdx) &&
|
|
1018
|
+
!this.configSharedPresets.find(_ => _.uid === this.cConfig.params.presetIdx))))
|
|
1068
1019
|
this.cConfig.params.presetIdx = this.configPresets[0].uid
|
|
1069
1020
|
|
|
1070
1021
|
return this.cConfig.params
|
|
@@ -1124,7 +1075,7 @@ export default{
|
|
|
1124
1075
|
},
|
|
1125
1076
|
|
|
1126
1077
|
freezeLeft(){
|
|
1127
|
-
return (this.preset?.columns).findIndex(_ => _.freeze) + 1
|
|
1078
|
+
return (this.preset?.columns ?? []).findIndex(_ => _.freeze) + 1
|
|
1128
1079
|
}
|
|
1129
1080
|
|
|
1130
1081
|
},
|
|
@@ -1135,10 +1086,8 @@ export default{
|
|
|
1135
1086
|
data: {
|
|
1136
1087
|
itemsPerPage: 16,
|
|
1137
1088
|
},
|
|
1138
|
-
observer: null,
|
|
1139
1089
|
compPrefix: '',
|
|
1140
1090
|
enumCache: {},
|
|
1141
|
-
extItems: null,
|
|
1142
1091
|
lastEnumItems: null,
|
|
1143
1092
|
queue: null,
|
|
1144
1093
|
_config: {
|
package/src/utils/wss.js
CHANGED
|
@@ -72,8 +72,6 @@ class WSS extends EventEmitter2{
|
|
|
72
72
|
|
|
73
73
|
_authFn = []
|
|
74
74
|
_reqFn = []
|
|
75
|
-
_retryCount = 0
|
|
76
|
-
|
|
77
75
|
_connectionId = 0
|
|
78
76
|
_debugIds = {}
|
|
79
77
|
|
|
@@ -110,6 +108,7 @@ class WSS extends EventEmitter2{
|
|
|
110
108
|
|
|
111
109
|
this._instance.on('connection', async (socket, req) => {
|
|
112
110
|
socket.id = `${++this._connectionId}`
|
|
111
|
+
socket._retryCount = 0
|
|
113
112
|
|
|
114
113
|
if(`${req.url}`.indexOf('debug-ws') > 0){
|
|
115
114
|
this._debugIds[socket.id] = {}
|
|
@@ -167,7 +166,7 @@ class WSS extends EventEmitter2{
|
|
|
167
166
|
|
|
168
167
|
if(pong){
|
|
169
168
|
delete socket.pinging
|
|
170
|
-
|
|
169
|
+
socket._retryCount = 0
|
|
171
170
|
}
|
|
172
171
|
else if(ping){
|
|
173
172
|
socket.send(await this.toBinaryData({ pong: 1 }, !!this._debugIds[socket.id]))
|
|
@@ -217,6 +216,9 @@ class WSS extends EventEmitter2{
|
|
|
217
216
|
if(subscriber){
|
|
218
217
|
subscriber.disconnect()
|
|
219
218
|
}
|
|
219
|
+
if(this._debugIds[socket.id]){
|
|
220
|
+
delete this._debugIds[socket.id]
|
|
221
|
+
}
|
|
220
222
|
this.emit('close', e, socket)
|
|
221
223
|
});
|
|
222
224
|
|
|
@@ -230,46 +232,117 @@ class WSS extends EventEmitter2{
|
|
|
230
232
|
await fn(token, socket)
|
|
231
233
|
}
|
|
232
234
|
|
|
233
|
-
socket.isAuth = true
|
|
234
|
-
socket.send(await this.toBinaryData({ auth:true }, !!this._debugIds[socket.id]))
|
|
235
|
-
|
|
236
235
|
subscriber = this._client.duplicate()
|
|
237
236
|
await subscriber.connect()
|
|
237
|
+
|
|
238
|
+
socket.isAuth = true
|
|
239
|
+
socket.send(await this.toBinaryData({ auth:true }, !!this._debugIds[socket.id]))
|
|
238
240
|
}
|
|
239
241
|
catch(e){
|
|
240
242
|
return socket.close(1002, (e.message ?? '').substring(0, 123));
|
|
241
243
|
}
|
|
242
244
|
|
|
243
245
|
if(this._opt.ping !== false){
|
|
246
|
+
let pingTimer
|
|
244
247
|
|
|
245
248
|
const ping = async() => {
|
|
249
|
+
if(socket.readyState !== WebSocket.OPEN) return
|
|
250
|
+
|
|
246
251
|
socket.send(await this.toBinaryData({ ping:1 }, !!this._debugIds[socket.id]))
|
|
247
252
|
socket.pinging = true
|
|
248
253
|
|
|
249
|
-
setTimeout(() => {
|
|
254
|
+
pingTimer = setTimeout(() => {
|
|
250
255
|
if(socket.pinging){
|
|
251
|
-
|
|
256
|
+
socket._retryCount++
|
|
252
257
|
|
|
253
|
-
if(
|
|
258
|
+
if(socket._retryCount > 10){
|
|
254
259
|
socket.close(1002, 'ping timeout')
|
|
255
260
|
if(subscriber){
|
|
256
261
|
subscriber.disconnect()
|
|
257
262
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
263
|
+
}
|
|
264
|
+
else{
|
|
265
|
+
pingTimer = setTimeout(ping, 3000)
|
|
261
266
|
}
|
|
262
267
|
}
|
|
263
268
|
else{
|
|
264
|
-
setTimeout(ping, (Math.round(Math.random() * 10) % 5) * 5000)
|
|
269
|
+
pingTimer = setTimeout(ping, (Math.round(Math.random() * 10) % 5) * 5000)
|
|
265
270
|
}
|
|
266
271
|
}, 3000)
|
|
267
272
|
}
|
|
268
|
-
setTimeout(ping, (Math.round(Math.random() * 10) % 5) * 5000)
|
|
273
|
+
pingTimer = setTimeout(ping, (Math.round(Math.random() * 10) % 5) * 5000)
|
|
274
|
+
|
|
275
|
+
socket.on('close', () => {
|
|
276
|
+
clearTimeout(pingTimer)
|
|
277
|
+
})
|
|
269
278
|
}
|
|
270
279
|
})
|
|
271
280
|
}
|
|
272
281
|
|
|
282
|
+
stats(){
|
|
283
|
+
let authenticated = 0
|
|
284
|
+
this._instance.clients.forEach(socket => {
|
|
285
|
+
if(socket.isAuth) authenticated++
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
pid: process.pid,
|
|
290
|
+
connections: this._instance.clients.size,
|
|
291
|
+
authenticated,
|
|
292
|
+
totalConnections: this._connectionId,
|
|
293
|
+
debugConnections: Object.keys(this._debugIds).length,
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
clusterStats(){
|
|
298
|
+
return new Promise((resolve) => {
|
|
299
|
+
const workers = {}
|
|
300
|
+
const timeout = setTimeout(() => resolve(this._aggregateStats(workers)), 3000)
|
|
301
|
+
|
|
302
|
+
process.on('message', (packet) => {
|
|
303
|
+
if(packet.type === 'process:msg' && packet.data?.type === 'wss:stats:response'){
|
|
304
|
+
workers[packet.data.pid] = packet.data.stats
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const expected = parseInt(process.env.instances || '0', 10)
|
|
308
|
+
if(expected > 0 && Object.keys(workers).length >= expected){
|
|
309
|
+
clearTimeout(timeout)
|
|
310
|
+
resolve(this._aggregateStats(workers))
|
|
311
|
+
}
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
process.send({ type: 'process:msg', data: { type: 'wss:stats:request' } })
|
|
315
|
+
|
|
316
|
+
// Include own stats
|
|
317
|
+
workers[process.pid] = this.stats()
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
_aggregateStats(workers){
|
|
322
|
+
const pids = Object.keys(workers)
|
|
323
|
+
return {
|
|
324
|
+
workers: pids.length,
|
|
325
|
+
connections: pids.reduce((sum, pid) => sum + workers[pid].connections, 0),
|
|
326
|
+
authenticated: pids.reduce((sum, pid) => sum + workers[pid].authenticated, 0),
|
|
327
|
+
totalConnections: pids.reduce((sum, pid) => sum + workers[pid].totalConnections, 0),
|
|
328
|
+
debugConnections: pids.reduce((sum, pid) => sum + workers[pid].debugConnections, 0),
|
|
329
|
+
perWorker: workers,
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
initClusterStats(){
|
|
334
|
+
if(process.send){
|
|
335
|
+
process.on('message', (packet) => {
|
|
336
|
+
if(packet.type === 'process:msg' && packet.data?.type === 'wss:stats:request'){
|
|
337
|
+
process.send({
|
|
338
|
+
type: 'process:msg',
|
|
339
|
+
data: { type: 'wss:stats:response', pid: process.pid, stats: this.stats() }
|
|
340
|
+
})
|
|
341
|
+
}
|
|
342
|
+
})
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
273
346
|
auth(fn){
|
|
274
347
|
this._authFn.push(fn)
|
|
275
348
|
}
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
width="360"
|
|
4
4
|
height="480" @show="$refs.search.select()">
|
|
5
5
|
<template v-slot:head>
|
|
6
|
-
<div class="relative
|
|
7
|
-
<
|
|
6
|
+
<div class="relative pt-6 pb-3 flex flex-col gap-4">
|
|
7
|
+
<div class="px-6">
|
|
8
|
+
<h3>Sharing</h3>
|
|
9
|
+
</div>
|
|
8
10
|
<div class="absolute top-0 right-0 p-2">
|
|
9
11
|
<button type="button" class="p-2" @click="close">
|
|
10
12
|
<svg width="24" height="24" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -14,27 +16,36 @@
|
|
|
14
16
|
</div>
|
|
15
17
|
|
|
16
18
|
<div>
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
<div class="mb-3 flex border-b-[1px] border-text-50 px-6">
|
|
20
|
+
<Tabs :items="tabItems" v-model="tabIndex" />
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="px-6">
|
|
24
|
+
<Textbox @keyup.enter="load"
|
|
25
|
+
ref="search"
|
|
26
|
+
v-model="search"
|
|
27
|
+
placeholder="Search..."
|
|
28
|
+
:clearable="true"
|
|
29
|
+
@clear="load(search = '')">
|
|
30
|
+
<template #start>
|
|
31
|
+
<div class="pl-3">
|
|
32
|
+
<svg width="14" height="14" class="fill-text-200" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z"/></svg>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
</Textbox>
|
|
36
|
+
</div>
|
|
29
37
|
</div>
|
|
30
38
|
</div>
|
|
31
39
|
</template>
|
|
32
|
-
<div class="flex-1
|
|
40
|
+
<div class="flex-1 flex flex-col">
|
|
33
41
|
|
|
34
|
-
<div v-if="items?.length
|
|
35
|
-
<div v-for="item in items"
|
|
42
|
+
<div v-if="items?.length" class="divide-y divide-text-50 border-y-[1px] border-text-50">
|
|
43
|
+
<div v-for="item in items" class="px-6 p-3 hover:bg-primary" @click="select(item)">
|
|
36
44
|
<slot name="item" :item="item">
|
|
37
|
-
<div>{{ item.name }}</div>
|
|
45
|
+
<div v-if="tabIndex === 1">{{ item.user?.name }}</div>
|
|
46
|
+
<div v-else-if="tabIndex === 2">{{ item.business }}</div>
|
|
47
|
+
<div v-else-if="tabIndex === 3">{{ item.subBusiness }}</div>
|
|
48
|
+
<div v-else-if="tabIndex === 4">{{ item.branchCode }}</div>
|
|
38
49
|
</slot>
|
|
39
50
|
</div>
|
|
40
51
|
</div>
|
|
@@ -69,6 +80,13 @@ export default{
|
|
|
69
80
|
selectedIds: null,
|
|
70
81
|
callback: null,
|
|
71
82
|
search: '',
|
|
83
|
+
tabItems: [
|
|
84
|
+
{ text:'User', value:1 },
|
|
85
|
+
{ text:'Bisnis', value:2 },
|
|
86
|
+
{ text:'Sub Bisnis', value:3 },
|
|
87
|
+
{ text:'Cabang', value:4 }
|
|
88
|
+
],
|
|
89
|
+
tabIndex: 1
|
|
72
90
|
}
|
|
73
91
|
},
|
|
74
92
|
|
|
@@ -79,7 +97,7 @@ export default{
|
|
|
79
97
|
},
|
|
80
98
|
|
|
81
99
|
load(){
|
|
82
|
-
this.socket.send(this.src, { search:this.search })
|
|
100
|
+
this.socket.send(this.src, { search:this.search, type: this.tabIndex })
|
|
83
101
|
.then(res => {
|
|
84
102
|
this.items = res.items
|
|
85
103
|
})
|
|
@@ -94,13 +112,26 @@ export default{
|
|
|
94
112
|
},
|
|
95
113
|
|
|
96
114
|
select(item){
|
|
115
|
+
const newItem = JSON.parse(JSON.stringify(item))
|
|
116
|
+
|
|
97
117
|
if(typeof this.callback === 'function')
|
|
98
|
-
this.callback(
|
|
99
|
-
this.$emit('select',
|
|
118
|
+
this.callback(newItem)
|
|
119
|
+
this.$emit('select', newItem)
|
|
100
120
|
this.close()
|
|
101
121
|
},
|
|
102
122
|
|
|
103
|
-
}
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
watch: {
|
|
126
|
+
|
|
127
|
+
tabIndex: {
|
|
128
|
+
handler(){
|
|
129
|
+
this.search = ''
|
|
130
|
+
this.load()
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
}
|
|
104
135
|
|
|
105
136
|
}
|
|
106
137
|
|
|
@@ -13,132 +13,140 @@
|
|
|
13
13
|
<slot name="toolbar" :edit="false"></slot>
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
|
-
<div class="
|
|
17
|
-
<div class="
|
|
18
|
-
<
|
|
19
|
-
|
|
16
|
+
<div class="flex-1 overflow-y-auto">
|
|
17
|
+
<div class="p-5">
|
|
18
|
+
<div class="px-2">
|
|
19
|
+
<label class="text-text-300">Presets</label>
|
|
20
|
+
</div>
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
<ListItem :items="config.presets"
|
|
23
|
+
class="mt-1 rounded-lg overflow-hidden bg-base-300 border-text-50 border-[1px]"
|
|
24
|
+
container-class="divide-y divide-text-50"
|
|
25
|
+
@reorder="(from, to) => { config.presets.splice(to, 0, config.presets.splice(from, 1)[0]); apply() }">
|
|
26
|
+
<template v-slot="{ item }">
|
|
27
|
+
<div :class="$style.presetBtn">
|
|
28
|
+
<div data-reorder>
|
|
29
|
+
<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>
|
|
30
|
+
</div>
|
|
31
|
+
<Radio v-model="configParams.presetIdx" :value="item.uid" @change="apply()" />
|
|
32
|
+
<button type="button" class="flex-1 py-1 text-left overflow-hidden text-ellipsis whitespace-nowrap"
|
|
33
|
+
@click="configParams.presetIdx = item.uid; apply()">
|
|
34
|
+
{{ item.name }}
|
|
35
|
+
</button>
|
|
36
|
+
<button type="button"
|
|
37
|
+
:class="$style.presetOptBtn"
|
|
38
|
+
:ref="`presetbtn${item.uid}`"
|
|
39
|
+
@click="$refs.contextMenu.open($refs[`presetbtn${item.uid}`], { item })">
|
|
40
|
+
<svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 208c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM16 104c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48zm0 304c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48z"/></svg>
|
|
41
|
+
</button>
|
|
29
42
|
</div>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@click="configParams.presetIdx = item.uid; apply()">
|
|
33
|
-
{{ item.name }}
|
|
34
|
-
</button>
|
|
35
|
-
<button type="button"
|
|
36
|
-
:class="$style.presetOptBtn"
|
|
37
|
-
:ref="`presetbtn${item.uid}`"
|
|
38
|
-
@click="$refs.contextMenu.open($refs[`presetbtn${item.uid}`], { item })">
|
|
39
|
-
<svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 208c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM16 104c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48zm0 304c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48z"/></svg>
|
|
40
|
-
</button>
|
|
41
|
-
</div>
|
|
42
|
-
</template>
|
|
43
|
-
</ListItem>
|
|
44
|
-
|
|
45
|
-
<ContextMenu ref="contextMenu" position="bottom-right">
|
|
46
|
-
<template #default="{ context }">
|
|
47
|
-
<div class="flex flex-col min-w-[200px] divide-y divide-text-50">
|
|
43
|
+
</template>
|
|
44
|
+
</ListItem>
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M402.3 344.9l32-32c5-5 13.7-1.5 13.7 5.7V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h273.5c7.1 0 10.7 8.6 5.7 13.7l-32 32c-1.5 1.5-3.5 2.3-5.7 2.3H48v352h352V350.5c0-2.1.8-4.1 2.3-5.6zm156.6-201.8L296.3 405.7l-90.4 10c-26.2 2.9-48.5-19.2-45.6-45.6l10-90.4L432.9 17.1c22.9-22.9 59.9-22.9 82.7 0l43.2 43.2c22.9 22.9 22.9 60 .1 82.8zM460.1 174L402 115.9 216.2 301.8l-7.3 65.3 65.3-7.3L460.1 174zm64.8-79.7l-43.2-43.2c-4.1-4.1-10.8-4.1-14.8 0L436 82l58.1 58.1 30.9-30.9c4-4.2 4-10.8-.1-14.9z"/></svg>
|
|
53
|
-
</div>
|
|
54
|
-
Edit
|
|
55
|
-
</button>
|
|
46
|
+
<ContextMenu ref="contextMenu" position="bottom-right">
|
|
47
|
+
<template #default="{ context }">
|
|
48
|
+
<div class="flex flex-col min-w-[200px] divide-y divide-text-50">
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
50
|
+
<button class="w-full p-3 text-left flex flex-row gap-3" :class="appStyle.menuItem"
|
|
51
|
+
@click="select(context.item)">
|
|
52
|
+
<div class="w-[24px]">
|
|
53
|
+
<svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M402.3 344.9l32-32c5-5 13.7-1.5 13.7 5.7V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h273.5c7.1 0 10.7 8.6 5.7 13.7l-32 32c-1.5 1.5-3.5 2.3-5.7 2.3H48v352h352V350.5c0-2.1.8-4.1 2.3-5.6zm156.6-201.8L296.3 405.7l-90.4 10c-26.2 2.9-48.5-19.2-45.6-45.6l10-90.4L432.9 17.1c22.9-22.9 59.9-22.9 82.7 0l43.2 43.2c22.9 22.9 22.9 60 .1 82.8zM460.1 174L402 115.9 216.2 301.8l-7.3 65.3 65.3-7.3L460.1 174zm64.8-79.7l-43.2-43.2c-4.1-4.1-10.8-4.1-14.8 0L436 82l58.1 58.1 30.9-30.9c4-4.2 4-10.8-.1-14.9z"/></svg>
|
|
54
|
+
</div>
|
|
55
|
+
Edit
|
|
56
|
+
</button>
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
58
|
+
<button class="w-full p-3 text-left flex flex-row gap-3" :class="appStyle.menuItem"
|
|
59
|
+
@click="duplicate(context.item)">
|
|
60
|
+
<div class="w-[24px]">
|
|
61
|
+
<svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg>
|
|
62
|
+
</div>
|
|
63
|
+
Duplicate
|
|
64
|
+
</button>
|
|
72
65
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
66
|
+
<button v-if="config.presets.length > 1" class="w-full p-3 text-left flex flex-row gap-3 text-red-500" :class="appStyle.menuItem"
|
|
67
|
+
@click="remove(context.item)">
|
|
68
|
+
<div class="w-[24px]">
|
|
69
|
+
<svg width="19" height="19" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M469.65 181.65l-11.31-11.31c-6.25-6.25-16.38-6.25-22.63 0L384 222.06l-51.72-51.72c-6.25-6.25-16.38-6.25-22.63 0l-11.31 11.31c-6.25 6.25-6.25 16.38 0 22.63L350.06 256l-51.72 51.72c-6.25 6.25-6.25 16.38 0 22.63l11.31 11.31c6.25 6.25 16.38 6.25 22.63 0L384 289.94l51.72 51.72c6.25 6.25 16.38 6.25 22.63 0l11.31-11.31c6.25-6.25 6.25-16.38 0-22.63L417.94 256l51.72-51.72c6.24-6.25 6.24-16.38-.01-22.63zM576 64H205.26C188.28 64 172 70.74 160 82.74L9.37 233.37c-12.5 12.5-12.5 32.76 0 45.25L160 429.25c12 12 28.28 18.75 45.25 18.75H576c35.35 0 64-28.65 64-64V128c0-35.35-28.65-64-64-64zm16 320c0 8.82-7.18 16-16 16H205.26c-4.27 0-8.29-1.66-11.31-4.69L54.63 256l139.31-139.31c3.02-3.02 7.04-4.69 11.31-4.69H576c8.82 0 16 7.18 16 16v256z"/></svg>
|
|
70
|
+
</div>
|
|
71
|
+
Remove
|
|
72
|
+
</button>
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
</ContextMenu>
|
|
81
77
|
</div>
|
|
82
78
|
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
<div :class="$style.presetBtn">
|
|
88
|
-
<Radio v-model="configParams.presetIdx" :value="item.uid" @change="apply()" />
|
|
89
|
-
<button type="button" class="flex-1 py-1 text-left overflow-hidden text-ellipsis whitespace-nowrap"
|
|
90
|
-
@click="configParams.presetIdx = item.uid; apply()">
|
|
91
|
-
{{ item.name }}
|
|
92
|
-
</button>
|
|
93
|
-
<button type="button"
|
|
94
|
-
:class="$style.presetOptBtn"
|
|
95
|
-
:ref="`presetsbtn${item.uid}`"
|
|
96
|
-
@click="$refs.contextMenu2.open($refs[`presetsbtn${item.uid}`], { item, index })">
|
|
97
|
-
<svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 208c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM16 104c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48zm0 304c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48z"/></svg>
|
|
98
|
-
</button>
|
|
99
|
-
</div>
|
|
100
|
-
</template>
|
|
101
|
-
</ListItem>
|
|
102
|
-
|
|
103
|
-
<ContextMenu ref="contextMenu2" position="bottom-right">
|
|
104
|
-
<template #default="{ context }">
|
|
105
|
-
<div class="flex flex-col min-w-[200px] divide-y divide-text-50">
|
|
79
|
+
<div v-if="useSharing" class="p-5">
|
|
80
|
+
<div class="px-2">
|
|
81
|
+
<label class="text-text-300">Shared Presets</label>
|
|
82
|
+
</div>
|
|
106
83
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
84
|
+
<div v-if="config.sharedPresets?.length">
|
|
85
|
+
<ListItem :items="config.sharedPresets"
|
|
86
|
+
class="mt-1 rounded-lg overflow-hidden bg-base-300 border-text-50 border-[1px]"
|
|
87
|
+
container-class="divide-y divide-text-50">
|
|
88
|
+
<template v-slot="{ item, index }">
|
|
89
|
+
<div :class="$style.presetBtn">
|
|
90
|
+
<Radio v-model="configParams.presetIdx" :value="item.uid" @change="apply()" />
|
|
91
|
+
<button type="button" class="flex-1 py-1 text-left overflow-hidden text-ellipsis whitespace-nowrap"
|
|
92
|
+
@click="configParams.presetIdx = item.uid; apply()">
|
|
93
|
+
{{ item.name }}
|
|
94
|
+
</button>
|
|
95
|
+
<button type="button"
|
|
96
|
+
:class="$style.presetOptBtn"
|
|
97
|
+
:ref="`presetsbtn${item.uid}`"
|
|
98
|
+
@click="$refs.contextMenu2.open($refs[`presetsbtn${item.uid}`], { item, index })">
|
|
99
|
+
<svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 208c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM16 104c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48zm0 304c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48z"/></svg>
|
|
100
|
+
</button>
|
|
111
101
|
</div>
|
|
112
|
-
|
|
113
|
-
|
|
102
|
+
</template>
|
|
103
|
+
</ListItem>
|
|
104
|
+
|
|
105
|
+
<ContextMenu ref="contextMenu2" position="bottom-right">
|
|
106
|
+
<template #default="{ context }">
|
|
107
|
+
<div class="flex flex-col min-w-[200px] divide-y divide-text-50">
|
|
108
|
+
|
|
109
|
+
<button class="w-full p-3 text-left flex flex-row gap-3" :class="appStyle.menuItem"
|
|
110
|
+
@click="duplicate(context.item)">
|
|
111
|
+
<div class="w-[24px]">
|
|
112
|
+
<svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg>
|
|
113
|
+
</div>
|
|
114
|
+
Duplicate
|
|
115
|
+
</button>
|
|
116
|
+
|
|
117
|
+
<button class="w-full p-3 text-left flex flex-row gap-3 text-red-500"
|
|
118
|
+
:class="appStyle.menuItem"
|
|
119
|
+
@click="removeShared(context.item, context.index)">
|
|
120
|
+
<div class="w-[24px]">
|
|
121
|
+
<svg width="19" height="19" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M469.65 181.65l-11.31-11.31c-6.25-6.25-16.38-6.25-22.63 0L384 222.06l-51.72-51.72c-6.25-6.25-16.38-6.25-22.63 0l-11.31 11.31c-6.25 6.25-6.25 16.38 0 22.63L350.06 256l-51.72 51.72c-6.25 6.25-6.25 16.38 0 22.63l11.31 11.31c6.25 6.25 16.38 6.25 22.63 0L384 289.94l51.72 51.72c6.25 6.25 16.38 6.25 22.63 0l11.31-11.31c6.25-6.25 6.25-16.38 0-22.63L417.94 256l51.72-51.72c6.24-6.25 6.24-16.38-.01-22.63zM576 64H205.26C188.28 64 172 70.74 160 82.74L9.37 233.37c-12.5 12.5-12.5 32.76 0 45.25L160 429.25c12 12 28.28 18.75 45.25 18.75H576c35.35 0 64-28.65 64-64V128c0-35.35-28.65-64-64-64zm16 320c0 8.82-7.18 16-16 16H205.26c-4.27 0-8.29-1.66-11.31-4.69L54.63 256l139.31-139.31c3.02-3.02 7.04-4.69 11.31-4.69H576c8.82 0 16 7.18 16 16v256z"/></svg>
|
|
122
|
+
</div>
|
|
123
|
+
Remove
|
|
124
|
+
</button>
|
|
114
125
|
|
|
115
|
-
<button class="w-full p-3 text-left flex flex-row gap-3 text-red-500"
|
|
116
|
-
:class="appStyle.menuItem"
|
|
117
|
-
@click="removeShared(context.item, context.index)">
|
|
118
|
-
<div class="w-[24px]">
|
|
119
|
-
<svg width="19" height="19" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M469.65 181.65l-11.31-11.31c-6.25-6.25-16.38-6.25-22.63 0L384 222.06l-51.72-51.72c-6.25-6.25-16.38-6.25-22.63 0l-11.31 11.31c-6.25 6.25-6.25 16.38 0 22.63L350.06 256l-51.72 51.72c-6.25 6.25-6.25 16.38 0 22.63l11.31 11.31c6.25 6.25 16.38 6.25 22.63 0L384 289.94l51.72 51.72c6.25 6.25 16.38 6.25 22.63 0l11.31-11.31c6.25-6.25 6.25-16.38 0-22.63L417.94 256l51.72-51.72c6.24-6.25 6.24-16.38-.01-22.63zM576 64H205.26C188.28 64 172 70.74 160 82.74L9.37 233.37c-12.5 12.5-12.5 32.76 0 45.25L160 429.25c12 12 28.28 18.75 45.25 18.75H576c35.35 0 64-28.65 64-64V128c0-35.35-28.65-64-64-64zm16 320c0 8.82-7.18 16-16 16H205.26c-4.27 0-8.29-1.66-11.31-4.69L54.63 256l139.31-139.31c3.02-3.02 7.04-4.69 11.31-4.69H576c8.82 0 16 7.18 16 16v256z"/></svg>
|
|
120
126
|
</div>
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
</template>
|
|
128
|
+
</ContextMenu>
|
|
129
|
+
</div>
|
|
123
130
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
<div v-else class="mt-2">
|
|
132
|
+
<p class="text-text-300 p-3 text-center bg-base-300">No Shared Presets</p>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
128
135
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
<div class="p-5" v-if="['true', 1, true].includes(useAssistant)">
|
|
137
|
+
<div class="px-2 flex flex-col gap-1">
|
|
138
|
+
<div class="flex flex-row gap-2">
|
|
139
|
+
<div class="flex-1">
|
|
140
|
+
<label class="text-text-300">AI Assistant</label>
|
|
141
|
+
</div>
|
|
142
|
+
<div v-if="$isDebugMode" class="flex flex-row gap-2">
|
|
143
|
+
<button type="button" class="text-primary text-sm" @click="log(config)">Config</button>
|
|
144
|
+
<button type="button" class="text-primary text-sm" @click="log(preset)">Preset</button>
|
|
145
|
+
</div>
|
|
138
146
|
</div>
|
|
147
|
+
<Textarea rows="6" placeholder="Generate preset based on text" v-model="generateText" />
|
|
148
|
+
<Button ref="generateBtn" class="w-[100px] mt-2" :state="canGenerate ? 1 : -1" @click="generatePreset">Generate</Button>
|
|
139
149
|
</div>
|
|
140
|
-
<Textarea rows="6" placeholder="Generate preset based on text" v-model="generateText" />
|
|
141
|
-
<Button ref="generateBtn" class="w-[100px] mt-2" :state="canGenerate ? 1 : -1" @click="generatePreset">Generate</Button>
|
|
142
150
|
</div>
|
|
143
151
|
</div>
|
|
144
152
|
|
|
@@ -570,8 +578,8 @@
|
|
|
570
578
|
<div class="flex flex-col gap-1 mt-2">
|
|
571
579
|
<div v-for="(item, index) in preset.shared"
|
|
572
580
|
class="bg-base-500 hover:bg-text-50 p-3 rounded-lg flex flex-row gap-2 items-center gap-1">
|
|
573
|
-
<div class="flex-1 flex flex-row items-center cursor-default gap-2">
|
|
574
|
-
<svg class="fill-text-200" height="14" viewBox="0 0 448 512" width="14"
|
|
581
|
+
<div v-if="item.userId" class="flex-1 flex flex-row items-center cursor-default gap-2">
|
|
582
|
+
<svg class="fill-text-200 mr-1" height="14" viewBox="0 0 448 512" width="14"
|
|
575
583
|
xmlns="http://www.w3.org/2000/svg">
|
|
576
584
|
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
577
585
|
<path
|
|
@@ -579,6 +587,18 @@
|
|
|
579
587
|
</svg>
|
|
580
588
|
{{ item.user?.name ?? item.userId }}
|
|
581
589
|
</div>
|
|
590
|
+
<div v-else-if="item.business" class="flex-1 flex flex-row items-center cursor-default gap-2">
|
|
591
|
+
<svg class="fill-text-200 mr-1" width="14" height="14" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M480 192c0-88.38-107.5-160-240-160S0 103.6 0 192c0 35.38 30.88 64 64 64v192c0 17.62 14.38 32 32 32h288c17.62 0 32-14.38 32-32V256C449.1 256 480 227.4 480 192zM400 32c-2.375 0-4.75 .25-7.25 .25C465.3 66.38 512 124.6 512 192c0 42.75-26.88 79-64 91.5V448c-.125 11.25-3.125 22.38-8.875 32H544c17.62 0 32-14.38 32-32V256h4C613.1 256 640 227.4 640 192C640 103.6 532.5 32 400 32z"/></svg>
|
|
592
|
+
{{ item.business }}
|
|
593
|
+
</div>
|
|
594
|
+
<div v-else-if="item.subBusiness" class="flex-1 flex flex-row items-center cursor-default gap-2">
|
|
595
|
+
<svg class="fill-text-200 mr-1" width="14" height="14" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M144 368C144 376.8 151.2 384 160 384s16-7.178 16-16S168.8 352 160 352S144 359.2 144 368zM368 144C368 135.2 360.8 128 352 128s-16 7.178-16 16S343.2 160 352 160S368 152.8 368 144zM184 0C155 0 132 22 129 50c-28 7-48.99 32-48.99 62c0 6 .9863 12 2.986 18C53.1 136 32 161 32 192c0 15 5 29 13.1 40C19 245 0 272 0 304c0 34 21.1 63 52 75C49.1 385 48 392 48 400c0 35 29 64 64 64c5.1 0 11-1 17-2C131 490 155 512 184 512c31 0 56-25 56-56V272H192C183.2 272 176 279.2 176 288v43.43C190.1 337.6 200 351.6 200 368c0 22.09-17.91 40-40 40s-40-17.91-40-40c0-16.38 9.9-30.38 24-36.57V288c0-26.47 21.53-48 48-48h48V160H196.6C190.4 174.1 176.4 184 160 184c-22.09 0-40-17.91-40-40S137.9 104 160 104c16.38 0 30.38 9.9 36.57 24H240V56C240 25 215 0 184 0zM144 144C144 152.8 151.2 160 160 160s16-7.178 16-16S168.8 128 160 128S144 135.2 144 144zM512 304c0-32-19-59-46-72C475 221 480 207 480 192c0-31-22-56-51-62c2-6 2.987-12 2.987-18c0-30-20.99-55-48.99-62C380 22 357 0 328 0c-31 0-56 25-56 56V240H320c8.828 0 16-7.172 16-16V180.6C321.9 174.4 312 160.4 312 144c0-22.09 17.91-40 40-40s40 17.91 40 40c0 16.38-9.9 30.38-24 36.57V224c0 26.47-21.53 48-48 48h-48V352h43.43C321.6 337.9 335.6 328 352 328c22.09 0 40 17.91 40 40s-17.91 40-40 40c-16.38 0-30.38-9.9-36.57-24H272v72c0 31 25 56 56 56c29 0 53-22 55-50C389 463 393.1 464 400 464c35 0 64-29 64-64c0-8-2-15-4-21C489.1 367 512 338 512 304zM368 368c0-8.822-7.178-16-16-16s-16 7.178-16 16S343.2 384 352 384S368 376.8 368 368z"/></svg>
|
|
596
|
+
{{ item.subBusiness }}
|
|
597
|
+
</div>
|
|
598
|
+
<div v-else-if="item.branchCode" class="flex-1 flex flex-row items-center cursor-default gap-2">
|
|
599
|
+
<svg class="fill-text-200 mr-1" width="14" height="14" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M464 0h-224C213.5 0 192 21.49 192 48v80.01L48 128c-26.51 0-48 21.49-48 48v304c0 17.67 14.33 32 32 32L480 512c17.67 0 32-14.33 32-32V48C512 21.49 490.5 0 464 0zM128 336c0 8.836-7.164 16-16 16h-32c-8.836 0-16-7.164-16-16v-32c0-8.838 7.164-16 16-16h32c8.836 0 16 7.162 16 16V336zM128 240c0 8.836-7.164 16-16 16h-32c-8.836 0-16-7.164-16-16v-32c0-8.838 7.164-16 16-16h32c8.836 0 16 7.162 16 16V240zM320 304c0 8.836-7.164 16-16 16h-32C263.2 320 256 312.8 256 304v-32C256 263.2 263.2 256 272 256h32C312.8 256 320 263.2 320 272V304zM320 208C320 216.8 312.8 224 304 224h-32C263.2 224 256 216.8 256 208v-32C256 167.2 263.2 160 272 160h32C312.8 160 320 167.2 320 176V208zM320 112C320 120.8 312.8 128 304 128h-32C263.2 128 256 120.8 256 112v-32C256 71.16 263.2 64 272 64h32C312.8 64 320 71.16 320 80V112zM448 304c0 8.836-7.164 16-16 16h-32C391.2 320 384 312.8 384 304v-32C384 263.2 391.2 256 400 256h32C440.8 256 448 263.2 448 272V304zM448 208C448 216.8 440.8 224 432 224h-32C391.2 224 384 216.8 384 208v-32C384 167.2 391.2 160 400 160h32C440.8 160 448 167.2 448 176V208zM448 112C448 120.8 440.8 128 432 128h-32C391.2 128 384 120.8 384 112v-32C384 71.16 391.2 64 400 64h32C440.8 64 448 71.16 448 80V112z"/></svg>
|
|
600
|
+
{{ item.branchCode }}
|
|
601
|
+
</div>
|
|
582
602
|
<button type="button" @click="removeSharing(item, index)">
|
|
583
603
|
<svg class="fill-text-300 hover:fill-red-600" height="14" viewBox="0 0 320 512"
|
|
584
604
|
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -631,6 +651,11 @@ export default{
|
|
|
631
651
|
useAssistant: {
|
|
632
652
|
type: undefined,
|
|
633
653
|
default: false
|
|
654
|
+
},
|
|
655
|
+
|
|
656
|
+
useSharing: {
|
|
657
|
+
type: undefined,
|
|
658
|
+
default: false
|
|
634
659
|
}
|
|
635
660
|
|
|
636
661
|
},
|
|
@@ -646,16 +671,16 @@ export default{
|
|
|
646
671
|
|
|
647
672
|
addSharing(item) {
|
|
648
673
|
const obj = {
|
|
674
|
+
...item,
|
|
649
675
|
key: this.presetKey,
|
|
650
|
-
presetUid: this.preset.uid
|
|
651
|
-
userId: item.id
|
|
676
|
+
presetUid: this.preset.uid
|
|
652
677
|
}
|
|
653
678
|
|
|
654
679
|
this.socket.send(`${this.controller}.add-sharing`, obj)
|
|
655
680
|
.then(newItem => {
|
|
656
681
|
if (!Array.isArray(this.preset.shared))
|
|
657
682
|
this.preset.shared = []
|
|
658
|
-
this.$util.push(this.preset.shared, newItem, {key: "
|
|
683
|
+
this.$util.push(this.preset.shared, newItem, {key: "id"})
|
|
659
684
|
})
|
|
660
685
|
},
|
|
661
686
|
|
|
@@ -675,6 +700,7 @@ export default{
|
|
|
675
700
|
this.config.sharedPresets.splice(index, 1)
|
|
676
701
|
this.configParams.presetIdx = this.config.presets[0].uid
|
|
677
702
|
})
|
|
703
|
+
.catch(err => this.alert(err))
|
|
678
704
|
})
|
|
679
705
|
},
|
|
680
706
|
|
|
@@ -849,7 +875,8 @@ export default{
|
|
|
849
875
|
|
|
850
876
|
if(this.config.presets.length > 0 &&
|
|
851
877
|
(!this.config.params.presetIdx ||
|
|
852
|
-
!this.config.presets.find(_ => _.uid === this.config.params.presetIdx)
|
|
878
|
+
(!this.config.presets.find(_ => _.uid === this.config.params.presetIdx) &&
|
|
879
|
+
!(this.config.sharedPresets ?? []).find(_ => _.uid === this.config.params.presetIdx))))
|
|
853
880
|
this.config.params.presetIdx = this.config.presets[0].uid
|
|
854
881
|
|
|
855
882
|
return this.config.params
|
|
@@ -944,7 +971,7 @@ export default{
|
|
|
944
971
|
...((this.config ?? {}).filters !== false ? [{ text:'Filters', value:2 }] : []),
|
|
945
972
|
...((this.config ?? {}).sorts !== false ? [{ text:'Sorts', value:3 }] : []),
|
|
946
973
|
...((this.config ?? {}).pivot !== false ? [{ text:'Pivot', value:5 }] : []),
|
|
947
|
-
...(this.
|
|
974
|
+
...(this.useSharing ? [{ text:'Sharing', value:6 }] : []),
|
|
948
975
|
],
|
|
949
976
|
chart: [
|
|
950
977
|
...((this.config ?? {}).filters !== false ? [{ text:'Filters', value:2 }] : []),
|