@mixd-id/web-scaffold 0.1.230406351 → 0.1.230406352
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/GHeatMaps.vue +56 -3
- package/src/configs/dashboard/grid-2.js +2 -0
- package/src/configs/dashboard/grid-3.js +2 -0
- package/src/configs/dashboard/grid-4.js +2 -0
- package/src/configs/dashboard/grid.js +2 -0
- package/src/utils/helpers.mjs +13 -1
- package/src/widgets/Dashboard/DatasourceFilterSharing.vue +93 -0
- package/src/widgets/Dashboard.vue +144 -82
package/package.json
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="$style.comp">
|
|
3
|
+
<div class="flex flex-row items-center gap-2 p-1 px-3 p-2">
|
|
4
|
+
<div class="flex-1">
|
|
5
|
+
<label class="text-text-400">{{ label }}</label>
|
|
6
|
+
</div>
|
|
7
|
+
<label class="text-sm text-text-300">Total points: {{ uniqueCount }}</label>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
3
10
|
<div v-if="apiKey" ref="map" class="flex-1">
|
|
4
11
|
|
|
5
12
|
</div>
|
|
6
13
|
<div v-else class="flex-1 flex items-center justify-center text-text-400">{{ $t('Google maps api required') }}</div>
|
|
7
14
|
|
|
8
|
-
<div class="flex flex-row
|
|
9
|
-
|
|
15
|
+
<div class="flex flex-row">
|
|
16
|
+
|
|
17
|
+
<div class="flex-1 flex items-center justify-center divide-x divide-text-50 border-l-[1px] border-r-[1px] border-text-50">
|
|
18
|
+
<button type="button" class="p-1 px-3 hover:bg-primary text-text-400" @click="zoomOut">
|
|
19
|
+
<svg width="16" height="16" class="fill-text-500 hover: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="M400 288h-352c-17.69 0-32-14.32-32-32.01s14.31-31.99 32-31.99h352c17.69 0 32 14.3 32 31.99S417.7 288 400 288z"/></svg>
|
|
20
|
+
</button>
|
|
21
|
+
<button type="button" class="p-1 px-3 hover:bg-primary text-text-400 hover:text-text" @click="panLeft">
|
|
22
|
+
<svg width="16" height="16" class="fill-text-500 hover:fill-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M137.4 406.6l-128-127.1C3.125 272.4 0 264.2 0 255.1s3.125-16.38 9.375-22.63l128-127.1c9.156-9.156 22.91-11.9 34.88-6.943S192 115.1 192 128v255.1c0 12.94-7.781 24.62-19.75 29.58S146.5 415.8 137.4 406.6z"/></svg>
|
|
23
|
+
</button>
|
|
24
|
+
<button type="button" class="p-1 px-3 hover:bg-primary text-text-400 hover:text-text" @click="panUp">
|
|
25
|
+
<svg width="16" height="16" class="fill-text-500 hover:fill-text" 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="M9.39 265.4l127.1-128C143.6 131.1 151.8 128 160 128s16.38 3.125 22.63 9.375l127.1 128c9.156 9.156 11.9 22.91 6.943 34.88S300.9 320 287.1 320H32.01c-12.94 0-24.62-7.781-29.58-19.75S.2333 274.5 9.39 265.4z"/></svg>
|
|
26
|
+
</button>
|
|
27
|
+
<button type="button" class="p-1 px-3 hover:bg-primary text-text-400 hover:text-text" @click="panRight">
|
|
28
|
+
<svg width="16" height="16" class="fill-text-500 hover:fill-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M118.6 105.4l128 127.1C252.9 239.6 256 247.8 256 255.1s-3.125 16.38-9.375 22.63l-128 127.1c-9.156 9.156-22.91 11.9-34.88 6.943S64 396.9 64 383.1V128c0-12.94 7.781-24.62 19.75-29.58S109.5 96.23 118.6 105.4z"/></svg>
|
|
29
|
+
</button>
|
|
30
|
+
<button type="button" class="p-1 px-3 hover:bg-primary text-text-400 hover:text-text" @click="panDown">
|
|
31
|
+
<svg width="16" height="16" class="fill-text-500 hover:fill-text" 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>
|
|
32
|
+
</button>
|
|
33
|
+
<button type="button" class="p-1 px-3 hover:bg-primary text-text-400 hover:text-text" @click="zoomIn">
|
|
34
|
+
<svg width="16" height="16" class="fill-text-500 hover: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="M432 256c0 17.69-14.33 32.01-32 32.01H256v144c0 17.69-14.33 31.99-32 31.99s-32-14.3-32-31.99v-144H48c-17.67 0-32-14.32-32-32.01s14.33-31.99 32-31.99H192v-144c0-17.69 14.33-32.01 32-32.01s32 14.32 32 32.01v144h144C417.7 224 432 238.3 432 256z"/></svg>
|
|
35
|
+
</button>
|
|
36
|
+
</div>
|
|
10
37
|
|
|
11
38
|
</div>
|
|
12
39
|
</div>
|
|
@@ -25,6 +52,8 @@ export default{
|
|
|
25
52
|
props: {
|
|
26
53
|
column: String,
|
|
27
54
|
|
|
55
|
+
label: String,
|
|
56
|
+
|
|
28
57
|
value: Object,
|
|
29
58
|
|
|
30
59
|
apiKey: {
|
|
@@ -219,7 +248,31 @@ export default{
|
|
|
219
248
|
];
|
|
220
249
|
heatmap.set("gradient", gradient);
|
|
221
250
|
});
|
|
222
|
-
}
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
zoomIn(){
|
|
254
|
+
this.map.setZoom(this.map.getZoom() + 1)
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
zoomOut(){
|
|
258
|
+
this.map.setZoom(this.map.getZoom() - 1)
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
panLeft(){
|
|
262
|
+
this.map.panBy(-50, 0);
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
panUp(){
|
|
266
|
+
this.map.panBy(0, -50);
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
panRight(){
|
|
270
|
+
this.map.panBy(50, 0);
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
panDown(){
|
|
274
|
+
this.map.panBy(0, 50);
|
|
275
|
+
},
|
|
223
276
|
|
|
224
277
|
},
|
|
225
278
|
|
package/src/utils/helpers.mjs
CHANGED
|
@@ -372,6 +372,17 @@ const round = (num, precision = 0) => {
|
|
|
372
372
|
return Math.round(n) / p
|
|
373
373
|
}
|
|
374
374
|
|
|
375
|
+
const invokeAfterIdle = (callback, delay = 1800) => {
|
|
376
|
+
let timeoutId
|
|
377
|
+
|
|
378
|
+
return function(){
|
|
379
|
+
window.clearTimeout(timeoutId)
|
|
380
|
+
timeoutId = window.setTimeout(() => {
|
|
381
|
+
callback.apply(this, arguments)
|
|
382
|
+
}, delay)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
375
386
|
|
|
376
387
|
export {
|
|
377
388
|
capitalize,
|
|
@@ -397,7 +408,8 @@ export {
|
|
|
397
408
|
createFormData,
|
|
398
409
|
unslugAndCapitalize,
|
|
399
410
|
applyDatasourceReplacer,
|
|
400
|
-
strVars
|
|
411
|
+
strVars,
|
|
412
|
+
invokeAfterIdle
|
|
401
413
|
}
|
|
402
414
|
|
|
403
415
|
function observeInit(){
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Modal ref="modal"
|
|
3
|
+
width="330"
|
|
4
|
+
height="360">
|
|
5
|
+
<template v-slot:head>
|
|
6
|
+
<div class="relative p-6">
|
|
7
|
+
<h3>Assign This Filter For</h3>
|
|
8
|
+
<div class="absolute top-0 right-0 p-2">
|
|
9
|
+
<button type="button" class="p-2" @click="close">
|
|
10
|
+
<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">
|
|
11
|
+
<path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
|
|
12
|
+
</svg>
|
|
13
|
+
</button>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
<template v-slot:foot>
|
|
18
|
+
<div class="p-6" v-if="items?.length > 0 && !readonly">
|
|
19
|
+
<Button class="w-[80px]" @click="apply">OK</Button>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
<div class="flex-1 p-6 flex">
|
|
23
|
+
|
|
24
|
+
<div v-if="items?.length > 0" class="flex flex-col gap-3">
|
|
25
|
+
<div v-for="item in items">
|
|
26
|
+
<Checkbox v-model="instance" :value="item.id" :disabled="readonly">
|
|
27
|
+
{{ item.name }}
|
|
28
|
+
</Checkbox>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div v-else class="flex-1 flex items-center justify-center">
|
|
33
|
+
<label class="text-text-300">No users shared</label>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
</div>
|
|
37
|
+
</Modal>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<script>
|
|
41
|
+
|
|
42
|
+
export default{
|
|
43
|
+
|
|
44
|
+
inject: [ 'socketEmit2' ],
|
|
45
|
+
|
|
46
|
+
props: {
|
|
47
|
+
items: Array,
|
|
48
|
+
readonly: [ Number, Boolean ],
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
computed: {
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
data(){
|
|
57
|
+
return {
|
|
58
|
+
instance: null,
|
|
59
|
+
callback: null
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
methods: {
|
|
64
|
+
|
|
65
|
+
apply(){
|
|
66
|
+
const instance = this.instance.map(_ => this.items.find(__ => __.id === _))
|
|
67
|
+
this.callback(instance)
|
|
68
|
+
this.close()
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
open(instance = [], callback){
|
|
72
|
+
this.instance = instance.map(_ => _.id)
|
|
73
|
+
this.callback = callback
|
|
74
|
+
this.$refs.modal.open()
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
close(){
|
|
78
|
+
this.$refs.modal.close()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<style module>
|
|
88
|
+
|
|
89
|
+
.comp{
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
</style>
|
|
@@ -77,68 +77,83 @@
|
|
|
77
77
|
</ListItem>
|
|
78
78
|
</div>
|
|
79
79
|
|
|
80
|
-
<div v-else-if="selectedDatasource.tabIndex === 2" class="flex-1 flex flex-col divide-y divide-text-50">
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<PresetSelectorFilterItem
|
|
111
|
-
class="flex-1"
|
|
112
|
-
:column="selectedDatasourceColumn(filter.key)"
|
|
113
|
-
:type="typeOf(selectedDatasourceColumn(filter.key).type)"
|
|
114
|
-
:typeParams="typeParamsOf(selectedDatasourceColumn(filter.key))"
|
|
115
|
-
:value="filterVal"
|
|
116
|
-
:enumCache="enumCache"
|
|
117
|
-
:readonly="selectedPreset.readonly"
|
|
118
|
-
@change="onDatasourceFilterChanged" />
|
|
119
|
-
|
|
120
|
-
<button v-if="filter.value.length > 1 && !selectedPreset.readonly"
|
|
121
|
-
type="button"
|
|
122
|
-
class="p-1"
|
|
123
|
-
@click="filter.value.splice(filterIdx, 1);onDatasourceFilterChanged()">
|
|
80
|
+
<div v-else-if="selectedDatasource.tabIndex === 2" class="flex-1 flex flex-col divide-y divide-text-50 py-3">
|
|
81
|
+
|
|
82
|
+
<ListItem :items="selectedDatasource.filters"
|
|
83
|
+
class="bg-transparent"
|
|
84
|
+
container-class="flex flex-col divide-y divide-text-50"
|
|
85
|
+
@reorder="(from, to) => { selectedDatasource.filters.splice(to, 0, selectedDatasource.filters.splice(from, 1)[0]); }">
|
|
86
|
+
<template v-slot="{ item:filter, index }">
|
|
87
|
+
<div class="p-5">
|
|
88
|
+
<div class="flex flex-row items-start">
|
|
89
|
+
<Checkbox v-model="filter.enabled" :disabled="selectedPreset.readonly" :default="true" @change="onDatasourceFilterChanged"/>
|
|
90
|
+
<div class="flex-1 flex flex-col gap-3">
|
|
91
|
+
<div class="flex-1 flex flex-row items-center gap-2">
|
|
92
|
+
<strong data-reorder class="flex-1 cursor-pointer whitespace-nowrap text-ellipsis overflow-hidden"
|
|
93
|
+
@click="filter._collapsed = !filter._collapsed">
|
|
94
|
+
<svg class="inline fill-text transition-transform relative top-[-1px]"
|
|
95
|
+
:class="filter._collapsed === true ? `` : `rotate-90`"
|
|
96
|
+
width="11" height="11" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M118.6 105.4l128 127.1C252.9 239.6 256 247.8 256 255.1s-3.125 16.38-9.375 22.63l-128 127.1c-9.156 9.156-22.91 11.9-34.88 6.943S64 396.9 64 383.1V128c0-12.94 7.781-24.62 19.75-29.58S109.5 96.23 118.6 105.4z"/></svg>
|
|
97
|
+
{{ selectedDatasourceColumn(filter.key).label ?? filter.key }}
|
|
98
|
+
</strong>
|
|
99
|
+
<select v-if="filter.value.length > 1"
|
|
100
|
+
v-model="filter.modifier"
|
|
101
|
+
class="appearance-none bg-text-50 min-w-[60px] text-text-400 px-2 outline-none"
|
|
102
|
+
@change="onDatasourceFilterChanged()">
|
|
103
|
+
<option value="and">And</option>
|
|
104
|
+
<option value="or">Or</option>
|
|
105
|
+
</select>
|
|
106
|
+
<button v-if="!selectedPreset.readonly && typeOf(selectedDatasourceColumn(filter.key).type) !== 'enum' && filter._collapsed !== true" type="button" @click="filter.value.push({})">
|
|
107
|
+
<svg width="14" height="14" class="fill-text-300" 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="M432 256C432 269.3 421.3 280 408 280h-160v160c0 13.25-10.75 24.01-24 24.01S200 453.3 200 440v-160h-160c-13.25 0-24-10.74-24-23.99C16 242.8 26.75 232 40 232h160v-160c0-13.25 10.75-23.99 24-23.99S248 58.75 248 72v160h160C421.3 232 432 242.8 432 256z"/></svg>
|
|
108
|
+
</button>
|
|
109
|
+
<button v-if="!selectedPreset.readonly" type="button" class="p-1" @click="selectedDatasource.filters.splice(idx, 1);onDatasourceFilterChanged()">
|
|
124
110
|
<svg width="14" height="14" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M193.94 256L296.5 153.44l21.15-21.15c3.12-3.12 3.12-8.19 0-11.31l-22.63-22.63c-3.12-3.12-8.19-3.12-11.31 0L160 222.06 36.29 98.34c-3.12-3.12-8.19-3.12-11.31 0L2.34 120.97c-3.12 3.12-3.12 8.19 0 11.31L126.06 256 2.34 379.71c-3.12 3.12-3.12 8.19 0 11.31l22.63 22.63c3.12 3.12 8.19 3.12 11.31 0L160 289.94 262.56 392.5l21.15 21.15c3.12 3.12 8.19 3.12 11.31 0l22.63-22.63c3.12-3.12 3.12-8.19 0-11.31L193.94 256z"/></svg>
|
|
125
111
|
</button>
|
|
112
|
+
|
|
113
|
+
<button v-if="selectedPreset.sharing?.length > 0"
|
|
114
|
+
type="button"
|
|
115
|
+
class="p-0.5 rounded-full"
|
|
116
|
+
@click="$refs.datasourceFilterSharing.open(filter.sharing, (sharing) => { filter.sharing = sharing; load() })">
|
|
117
|
+
<svg width="14" height="14"
|
|
118
|
+
:class="filter.sharing?.length > 0 ? 'fill-primary' : 'fill-text-300 hover:fill-primary'" 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="M319.9 320c57.41 0 103.1-46.56 103.1-104c0-57.44-46.54-104-103.1-104c-57.41 0-103.1 46.56-103.1 104C215.9 273.4 262.5 320 319.9 320zM369.9 352H270.1C191.6 352 128 411.7 128 485.3C128 500.1 140.7 512 156.4 512h327.2C499.3 512 512 500.1 512 485.3C512 411.7 448.4 352 369.9 352zM512 160c44.18 0 80-35.82 80-80S556.2 0 512 0c-44.18 0-80 35.82-80 80S467.8 160 512 160zM183.9 216c0-5.449 .9824-10.63 1.609-15.91C174.6 194.1 162.6 192 149.9 192H88.08C39.44 192 0 233.8 0 285.3C0 295.6 7.887 304 17.62 304h199.5C196.7 280.2 183.9 249.7 183.9 216zM128 160c44.18 0 80-35.82 80-80S172.2 0 128 0C83.82 0 48 35.82 48 80S83.82 160 128 160zM551.9 192h-61.84c-12.8 0-24.88 3.037-35.86 8.24C454.8 205.5 455.8 210.6 455.8 216c0 33.71-12.78 64.21-33.16 88h199.7C632.1 304 640 295.6 640 285.3C640 233.8 600.6 192 551.9 192z"/></svg>
|
|
119
|
+
</button>
|
|
120
|
+
</div>
|
|
121
|
+
<div v-if="filter._collapsed !== true">
|
|
122
|
+
<div v-if="Array.isArray(filter.value)" class="flex flex-col gap-2">
|
|
123
|
+
<div class="flex flex-row gap-2" v-for="(filterVal, filterIdx) in filter.value">
|
|
124
|
+
<PresetSelectorFilterItem
|
|
125
|
+
class="flex-1"
|
|
126
|
+
:column="selectedDatasourceColumn(filter.key)"
|
|
127
|
+
:type="typeOf(selectedDatasourceColumn(filter.key).type)"
|
|
128
|
+
:typeParams="typeParamsOf(selectedDatasourceColumn(filter.key))"
|
|
129
|
+
:value="filterVal"
|
|
130
|
+
:enumCache="enumCache"
|
|
131
|
+
:readonly="selectedPreset.readonly"
|
|
132
|
+
@change="onDatasourceFilterChanged" />
|
|
133
|
+
|
|
134
|
+
<button v-if="filter.value.length > 1 && !selectedPreset.readonly"
|
|
135
|
+
type="button"
|
|
136
|
+
class="p-1"
|
|
137
|
+
@click="filter.value.splice(filterIdx, 1);onDatasourceFilterChanged()">
|
|
138
|
+
<svg width="14" height="14" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M193.94 256L296.5 153.44l21.15-21.15c3.12-3.12 3.12-8.19 0-11.31l-22.63-22.63c-3.12-3.12-8.19-3.12-11.31 0L160 222.06 36.29 98.34c-3.12-3.12-8.19-3.12-11.31 0L2.34 120.97c-3.12 3.12-3.12 8.19 0 11.31L126.06 256 2.34 379.71c-3.12 3.12-3.12 8.19 0 11.31l22.63 22.63c3.12 3.12 8.19 3.12 11.31 0L160 289.94 262.56 392.5l21.15 21.15c3.12 3.12 8.19 3.12 11.31 0l22.63-22.63c3.12-3.12 3.12-8.19 0-11.31L193.94 256z"/></svg>
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
<PresetSelectorFilterItem v-else
|
|
143
|
+
:column="selectedDatasourceColumn(filter.key)"
|
|
144
|
+
:type="typeOf(selectedDatasourceColumn(filter.key).type)"
|
|
145
|
+
:value="filter"
|
|
146
|
+
:enumCache="enumCache"
|
|
147
|
+
:readonly="selectedPreset.readonly"
|
|
148
|
+
@change="onDatasourceFilterChanged" />
|
|
126
149
|
</div>
|
|
127
150
|
</div>
|
|
128
|
-
<PresetSelectorFilterItem v-else
|
|
129
|
-
:column="selectedDatasourceColumn(filter.key)"
|
|
130
|
-
:type="typeOf(selectedDatasourceColumn(filter.key).type)"
|
|
131
|
-
:value="filter"
|
|
132
|
-
:enumCache="enumCache"
|
|
133
|
-
:readonly="selectedPreset.readonly"
|
|
134
|
-
@change="onDatasourceFilterChanged" />
|
|
135
151
|
</div>
|
|
136
152
|
</div>
|
|
137
|
-
</
|
|
138
|
-
|
|
139
|
-
</div>
|
|
153
|
+
</template>
|
|
154
|
+
</ListItem>
|
|
140
155
|
|
|
141
|
-
<div v-for="(filter, idx) in queryFilters[selectedDatasource.uid]" class="p-5
|
|
156
|
+
<div v-for="(filter, idx) in queryFilters[selectedDatasource.uid]" class="p-5">
|
|
142
157
|
|
|
143
158
|
<div class="flex flex-col gap-2">
|
|
144
159
|
<strong>{{ filter.key }}</strong>
|
|
@@ -152,7 +167,7 @@
|
|
|
152
167
|
|
|
153
168
|
</div>
|
|
154
169
|
|
|
155
|
-
<div class="
|
|
170
|
+
<div class="p-5 flex justify-center" v-if="!selectedPreset.readonly">
|
|
156
171
|
<button type="button"
|
|
157
172
|
class="text-primary flex flex-row items-center justify-center p-3"
|
|
158
173
|
@click="$refs.columnSelector.open(addFilter, selectedDatasourceFilterColumns)">
|
|
@@ -160,6 +175,8 @@
|
|
|
160
175
|
Add Filter
|
|
161
176
|
</button>
|
|
162
177
|
</div>
|
|
178
|
+
|
|
179
|
+
<DatasourceFilterSharing ref="datasourceFilterSharing" :items="selectedPreset.sharing" :readonly="selectedPreset.readonly" />
|
|
163
180
|
</div>
|
|
164
181
|
|
|
165
182
|
<div v-else-if="selectedDatasource.tabIndex === 3" class="p-5 flex-1 flex flex-col">
|
|
@@ -386,13 +403,13 @@
|
|
|
386
403
|
<SharingModal ref="sharingModal" :src="sharingSrc" />
|
|
387
404
|
</div>
|
|
388
405
|
<div class="flex flex-col gap-1 mt-2">
|
|
389
|
-
<div v-for="user in selectedPreset.sharing"
|
|
406
|
+
<div v-for="(user, index) in selectedPreset.sharing"
|
|
390
407
|
class="bg-base-500 hover:bg-text-50 p-3 rounded-lg flex flex-row gap-2 items-center gap-1">
|
|
391
408
|
<div class="flex-1 flex flex-row items-center cursor-default gap-2">
|
|
392
409
|
<svg width="14" height="14" class="fill-text-200" 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="M224 256c70.7 0 128-57.31 128-128s-57.3-128-128-128C153.3 0 96 57.31 96 128S153.3 256 224 256zM274.7 304H173.3C77.61 304 0 381.6 0 477.3c0 19.14 15.52 34.67 34.66 34.67h378.7C432.5 512 448 496.5 448 477.3C448 381.6 370.4 304 274.7 304z"/></svg>
|
|
393
410
|
{{ user.name }}
|
|
394
411
|
</div>
|
|
395
|
-
<button type="button" @click="
|
|
412
|
+
<button type="button" @click="removeSharing(index)">
|
|
396
413
|
<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>
|
|
397
414
|
</button>
|
|
398
415
|
</div>
|
|
@@ -487,7 +504,7 @@
|
|
|
487
504
|
</div>
|
|
488
505
|
|
|
489
506
|
<button class="w-full p-3 text-left flex flex-row items-center" :class="appStyle.menuItem"
|
|
490
|
-
@click="confirm('Remove this preset?', () =>
|
|
507
|
+
@click="confirm('Remove this preset?', () => removePreset(context.index))">
|
|
491
508
|
<div class="w-[30px]">
|
|
492
509
|
<svg width="16" height="16" class="fill-text-300" 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>
|
|
493
510
|
</div>
|
|
@@ -533,10 +550,6 @@
|
|
|
533
550
|
|
|
534
551
|
</div>
|
|
535
552
|
|
|
536
|
-
<div class="p-5">
|
|
537
|
-
<Button ref="saveConfigBtn" class="w-[90px] py-2" :state="configChanged ? 1 : -1" @click="save">Save</Button>
|
|
538
|
-
</div>
|
|
539
|
-
|
|
540
553
|
</TransitionGroup>
|
|
541
554
|
|
|
542
555
|
<div :class="$style.resize1"
|
|
@@ -648,12 +661,12 @@ import TreeView from "./WebPageBuilder4/TreeView.vue";
|
|
|
648
661
|
import DoughnutSetting from "./Dashboard/DoughnutSetting.vue";
|
|
649
662
|
import PieSetting from "./Dashboard/PieSetting.vue";
|
|
650
663
|
import PolarAreaSetting from "./Dashboard/PolarAreaSetting.vue";
|
|
651
|
-
import {useDatasource} from "../stores/datasource";
|
|
652
664
|
import {defineAsyncComponent} from "vue";
|
|
653
665
|
import SharingModal from "./Dashboard/SharingModal.vue";
|
|
654
666
|
import PresetSelectorFilterItem from "../components/PresetSelectorFilterItem.vue";
|
|
655
667
|
import {generatePivotColumns} from "../utils/preset-selector.mjs";
|
|
656
668
|
import PresetBarPivot from "./PresetBarPivot.vue";
|
|
669
|
+
import {invokeAfterIdle} from "../utils/helpers.mjs";
|
|
657
670
|
|
|
658
671
|
const findComponents = (items, uid) => {
|
|
659
672
|
if(!Array.isArray(items)) return
|
|
@@ -670,9 +683,13 @@ const findComponents = (items, uid) => {
|
|
|
670
683
|
}
|
|
671
684
|
}
|
|
672
685
|
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
|
|
673
689
|
export default{
|
|
674
690
|
|
|
675
691
|
components: {
|
|
692
|
+
DatasourceFilterSharing: defineAsyncComponent(() => import('./Dashboard/DatasourceFilterSharing.vue')),
|
|
676
693
|
PresetBarPivot,
|
|
677
694
|
DatasourcePreview: defineAsyncComponent(() => import('./Dashboard/DatasourcePreview.vue')),
|
|
678
695
|
PresetSelectorFilterItem,
|
|
@@ -972,7 +989,8 @@ export default{
|
|
|
972
989
|
|
|
973
990
|
addView(item, items, opt = { unshift:false }){
|
|
974
991
|
items[opt?.unshift ? 'unshift' : 'push'](item)
|
|
975
|
-
|
|
992
|
+
if(item.openOnAdd !== false)
|
|
993
|
+
this.$nextTick(() => this.cConfig.selectedView = item.uid)
|
|
976
994
|
},
|
|
977
995
|
|
|
978
996
|
emitRoot(name, component){
|
|
@@ -1166,12 +1184,15 @@ export default{
|
|
|
1166
1184
|
async load(uids){
|
|
1167
1185
|
if(this.readyState !== 1) return
|
|
1168
1186
|
if(!this.viewedComponents) return
|
|
1187
|
+
if(!this.cConfig) return
|
|
1169
1188
|
|
|
1170
1189
|
const views = this.recurseViews(this.viewedComponents, uids)
|
|
1171
1190
|
if(views?.length < 1) return
|
|
1172
1191
|
|
|
1192
|
+
const { datasource } = this.viewedPreset
|
|
1193
|
+
|
|
1173
1194
|
if(!uids) this.readyState = 0
|
|
1174
|
-
this.socket.send(this.src, { views })
|
|
1195
|
+
this.socket.send(this.src, { views, datasource })
|
|
1175
1196
|
.then(_ => {
|
|
1176
1197
|
Object.assign(this.values, _)
|
|
1177
1198
|
})
|
|
@@ -1218,18 +1239,14 @@ export default{
|
|
|
1218
1239
|
this.$nextTick(() => {
|
|
1219
1240
|
this.cConfig.viewedUid = newPreset.uid
|
|
1220
1241
|
this.openPreset(newPreset.uid)
|
|
1242
|
+
this.selectPreset(newPreset.uid)
|
|
1243
|
+
this.saveConfig()
|
|
1221
1244
|
})
|
|
1222
1245
|
},
|
|
1223
1246
|
|
|
1224
1247
|
openPreset(uid, opt = {}){
|
|
1225
1248
|
this.cConfig.selectedUid = uid
|
|
1226
|
-
|
|
1227
|
-
query:{
|
|
1228
|
-
...(this.$route.query ?? {}),
|
|
1229
|
-
edit:uid,
|
|
1230
|
-
...(opt.select ? { uid } : {})
|
|
1231
|
-
}
|
|
1232
|
-
})*/
|
|
1249
|
+
this.saveConfig()
|
|
1233
1250
|
},
|
|
1234
1251
|
|
|
1235
1252
|
selectPreset(uid, params = {}){
|
|
@@ -1239,6 +1256,7 @@ export default{
|
|
|
1239
1256
|
...params
|
|
1240
1257
|
}
|
|
1241
1258
|
})
|
|
1259
|
+
this.saveConfig()
|
|
1242
1260
|
},
|
|
1243
1261
|
|
|
1244
1262
|
resize1(w){
|
|
@@ -1288,23 +1306,51 @@ export default{
|
|
|
1288
1306
|
})
|
|
1289
1307
|
},
|
|
1290
1308
|
|
|
1291
|
-
|
|
1292
|
-
this
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1309
|
+
saveConfig: invokeAfterIdle(function() {
|
|
1310
|
+
if(this.selectedPreset.readonly) return
|
|
1311
|
+
|
|
1312
|
+
this.$emit('save', {
|
|
1313
|
+
config:this.cConfig,
|
|
1314
|
+
presets: undefined
|
|
1315
|
+
})
|
|
1316
|
+
}),
|
|
1317
|
+
|
|
1318
|
+
removePreset(index){
|
|
1319
|
+
const [ preset ] = this.cConfig.presets.splice(index, 1)
|
|
1320
|
+
this.$emit('save', { removePreset:{ uid:preset.uid } })
|
|
1321
|
+
},
|
|
1322
|
+
|
|
1323
|
+
savePreset: invokeAfterIdle(function(){
|
|
1324
|
+
if(this.selectedPreset.readonly) return
|
|
1325
|
+
this.$emit('save', { preset:this.selectedPreset })
|
|
1326
|
+
}),
|
|
1327
|
+
|
|
1328
|
+
removeSharing(index){
|
|
1329
|
+
const user = this.selectedPreset.sharing[index]
|
|
1330
|
+
|
|
1331
|
+
for(let datasource of this.selectedPreset.datasource){
|
|
1332
|
+
for(let filter of datasource.filters){
|
|
1333
|
+
const index = (filter.sharing ?? []).findIndex(_ => _.id === user.id)
|
|
1334
|
+
if(index > -1){
|
|
1335
|
+
filter.sharing.splice(index, 1)
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
this.selectedPreset.sharing.splice(index, 1)
|
|
1297
1341
|
}
|
|
1298
1342
|
|
|
1299
1343
|
},
|
|
1300
1344
|
|
|
1345
|
+
mounted() {
|
|
1346
|
+
this.load()
|
|
1347
|
+
},
|
|
1348
|
+
|
|
1301
1349
|
props:{
|
|
1302
1350
|
|
|
1303
1351
|
config: Object,
|
|
1304
1352
|
|
|
1305
1353
|
src: String,
|
|
1306
|
-
configSrc: String,
|
|
1307
|
-
configKey: String,
|
|
1308
1354
|
|
|
1309
1355
|
datasourceSrc: String,
|
|
1310
1356
|
datasourceListSrc: String,
|
|
@@ -1334,7 +1380,7 @@ export default{
|
|
|
1334
1380
|
|
|
1335
1381
|
watch: {
|
|
1336
1382
|
|
|
1337
|
-
'cConfig.presets'(){
|
|
1383
|
+
'cConfig.presets'(to){
|
|
1338
1384
|
this.cConfig.viewedUid = 'uid' in this.$route.query ? this.$route.query.uid : this.cConfig.viewedUid
|
|
1339
1385
|
},
|
|
1340
1386
|
|
|
@@ -1342,6 +1388,14 @@ export default{
|
|
|
1342
1388
|
this.$emit('change')
|
|
1343
1389
|
},
|
|
1344
1390
|
|
|
1391
|
+
'cConfig.selectedUid'(){
|
|
1392
|
+
this.saveConfig()
|
|
1393
|
+
},
|
|
1394
|
+
|
|
1395
|
+
'cConfig.selectedDatasource'(){
|
|
1396
|
+
this.saveConfig()
|
|
1397
|
+
},
|
|
1398
|
+
|
|
1345
1399
|
'$route.query': {
|
|
1346
1400
|
handler(to){
|
|
1347
1401
|
if(this.cConfig){
|
|
@@ -1352,10 +1406,18 @@ export default{
|
|
|
1352
1406
|
},
|
|
1353
1407
|
|
|
1354
1408
|
cConfig(to, from){
|
|
1409
|
+
console.log('cConfig', from)
|
|
1355
1410
|
if(!from){
|
|
1356
1411
|
this.load()
|
|
1357
1412
|
this.initialConfig = JSON.stringify(this.cConfig)
|
|
1358
1413
|
}
|
|
1414
|
+
},
|
|
1415
|
+
|
|
1416
|
+
selectedPreset:{
|
|
1417
|
+
deep: true,
|
|
1418
|
+
handler(to) {
|
|
1419
|
+
this.savePreset()
|
|
1420
|
+
}
|
|
1359
1421
|
}
|
|
1360
1422
|
|
|
1361
1423
|
}
|