@mixd-id/web-scaffold 0.2.240701 → 0.2.240703
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 +35 -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 -10
- 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/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/UserActionBuilder/UserActionCondition.vue +97 -0
- package/src/widgets/UserActionBuilder/UserActionConsole.vue +77 -0
- package/src/widgets/UserActionBuilder/UserActionItem.vue +163 -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 +211 -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
|
@@ -0,0 +1,1773 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="cConfig && presets" :class="$style.comp">
|
|
3
|
+
|
|
4
|
+
<div :style="sidebarStyle"
|
|
5
|
+
class="relative flex flex-col border-r-[1px] border-text-50 panel-400 overflow-hidden">
|
|
6
|
+
|
|
7
|
+
<TransitionGroup class="flex-1 flex flex-col" name="openltr" tag="div">
|
|
8
|
+
|
|
9
|
+
<div v-if="selectedView" class="flex-1 flex flex-col">
|
|
10
|
+
<div class="p-5 flex flex-row gap-3">
|
|
11
|
+
<button type="button" @click="delete cConfig.selectedView">
|
|
12
|
+
<svg class="fill-text hover:fill-primary" height="16" viewBox="0 0 448 512" width="16"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
14
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
15
|
+
<path
|
|
16
|
+
d="M447.1 256C447.1 273.7 433.7 288 416 288H109.3l105.4 105.4c12.5 12.5 12.5 32.75 0 45.25C208.4 444.9 200.2 448 192 448s-16.38-3.125-22.62-9.375l-160-160c-12.5-12.5-12.5-32.75 0-45.25l160-160c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25L109.3 224H416C433.7 224 447.1 238.3 447.1 256z"/>
|
|
17
|
+
</svg>
|
|
18
|
+
</button>
|
|
19
|
+
<div class="leading-tight flex-1">
|
|
20
|
+
<small class="text-xs text-text-400">{{ selectedView.type }}</small>
|
|
21
|
+
<h5 class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap" @click="log(selectedView)">
|
|
22
|
+
{{ selectedView.props.label ?? selectedView.name }}
|
|
23
|
+
</h5>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="flex-1 overflow-y-auto flex flex-col">
|
|
28
|
+
|
|
29
|
+
<component :is="`${selectedView?.type}Setting`"
|
|
30
|
+
:config="config"
|
|
31
|
+
:datasource="selectedPreset.datasource"
|
|
32
|
+
:index="viewTypeIndex"
|
|
33
|
+
:readonly="selectedPreset.readonly"
|
|
34
|
+
:value="selectedView"
|
|
35
|
+
:view-type="config.viewType"
|
|
36
|
+
@change="load({ [selectedView.uid]:selectedView })"/>
|
|
37
|
+
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div v-else-if="selectedDatasource" class="flex-1 flex flex-col">
|
|
42
|
+
<div class="p-5 flex flex-row items-center gap-2 pb-0">
|
|
43
|
+
<button type="button" @click="delete cConfig.selectedDatasource">
|
|
44
|
+
<svg class="fill-text hover:fill-primary" height="16" viewBox="0 0 448 512" width="16"
|
|
45
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
46
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
47
|
+
<path
|
|
48
|
+
d="M447.1 256C447.1 273.7 433.7 288 416 288H109.3l105.4 105.4c12.5 12.5 12.5 32.75 0 45.25C208.4 444.9 200.2 448 192 448s-16.38-3.125-22.62-9.375l-160-160c-12.5-12.5-12.5-32.75 0-45.25l160-160c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25L109.3 224H416C433.7 224 447.1 238.3 447.1 256z"/>
|
|
49
|
+
</svg>
|
|
50
|
+
</button>
|
|
51
|
+
<Textbox v-model="selectedDatasource.name"
|
|
52
|
+
class="flex-1 bg-transparent border-transparent rounded-none"
|
|
53
|
+
item-class="font-bold text-lg p-0"
|
|
54
|
+
@click="log(selectedDatasource)"/>
|
|
55
|
+
<button v-if="previewSrc" class="text-primary" type="button"
|
|
56
|
+
@click="previewDatasource(selectedDatasource)">
|
|
57
|
+
Preview
|
|
58
|
+
</button>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="flex justify-center border-b-[1px] border-text-50 mt-3">
|
|
62
|
+
<Tabs v-model="selectedDatasource.tabIndex" :items="datasourceTabs"/>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="flex-1 overflow-y-auto flex">
|
|
66
|
+
|
|
67
|
+
<div v-if="selectedDatasource.tabIndex === 1" class="py-5 flex-1 flex flex-col gap-5">
|
|
68
|
+
|
|
69
|
+
<div class="px-5">
|
|
70
|
+
<Textbox placeholder="Search columns..." v-model="datasourceColumnSearch" />
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<VirtualGrid class="flex-1"
|
|
74
|
+
:items="selectedDatasourceColumns">
|
|
75
|
+
<template #item="{ item }">
|
|
76
|
+
<div v-if="!item.key.startsWith('_') || (item.key.startsWith('_') && (preset.pivot && preset.pivot.enabled))"
|
|
77
|
+
class="flex flex-row items-center gap-3 mx-5">
|
|
78
|
+
<div class="flex-1 flex flex-row gap-2 items-center" :class="$style.button">
|
|
79
|
+
<div>
|
|
80
|
+
{{ item.label2 ?? item.label }}
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</template>
|
|
85
|
+
</VirtualGrid>
|
|
86
|
+
|
|
87
|
+
<div class="h-[1px] bg-text-50"></div>
|
|
88
|
+
|
|
89
|
+
<div class="h-[200px] flex flex-col">
|
|
90
|
+
<div class="flex flex-row gap-2 px-5">
|
|
91
|
+
<label class="text-text-400 flex-1">Computed Columns</label>
|
|
92
|
+
<button type="button" class="text-primary" @click="$refs.virtualColumnEdit.open({}, addComputedColumns)">
|
|
93
|
+
Add Column
|
|
94
|
+
</button>
|
|
95
|
+
</div>
|
|
96
|
+
<VirtualGrid class="flex-1 mt-5" :items="selectedDatasourceComputedColumns">
|
|
97
|
+
<template #item="{ item, index }">
|
|
98
|
+
<div class="flex flex-row items-center gap-3 p-3 mx-5 group" :class="$style.button">
|
|
99
|
+
<div class="flex-1">{{ item.label }}</div>
|
|
100
|
+
<div class="hidden flex-row gap-3 group-hover:flex">
|
|
101
|
+
<button type="button" class="text-primary" @click="selectedDatasource.computedColumns.splice(index, 1)">
|
|
102
|
+
<svg width="16" height="16" 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="M312.1 375c9.369 9.369 9.369 24.57 0 33.94s-24.57 9.369-33.94 0L160 289.9l-119 119c-9.369 9.369-24.57 9.369-33.94 0s-9.369-24.57 0-33.94L126.1 256L7.027 136.1c-9.369-9.369-9.369-24.57 0-33.94s24.57-9.369 33.94 0L160 222.1l119-119c9.369-9.369 24.57-9.369 33.94 0s9.369 24.57 0 33.94L193.9 256L312.1 375z"/></svg>
|
|
103
|
+
</button>
|
|
104
|
+
<button type="button" class="text-primary" @click="$refs.virtualColumnEdit.open(item, addComputedColumns)">
|
|
105
|
+
<svg width="14" height="14" class="fill-text-300 hover:fill-primary-600" 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="M383.1 448H63.1V128h156.1l64-64H63.1C28.65 64 0 92.65 0 128v320c0 35.35 28.65 64 63.1 64h319.1c35.34 0 63.1-28.65 63.1-64l-.0039-220.1l-63.1 63.99V448zM497.9 42.19l-28.13-28.14c-18.75-18.75-49.14-18.75-67.88 0l-38.62 38.63l96.01 96.01l38.62-38.63C516.7 91.33 516.7 60.94 497.9 42.19zM147.3 274.4l-19.04 95.22c-1.678 8.396 5.725 15.8 14.12 14.12l95.23-19.04c4.646-.9297 8.912-3.213 12.26-6.562l186.8-186.8l-96.01-96.01L153.8 262.2C150.5 265.5 148.2 269.8 147.3 274.4z"/></svg>
|
|
106
|
+
</button>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</template>
|
|
110
|
+
</VirtualGrid>
|
|
111
|
+
|
|
112
|
+
<VirtualColumnEdit ref="virtualColumnEdit" :columns="selectedDatasource.columns" />
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<div v-else-if="selectedDatasource.tabIndex === 2"
|
|
117
|
+
class="flex-1 flex flex-col divide-y divide-text-50 py-3">
|
|
118
|
+
|
|
119
|
+
<ListItem :items="selectedDatasource.filters"
|
|
120
|
+
class="bg-transparent"
|
|
121
|
+
container-class="flex flex-col divide-y divide-text-50"
|
|
122
|
+
@reorder="(from, to) => { selectedDatasource.filters.splice(to, 0, selectedDatasource.filters.splice(from, 1)[0]); }">
|
|
123
|
+
<template v-slot="{ item:filter, index:idx }">
|
|
124
|
+
<div class="p-5">
|
|
125
|
+
<div class="flex flex-row items-start">
|
|
126
|
+
<Checkbox v-model="filter.enabled" :default="true" :disabled="selectedPreset.readonly"
|
|
127
|
+
@change="onDatasourceFilterChanged"/>
|
|
128
|
+
<div class="flex-1 flex flex-col gap-3">
|
|
129
|
+
<div class="flex-1 flex flex-row items-center gap-2">
|
|
130
|
+
<strong class="flex-1 cursor-pointer whitespace-nowrap text-ellipsis overflow-hidden"
|
|
131
|
+
data-reorder
|
|
132
|
+
@click="filter._collapsed = !filter._collapsed">
|
|
133
|
+
<svg :class="filter._collapsed === true ? `` : `rotate-90`"
|
|
134
|
+
class="inline fill-text transition-transform relative top-[-1px]"
|
|
135
|
+
height="11" viewBox="0 0 256 512" width="11" xmlns="http://www.w3.org/2000/svg">
|
|
136
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
137
|
+
<path
|
|
138
|
+
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"/>
|
|
139
|
+
</svg>
|
|
140
|
+
{{ selectedDatasourceColumn(filter.key).label ?? filter.key }}
|
|
141
|
+
</strong>
|
|
142
|
+
<select v-if="filter.value.length > 1"
|
|
143
|
+
v-model="filter.modifier"
|
|
144
|
+
class="appearance-none bg-text-50 min-w-[60px] text-text-400 px-2 outline-none"
|
|
145
|
+
@change="onDatasourceFilterChanged()">
|
|
146
|
+
<option value="and">And</option>
|
|
147
|
+
<option value="or">Or</option>
|
|
148
|
+
</select>
|
|
149
|
+
<button
|
|
150
|
+
v-if="!selectedPreset.readonly && typeOf(selectedDatasourceColumn(filter.key).type) !== 'enum' && filter._collapsed !== true"
|
|
151
|
+
type="button" @click="filter.value.push({})">
|
|
152
|
+
<svg class="fill-text-300" height="14" viewBox="0 0 448 512" width="14"
|
|
153
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
154
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
155
|
+
<path
|
|
156
|
+
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"/>
|
|
157
|
+
</svg>
|
|
158
|
+
</button>
|
|
159
|
+
<button v-if="!selectedPreset.readonly" class="p-1" type="button"
|
|
160
|
+
@click="selectedDatasource.filters.splice(idx, 1);onDatasourceFilterChanged()">
|
|
161
|
+
<svg class="fill-text-300 hover:fill-red-500" height="14" viewBox="0 0 320 512"
|
|
162
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
163
|
+
<path
|
|
164
|
+
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"/>
|
|
165
|
+
</svg>
|
|
166
|
+
</button>
|
|
167
|
+
|
|
168
|
+
<button v-if="selectedPreset.sharing?.length > 0 && !selectedPreset.readonly"
|
|
169
|
+
class="p-0.5 rounded-full"
|
|
170
|
+
type="button"
|
|
171
|
+
@click="$refs.datasourceFilterSharing.open(filter.sharing, (sharing) => { filter.sharing = sharing; load() })">
|
|
172
|
+
<svg :class="filter.sharing?.length > 0 ? 'fill-primary' : 'fill-text-300 hover:fill-primary'" height="14"
|
|
173
|
+
viewBox="0 0 640 512"
|
|
174
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
175
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
176
|
+
<path
|
|
177
|
+
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"/>
|
|
178
|
+
</svg>
|
|
179
|
+
</button>
|
|
180
|
+
</div>
|
|
181
|
+
<div v-if="filter._collapsed !== true">
|
|
182
|
+
<div v-if="Array.isArray(filter.value)" class="flex flex-col gap-2">
|
|
183
|
+
<div v-for="(filterVal, filterIdx) in filter.value" class="flex flex-row gap-2">
|
|
184
|
+
<PresetSelectorFilterItem
|
|
185
|
+
:column="selectedDatasourceColumn(filter.key)"
|
|
186
|
+
:enumCache="enumCache"
|
|
187
|
+
:readonly="selectedPreset.readonly"
|
|
188
|
+
:type="typeOf(selectedDatasourceColumn(filter.key).type)"
|
|
189
|
+
:typeParams="typeParamsOf(selectedDatasourceColumn(filter.key))"
|
|
190
|
+
:value="filterVal"
|
|
191
|
+
class="flex-1"
|
|
192
|
+
@change="onDatasourceFilterChanged"/>
|
|
193
|
+
|
|
194
|
+
<button v-if="filter.value.length > 1 && !selectedPreset.readonly"
|
|
195
|
+
class="p-1"
|
|
196
|
+
type="button"
|
|
197
|
+
@click="filter.value.splice(filterIdx, 1);onDatasourceFilterChanged()">
|
|
198
|
+
<svg class="fill-text-300 hover:fill-red-500" height="14" viewBox="0 0 320 512"
|
|
199
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
200
|
+
<path
|
|
201
|
+
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"/>
|
|
202
|
+
</svg>
|
|
203
|
+
</button>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
<PresetSelectorFilterItem v-else
|
|
207
|
+
:column="selectedDatasourceColumn(filter.key)"
|
|
208
|
+
:enumCache="enumCache"
|
|
209
|
+
:readonly="selectedPreset.readonly"
|
|
210
|
+
:type="typeOf(selectedDatasourceColumn(filter.key).type)"
|
|
211
|
+
:value="filter"
|
|
212
|
+
@change="onDatasourceFilterChanged"/>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
</template>
|
|
218
|
+
</ListItem>
|
|
219
|
+
|
|
220
|
+
<div v-for="(filter, idx) in queryFilters[selectedDatasource.uid]" class="p-5">
|
|
221
|
+
|
|
222
|
+
<div class="flex flex-col gap-2">
|
|
223
|
+
<strong>{{ filter.key }}</strong>
|
|
224
|
+
<div class="flex flex-row gap-2">
|
|
225
|
+
<Dropdown v-model="filter.operator" :readonly="true" class="w-[100px]">
|
|
226
|
+
<option :value="filter.operator">{{ filter.operator }}</option>
|
|
227
|
+
</Dropdown>
|
|
228
|
+
<Textbox v-model="filter.value" :readonly="true" class="flex-1"/>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
</div>
|
|
233
|
+
|
|
234
|
+
<div v-if="!selectedPreset.readonly" class="p-5 flex justify-center">
|
|
235
|
+
<button class="text-primary flex flex-row items-center justify-center p-3"
|
|
236
|
+
type="button"
|
|
237
|
+
@click="$refs.columnSelector.open(addFilter, selectedDatasourceFilterColumns)">
|
|
238
|
+
<svg class="fill-primary" height="16" viewBox="0 0 448 512" width="16"
|
|
239
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
240
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
241
|
+
<path
|
|
242
|
+
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"/>
|
|
243
|
+
</svg>
|
|
244
|
+
Add Filter
|
|
245
|
+
</button>
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
<DatasourceFilterSharing ref="datasourceFilterSharing" :items="selectedPreset.sharing"
|
|
249
|
+
:readonly="selectedPreset.readonly"/>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
<div v-else-if="selectedDatasource.tabIndex === 3" class="p-5 flex-1 flex flex-col">
|
|
253
|
+
|
|
254
|
+
<ListItem v-if="selectedDatasource.sorts?.length > 0"
|
|
255
|
+
:items="selectedDatasource.sorts"
|
|
256
|
+
container-class="flex flex-col rounded-lg border-[1px] border-text-50 bg-base-300 divide-y divide-text-50"
|
|
257
|
+
@reorder="(from, to) => { selectedDatasource.sorts.splice(to, 0, selectedDatasource.sorts.splice(from, 1)[0]); }">
|
|
258
|
+
<template v-slot="{ item, index }">
|
|
259
|
+
<div class="flex flex-row items-center gap-3 p-1">
|
|
260
|
+
<div v-if="!selectedPreset.readonly" data-reorder>
|
|
261
|
+
<svg class="fill-text-300" height="14" viewBox="0 0 512 512" width="14"
|
|
262
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
263
|
+
<path
|
|
264
|
+
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"/>
|
|
265
|
+
</svg>
|
|
266
|
+
</div>
|
|
267
|
+
<div class="flex-1 flex flex-row gap-3">
|
|
268
|
+
<Dropdown v-model="item.key"
|
|
269
|
+
:readonly="selectedPreset.readonly"
|
|
270
|
+
class="flex-1"
|
|
271
|
+
@change="">
|
|
272
|
+
<option v-for="column in selectedDatasourceSortColumns"
|
|
273
|
+
:value="column.key">
|
|
274
|
+
{{ column.label2 ?? column.label }}
|
|
275
|
+
</option>
|
|
276
|
+
</Dropdown>
|
|
277
|
+
<div class="flex flex-row">
|
|
278
|
+
<Radio v-model="item.type" :disabled="selectedPreset.readonly" custom="true" value="asc"
|
|
279
|
+
@change="">
|
|
280
|
+
<button :class="item.type === 'asc' ? 'bg-primary' : ''" class="p-1" type="button">
|
|
281
|
+
<svg :class="item.type === 'asc' ? 'fill-white' : 'fill-text'" height="14" viewBox="0 0 512 512"
|
|
282
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
283
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
284
|
+
<path
|
|
285
|
+
d="M439.1 432H377.1l81.87-105.3c5.625-7.25 6.656-17.06 2.625-25.28C457.5 293.2 449.1 288 439.1 288h-111.1c-13.25 0-23.1 10.75-23.1 24s10.75 24 23.1 24h62.94L309.1 441.3c-5.623 7.25-6.654 17.06-2.625 25.28C310.5 474.8 318.8 480 327.1 480h111.1c13.25 0 23.1-10.75 23.1-24S453.2 432 439.1 432zM477.5 189.3l-71.1-144c-8.123-16.31-34.81-16.31-42.94 0l-71.1 144c-5.938 11.84-1.125 26.25 10.75 32.19c11.9 5.938 26.25 1.156 32.19-10.75L338.8 200h90.34l5.359 10.72C438.7 219.2 447.2 224 456 224c3.594 0 7.25-.8125 10.69-2.531C478.6 215.5 483.4 201.1 477.5 189.3zM362.8 152l21.17-42.34L405.2 152H362.8zM206.4 335.1L152 394.9V56.02c0-13.27-10.75-24.02-24-24.02S104 42.76 104 56.02v338.9l-54.37-58.95c-4.719-5.125-11.16-7.719-17.62-7.719c-5.812 0-11.66 2.094-16.28 6.375c-9.75 8.977-10.34 24.18-1.344 33.94l95.1 104.1c9.062 9.82 26.19 9.82 35.25 0l95.1-104.1c9-9.758 8.406-24.96-1.344-33.94C230.5 325.5 215.3 326.2 206.4 335.1z"/>
|
|
286
|
+
</svg>
|
|
287
|
+
</button>
|
|
288
|
+
</Radio>
|
|
289
|
+
<Radio v-model="item.type" :disabled="selectedPreset.readonly" custom="true" value="desc"
|
|
290
|
+
@change="">
|
|
291
|
+
<button :class="item.type === 'desc' ? 'bg-primary' : ''" class="p-1" type="button">
|
|
292
|
+
<svg :class="item.type === 'desc' ? 'fill-white' : 'fill-text'" height="14" viewBox="0 0 512 512"
|
|
293
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
294
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
295
|
+
<path
|
|
296
|
+
d="M327.1 80h62.94L309.1 185.2c-5.623 7.25-6.654 17.06-2.625 25.28c4.031 8.25 12.41 13.47 21.56 13.47h111.1c13.25 0 23.1-10.75 23.1-24s-10.75-24-23.1-24H377.1l81.87-105.2c5.625-7.25 6.656-17.06 2.625-25.28C457.5 37.22 449.1 32 439.1 32h-111.1c-13.25 0-23.1 10.75-23.1 24S314.7 80 327.1 80zM477.5 445.3l-71.1-144c-8.123-16.3-34.81-16.3-42.94 0l-71.1 144c-5.938 11.84-1.125 26.25 10.75 32.19c11.9 5.938 26.25 1.156 32.19-10.75l5.359-10.72h90.34l5.359 10.72c4.219 8.438 12.69 13.28 21.5 13.28c3.594 0 7.25-.8125 10.69-2.531C478.6 471.5 483.4 457.1 477.5 445.3zM362.8 407.1l21.17-42.34l21.17 42.34H362.8zM206.4 335.1L152 394.9V56.02c0-13.27-10.75-24.02-24-24.02S104 42.76 104 56.02v338.9l-54.37-58.95c-4.719-5.125-11.16-7.719-17.62-7.719c-5.812 0-11.66 2.094-16.28 6.375c-9.75 8.977-10.34 24.18-1.344 33.94l95.1 104.1c9.062 9.82 26.19 9.82 35.25 0l95.1-104.1c9-9.758 8.406-24.96-1.344-33.94C230.5 325.5 215.3 326.2 206.4 335.1z"/>
|
|
297
|
+
</svg>
|
|
298
|
+
</button>
|
|
299
|
+
</Radio>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
<button v-if="!selectedPreset.readonly" type="button"
|
|
303
|
+
@click="selectedDatasource.sorts.splice(index, 1); ">
|
|
304
|
+
<svg class="fill-text-300 hover:fill-red-500" height="16" viewBox="0 0 320 512"
|
|
305
|
+
width="16" xmlns="http://www.w3.org/2000/svg">
|
|
306
|
+
<path
|
|
307
|
+
d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"/>
|
|
308
|
+
</svg>
|
|
309
|
+
</button>
|
|
310
|
+
</div>
|
|
311
|
+
</template>
|
|
312
|
+
</ListItem>
|
|
313
|
+
|
|
314
|
+
<button v-if="!selectedPreset.readonly"
|
|
315
|
+
class="text-primary flex flex-row items-center justify-center p-3"
|
|
316
|
+
type="button"
|
|
317
|
+
@click="addSort({ type:'asc' })">
|
|
318
|
+
<svg class="fill-primary" height="16" viewBox="0 0 448 512" width="16"
|
|
319
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
320
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
321
|
+
<path
|
|
322
|
+
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"/>
|
|
323
|
+
</svg>
|
|
324
|
+
Add Sort
|
|
325
|
+
</button>
|
|
326
|
+
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<div v-else-if="selectedDatasource.tabIndex === 4" class="p-5 flex-1 flex flex-col gap-5">
|
|
330
|
+
|
|
331
|
+
<PresetBarPivot :columns="selectedDatasourcePivotColumns"
|
|
332
|
+
:pivot="selectedDatasourcePivot"
|
|
333
|
+
@apply="updatePivot"/>
|
|
334
|
+
|
|
335
|
+
<br/>
|
|
336
|
+
</div>
|
|
337
|
+
|
|
338
|
+
<ColumnSelector ref="columnSelector"/>
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
|
|
342
|
+
<div v-else-if="selectedPreset" class="flex-1 flex flex-col">
|
|
343
|
+
<div class="p-5 flex flex-row gap-2">
|
|
344
|
+
<button type="button" @click="delete cConfig.selectedUid">
|
|
345
|
+
<svg class="fill-text hover:fill-primary" height="16" viewBox="0 0 448 512" width="16"
|
|
346
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
347
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
348
|
+
<path
|
|
349
|
+
d="M447.1 256C447.1 273.7 433.7 288 416 288H109.3l105.4 105.4c12.5 12.5 12.5 32.75 0 45.25C208.4 444.9 200.2 448 192 448s-16.38-3.125-22.62-9.375l-160-160c-12.5-12.5-12.5-32.75 0-45.25l160-160c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25L109.3 224H416C433.7 224 447.1 238.3 447.1 256z"/>
|
|
350
|
+
</svg>
|
|
351
|
+
</button>
|
|
352
|
+
<Textbox v-model="selectedPreset.name"
|
|
353
|
+
class="border-none bg-transparent"
|
|
354
|
+
item-class="p-0 text-lg font-bold"
|
|
355
|
+
@click="log(selectedPreset)"/>
|
|
356
|
+
</div>
|
|
357
|
+
|
|
358
|
+
<div class="flex-1 overflow-y-auto">
|
|
359
|
+
<div class="p-5">
|
|
360
|
+
<div class="flex flex-row gap-2">
|
|
361
|
+
<label class="flex-1" @click="log(selectedPreset.datasource)">Datasource</label>
|
|
362
|
+
<button v-if="!selectedPreset.readonly" class="text-primary"
|
|
363
|
+
type="button"
|
|
364
|
+
@click="$refs.chooseDatasource.open()">
|
|
365
|
+
Add Datasource
|
|
366
|
+
</button>
|
|
367
|
+
</div>
|
|
368
|
+
<div class="flex flex-col mt-2">
|
|
369
|
+
<ListItem :items="selectedPreset.datasource"
|
|
370
|
+
class="bg-transparent"
|
|
371
|
+
container-class="flex flex-col gap-1">
|
|
372
|
+
<template v-slot="{ item, index }">
|
|
373
|
+
<div class="flex flex-row items-center gap-3 p-3 bg-base-500 hover:bg-text-50 rounded-lg">
|
|
374
|
+
<div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer"
|
|
375
|
+
@click="cConfig.selectedDatasource = item.uid">
|
|
376
|
+
{{ item.name }}
|
|
377
|
+
</div>
|
|
378
|
+
<button v-if="!selectedPreset.readonly" :ref="`datasourceOpt${index}`" type="button"
|
|
379
|
+
@click="$refs.datasourceMenu.open($refs[`datasourceOpt${index}`], { index, uid:item.uid })">
|
|
380
|
+
<svg class="fill-text-300 hover:fill-primary" height="14" viewBox="0 0 512 512"
|
|
381
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
382
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
383
|
+
<path
|
|
384
|
+
d="M64 192C28.61 192 0 220.6 0 256s28.61 64 64 64s64-28.62 64-64S99.39 192 64 192zM256 192C220.6 192 192 220.6 192 256s28.61 64 64 64s64-28.62 64-64S291.4 192 256 192zM448 192c-35.39 0-64 28.62-64 64s28.61 64 64 64s64-28.62 64-64S483.4 192 448 192z"/>
|
|
385
|
+
</svg>
|
|
386
|
+
</button>
|
|
387
|
+
</div>
|
|
388
|
+
</template>
|
|
389
|
+
</ListItem>
|
|
390
|
+
</div>
|
|
391
|
+
<ContextMenu ref="datasourceMenu" position="bottom-right">
|
|
392
|
+
<template #default="{ context }">
|
|
393
|
+
<div class="flex flex-col min-w-[200px]">
|
|
394
|
+
|
|
395
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
396
|
+
@click="cConfig.selectedDatasource = context.uid">
|
|
397
|
+
<div class="w-[30px]">
|
|
398
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 512 512" width="16"
|
|
399
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
400
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
401
|
+
<path
|
|
402
|
+
d="M495.6 49.23l-32.82-32.82C451.8 5.471 437.5 0 423.1 0c-14.33 0-28.66 5.469-39.6 16.41L167.5 232.5C159.1 240 154.8 249.5 152.4 259.8L128.3 367.2C126.5 376.1 133.4 384 141.1 384c.916 0 1.852-.0918 2.797-.2813c0 0 74.03-15.71 107.4-23.56c10.1-2.377 19.13-7.459 26.46-14.79l217-217C517.5 106.5 517.4 71.1 495.6 49.23zM461.7 94.4L244.7 311.4C243.6 312.5 242.5 313.1 241.2 313.4c-13.7 3.227-34.65 7.857-54.3 12.14l12.41-55.2C199.6 268.9 200.3 267.5 201.4 266.5l216.1-216.1C419.4 48.41 421.6 48 423.1 48s3.715 .4062 5.65 2.342l32.82 32.83C464.8 86.34 464.8 91.27 461.7 94.4zM424 288c-13.25 0-24 10.75-24 24v128c0 13.23-10.78 24-24 24h-304c-13.22 0-24-10.77-24-24v-304c0-13.23 10.78-24 24-24h144c13.25 0 24-10.75 24-24S229.3 64 216 64L71.1 63.99C32.31 63.99 0 96.29 0 135.1v304C0 479.7 32.31 512 71.1 512h303.1c39.69 0 71.1-32.3 71.1-72L448 312C448 298.8 437.3 288 424 288z"/>
|
|
403
|
+
</svg>
|
|
404
|
+
</div>
|
|
405
|
+
Edit
|
|
406
|
+
</button>
|
|
407
|
+
|
|
408
|
+
<button v-if="!selectedPreset.readonly" :class="appStyle.menuItem"
|
|
409
|
+
class="w-full p-3 text-left flex flex-row items-center"
|
|
410
|
+
@click="duplicateDatasource(context.index)">
|
|
411
|
+
<div class="w-[30px]">
|
|
412
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 512 512" width="16"
|
|
413
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
414
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
415
|
+
<path
|
|
416
|
+
d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/>
|
|
417
|
+
</svg>
|
|
418
|
+
</div>
|
|
419
|
+
Duplicate
|
|
420
|
+
</button>
|
|
421
|
+
|
|
422
|
+
<button v-if="!selectedPreset.readonly" :class="appStyle.menuItem"
|
|
423
|
+
class="w-full p-3 text-left flex flex-row items-center"
|
|
424
|
+
@click="removeDatasource(context.index)">
|
|
425
|
+
<div class="w-[30px]">
|
|
426
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 320 512" width="16"
|
|
427
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
428
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
429
|
+
<path
|
|
430
|
+
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"/>
|
|
431
|
+
</svg>
|
|
432
|
+
</div>
|
|
433
|
+
Remove
|
|
434
|
+
</button>
|
|
435
|
+
|
|
436
|
+
</div>
|
|
437
|
+
</template>
|
|
438
|
+
</ContextMenu>
|
|
439
|
+
</div>
|
|
440
|
+
|
|
441
|
+
<div class="p-5">
|
|
442
|
+
<div class="flex flex-row gap-2">
|
|
443
|
+
<label class="flex-1" @click="log(selectedPreset.views)">Views</label>
|
|
444
|
+
<button v-if="!selectedPreset.readonly" class="text-primary" type="button"
|
|
445
|
+
@click="(e) => $refs.chooseView.open((_) => addView(_, selectedPreset.views, { unshift:e.shiftKey }))">
|
|
446
|
+
Add View
|
|
447
|
+
</button>
|
|
448
|
+
</div>
|
|
449
|
+
<div class="flex flex-col">
|
|
450
|
+
<TreeView v-model="selectedViewUid"
|
|
451
|
+
:config="componentsConfig"
|
|
452
|
+
:items="selectedPreset.views"
|
|
453
|
+
:readonly="selectedPreset.readonly"
|
|
454
|
+
class="mt-2">
|
|
455
|
+
<template #item="{ item, parent, depth }">
|
|
456
|
+
<div
|
|
457
|
+
class="flex-1 p-3 overflow-hidden text-ellipsis cursor-pointer flex flex-row items-center gap-3">
|
|
458
|
+
<div>
|
|
459
|
+
<svg v-if="item.type === 'Grid'" class="fill-text-200" height="14" viewBox="0 0 512 512"
|
|
460
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
461
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
462
|
+
<path
|
|
463
|
+
d="M448 32H64C28.65 32 0 60.65 0 96v320c0 35.35 28.65 64 64 64h384c35.35 0 64-28.65 64-64V96C512 60.65 483.3 32 448 32zM64 96h160v128H64V96zM64 416V288h160v128H64zM448 416h-160V288h160V416zM448 224h-160V96h160V224z"/>
|
|
464
|
+
</svg>
|
|
465
|
+
<svg v-else-if="item.type === 'Doughnut'" class="fill-text-200" height="14" viewBox="0 0 512 512"
|
|
466
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
467
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
468
|
+
<path
|
|
469
|
+
d="M512 256c0-26.88-16.6-49.84-40.22-59.34c-20.88-75.75-80.68-135.6-156.4-156.4C305.8 16.6 282.9 0 256 0C229.1 0 206.2 16.6 196.7 40.22c-75.75 20.88-135.6 80.68-156.4 156.4C16.6 206.2 0 229.1 0 256s16.6 49.84 40.22 59.34c20.88 75.75 80.68 135.6 156.4 156.4C206.2 495.4 229.1 512 256 512c26.88 0 49.84-16.6 59.34-40.22c75.75-20.88 135.6-80.68 156.4-156.4C495.4 305.8 512 282.9 512 256zM448 240c8.875 0 16 7.125 16 16c0 8.875-7.125 16-16 16S432 264.9 432 256C432 247.1 439.1 240 448 240zM272 64c0 8.875-7.125 16-16 16C247.1 80 240 72.88 240 64S247.1 48 256 48C264.9 48 272 55.12 272 64zM64 272C55.12 272 48 264.9 48 256c0-8.875 7.125-16 16-16S80 247.1 80 256C80 264.9 72.88 272 64 272zM240 448c0-8.875 7.125-16 16-16c8.875 0 16 7.125 16 16s-7.125 16-16 16C247.1 464 240 456.9 240 448zM305.1 407.5C293.4 393.2 275.9 384 256 384c-19.88 0-37.39 9.235-49.14 23.49C158.4 391.6 120.4 353.6 104.5 305.1C118.8 293.4 128 275.9 128 256S118.8 218.6 104.5 206.9c15.88-48.5 53.85-86.47 102.3-102.3C218.6 118.8 236.1 128 256 128c19.88 0 37.39-9.235 49.14-23.49c48.5 15.88 86.47 53.85 102.3 102.3C393.2 218.6 384 236.1 384 256s9.235 37.39 23.49 49.14C391.6 353.6 353.6 391.6 305.1 407.5z"/>
|
|
470
|
+
</svg>
|
|
471
|
+
<svg v-else-if="item.type === 'VirtualTable'" class="fill-text-200" height="14" viewBox="0 0 512 512"
|
|
472
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
473
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
474
|
+
<path
|
|
475
|
+
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"/>
|
|
476
|
+
</svg>
|
|
477
|
+
<svg v-else-if="item.type === 'Pie'" class="fill-text-200" height="14" viewBox="0 0 576 512"
|
|
478
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
479
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
480
|
+
<path
|
|
481
|
+
d="M559.7 288l-237.2-.0006l157.1 158c6.124 6.124 15.99 6.484 22.24 .7343c38.62-36.5 65.25-85.62 73.12-140.9C577.2 296.4 569.4 288 559.7 288zM543.1 223.2c-8.249-119.5-103.7-214.1-223.2-223.2c-9.124-.6249-16.76 7.113-16.76 16.24L304 240l223.7-.0012C536.9 240 544.6 232.4 543.1 223.2zM256 288V50.75c0-9.624-8.369-17.48-17.87-16.11C119 51.52 27.89 155.6 32.14 280.4c4.375 128.1 114.8 233.2 242.9 231.6c50.37-.6249 97-16.88 135.2-44c7.999-5.624 8.487-17.24 1.612-24.11L256 288z"/>
|
|
482
|
+
</svg>
|
|
483
|
+
<svg v-else-if="item.type === 'PolarArea'" class="fill-text-200" height="14" viewBox="0 0 640 512"
|
|
484
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
485
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
486
|
+
<path
|
|
487
|
+
d="M119.1 272C107.1 252.1 87.55 240 64 240c-35.25 0-64 28.75-64 64s28.75 64 64 64c23.55 0 43.96-12.97 55.08-32h60.15C177.1 325.7 176 314.1 176 304s1.127-21.66 3.229-32H119.1zM576 192c35.25 0 64-28.75 64-64s-28.75-64-64-64s-64 28.75-64 64S540.8 192 576 192zM576 384c-11.19 0-21.66 3.094-30.78 8.213l-86.1-52.2C461.6 328.5 464 316.6 464 304c0-16.77-3.436-32.68-9.301-47.36l67.3-49.36c-17.94-12.26-31.13-30.59-37.53-51.86l-67.96 49.84C394.5 187.3 366.7 176 336 176c-7.988 0-15.74 .9492-23.32 2.352L276.3 100.3C283.5 89.98 288 77.54 288 64c0-35.25-28.75-64-64-64S160 28.75 160 64c0 33.29 25.73 60.47 58.28 63.42l36.57 78.36C226.5 229.3 208 264.3 208 304c0 70.67 57.33 128 128 128c34.97 0 66.61-14.11 89.71-36.85l86.39 51.83C512.1 447.3 512 447.7 512 448c0 35.25 28.75 64 64 64S640 483.3 640 448S611.3 384 576 384zM336 352C309.5 352 288 330.5 288 304S309.5 256 336 256S384 277.5 384 304S362.5 352 336 352z"/>
|
|
488
|
+
</svg>
|
|
489
|
+
</div>
|
|
490
|
+
<div :class="!item.props?.enabled ? 'line-through opacity-50' : ''"
|
|
491
|
+
class="flex-1 text-ellipsis overflow-hidden whitespace-nowrap">
|
|
492
|
+
<strong class="hover:text-primary" @click="cConfig.selectedView = item.uid">
|
|
493
|
+
{{ item.props?.label ?? (item.name ?? item.type) }}
|
|
494
|
+
</strong>
|
|
495
|
+
</div>
|
|
496
|
+
<button v-if="item.isContainer && !selectedPreset.readonly"
|
|
497
|
+
class="px-1"
|
|
498
|
+
type="button"
|
|
499
|
+
@click="(e) => $refs.chooseView.open((_) => addView(_, item.items, { unshift:e.shiftKey }))">
|
|
500
|
+
<svg class="fill-text-300 hover:fill-primary-600" height="14" viewBox="0 0 448 512"
|
|
501
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
502
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
503
|
+
<path
|
|
504
|
+
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"/>
|
|
505
|
+
</svg>
|
|
506
|
+
</button>
|
|
507
|
+
<button v-if="!selectedPreset.readonly" :ref="`viewOpt${item.uid}`" type="button"
|
|
508
|
+
@click="$refs.viewOpt.open($refs[`viewOpt${item.uid}`], { item, parent })">
|
|
509
|
+
<svg class="fill-text-300 hover:fill-primary" height="14" viewBox="0 0 512 512"
|
|
510
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
511
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
512
|
+
<path
|
|
513
|
+
d="M64 192C28.61 192 0 220.6 0 256s28.61 64 64 64s64-28.62 64-64S99.39 192 64 192zM256 192C220.6 192 192 220.6 192 256s28.61 64 64 64s64-28.62 64-64S291.4 192 256 192zM448 192c-35.39 0-64 28.62-64 64s28.61 64 64 64s64-28.62 64-64S483.4 192 448 192z"/>
|
|
514
|
+
</svg>
|
|
515
|
+
</button>
|
|
516
|
+
</div>
|
|
517
|
+
</template>
|
|
518
|
+
</TreeView>
|
|
519
|
+
|
|
520
|
+
<ContextMenu ref="viewOpt" position="bottom-right">
|
|
521
|
+
<template #default="{ context }">
|
|
522
|
+
<div class="flex flex-col min-w-[200px]">
|
|
523
|
+
|
|
524
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
525
|
+
@click="cConfig.selectedView = context.item.uid">
|
|
526
|
+
<div class="w-[30px]">
|
|
527
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 512 512" width="16"
|
|
528
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
529
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
530
|
+
<path
|
|
531
|
+
d="M495.6 49.23l-32.82-32.82C451.8 5.471 437.5 0 423.1 0c-14.33 0-28.66 5.469-39.6 16.41L167.5 232.5C159.1 240 154.8 249.5 152.4 259.8L128.3 367.2C126.5 376.1 133.4 384 141.1 384c.916 0 1.852-.0918 2.797-.2813c0 0 74.03-15.71 107.4-23.56c10.1-2.377 19.13-7.459 26.46-14.79l217-217C517.5 106.5 517.4 71.1 495.6 49.23zM461.7 94.4L244.7 311.4C243.6 312.5 242.5 313.1 241.2 313.4c-13.7 3.227-34.65 7.857-54.3 12.14l12.41-55.2C199.6 268.9 200.3 267.5 201.4 266.5l216.1-216.1C419.4 48.41 421.6 48 423.1 48s3.715 .4062 5.65 2.342l32.82 32.83C464.8 86.34 464.8 91.27 461.7 94.4zM424 288c-13.25 0-24 10.75-24 24v128c0 13.23-10.78 24-24 24h-304c-13.22 0-24-10.77-24-24v-304c0-13.23 10.78-24 24-24h144c13.25 0 24-10.75 24-24S229.3 64 216 64L71.1 63.99C32.31 63.99 0 96.29 0 135.1v304C0 479.7 32.31 512 71.1 512h303.1c39.69 0 71.1-32.3 71.1-72L448 312C448 298.8 437.3 288 424 288z"/>
|
|
532
|
+
</svg>
|
|
533
|
+
</div>
|
|
534
|
+
Edit
|
|
535
|
+
</button>
|
|
536
|
+
|
|
537
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
538
|
+
@click="duplicateComponent(context.item, context.parent)">
|
|
539
|
+
<div class="w-[30px]">
|
|
540
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 512 512" width="16"
|
|
541
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
542
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
543
|
+
<path
|
|
544
|
+
d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/>
|
|
545
|
+
</svg>
|
|
546
|
+
</div>
|
|
547
|
+
Duplicate
|
|
548
|
+
</button>
|
|
549
|
+
|
|
550
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
551
|
+
@click="context.parent.splice(context.parent.indexOf(context.item), 1)">
|
|
552
|
+
<div class="w-[30px]">
|
|
553
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 320 512" width="16"
|
|
554
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
555
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
556
|
+
<path
|
|
557
|
+
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"/>
|
|
558
|
+
</svg>
|
|
559
|
+
</div>
|
|
560
|
+
Remove
|
|
561
|
+
</button>
|
|
562
|
+
|
|
563
|
+
</div>
|
|
564
|
+
</template>
|
|
565
|
+
</ContextMenu>
|
|
566
|
+
</div>
|
|
567
|
+
</div>
|
|
568
|
+
|
|
569
|
+
<div v-if="sharingSrc && !selectedPreset.readonly" class="p-5">
|
|
570
|
+
<div class="flex flex-row gap-2">
|
|
571
|
+
<label class="flex-1" @click="log(selectedPreset.shared)">Sharing</label>
|
|
572
|
+
<button class="text-primary" type="button"
|
|
573
|
+
@click="$refs.sharingModal.open([], { callback:addSharing })">
|
|
574
|
+
Share
|
|
575
|
+
</button>
|
|
576
|
+
|
|
577
|
+
<SharingModal ref="sharingModal" :src="sharingSrc"/>
|
|
578
|
+
</div>
|
|
579
|
+
<div class="flex flex-col gap-1 mt-2">
|
|
580
|
+
<div v-for="(user, index) in selectedPreset.sharing"
|
|
581
|
+
class="bg-base-500 hover:bg-text-50 p-3 rounded-lg flex flex-row gap-2 items-center gap-1">
|
|
582
|
+
<div class="flex-1 flex flex-row items-center cursor-default gap-2">
|
|
583
|
+
<svg class="fill-text-200" height="14" viewBox="0 0 448 512" width="14"
|
|
584
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
585
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
586
|
+
<path
|
|
587
|
+
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"/>
|
|
588
|
+
</svg>
|
|
589
|
+
{{ user.name }}
|
|
590
|
+
</div>
|
|
591
|
+
<button type="button" @click="removeSharing(index)">
|
|
592
|
+
<svg class="fill-text-300 hover:fill-red-600" height="14" viewBox="0 0 320 512"
|
|
593
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
594
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
595
|
+
<path
|
|
596
|
+
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"/>
|
|
597
|
+
</svg>
|
|
598
|
+
</button>
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
</div>
|
|
602
|
+
</div>
|
|
603
|
+
|
|
604
|
+
</div>
|
|
605
|
+
|
|
606
|
+
<div v-else class="flex-1 flex flex-col">
|
|
607
|
+
<div class="p-5 flex flex-row items-start gap-2">
|
|
608
|
+
<div class="flex-1">
|
|
609
|
+
<h5 @click="log(cConfig)">{{ title }}</h5>
|
|
610
|
+
</div>
|
|
611
|
+
<button v-if="hasPresets" type="button" @click="addPreset">
|
|
612
|
+
<svg class="fill-primary" height="19" viewBox="0 0 448 512" width="19" xmlns="http://www.w3.org/2000/svg">
|
|
613
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
614
|
+
<path
|
|
615
|
+
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"/>
|
|
616
|
+
</svg>
|
|
617
|
+
</button>
|
|
618
|
+
</div>
|
|
619
|
+
|
|
620
|
+
<div v-if="hasPresets" class="flex-1 overflow-y-auto px-6 flex flex-col gap-5">
|
|
621
|
+
|
|
622
|
+
<div v-if="(presets ?? []).length > 0">
|
|
623
|
+
<div class="mb-2">
|
|
624
|
+
<label class="text-text-400">Views</label>
|
|
625
|
+
</div>
|
|
626
|
+
|
|
627
|
+
<ListItem :items="presets"
|
|
628
|
+
class="bg-transparent rounded-xl overflow-hidden"
|
|
629
|
+
container-class="divide-y divide-text-50">
|
|
630
|
+
<template v-slot="{ item, index }">
|
|
631
|
+
<div class="flex flex-row items-center gap-1 bg-base-500 hover:bg-text-50 pl-3">
|
|
632
|
+
<Radio :checked="item.uid === cConfig.viewedUid" class="flex-1 py-3"
|
|
633
|
+
@click="(e) => e.shiftKey ? openPreset(item.uid) : selectPreset(item.uid)">
|
|
634
|
+
{{ item.name }}
|
|
635
|
+
</Radio>
|
|
636
|
+
<button :ref="`presetItemBtn${index}`"
|
|
637
|
+
class="pr-3"
|
|
638
|
+
type="button"
|
|
639
|
+
@click="$refs.presetItemMenu.open($refs[`presetItemBtn${index}`], { item, index })">
|
|
640
|
+
<svg class="fill-text-300 hover:fill-primary" height="14" viewBox="0 0 128 512"
|
|
641
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
642
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
643
|
+
<path
|
|
644
|
+
d="M128 64c0-35.39-28.62-64-64-64S0 28.61 0 64s28.62 64 64 64S128 99.39 128 64zM128 256c0-35.39-28.62-64-64-64S0 220.6 0 256s28.62 64 64 64S128 291.4 128 256zM128 448c0-35.39-28.62-64-64-64s-64 28.61-64 64s28.62 64 64 64S128 483.4 128 448z"/>
|
|
645
|
+
</svg>
|
|
646
|
+
</button>
|
|
647
|
+
</div>
|
|
648
|
+
</template>
|
|
649
|
+
</ListItem>
|
|
650
|
+
</div>
|
|
651
|
+
|
|
652
|
+
<div v-if="(sharedPresets ?? []).length > 0">
|
|
653
|
+
<div class="mb-2">
|
|
654
|
+
<label class="text-text-400">Shared</label>
|
|
655
|
+
</div>
|
|
656
|
+
|
|
657
|
+
<ListItem :items="sharedPresets"
|
|
658
|
+
class="bg-transparent rounded-xl overflow-hidden"
|
|
659
|
+
container-class="divide-y divide-text-50">
|
|
660
|
+
<template v-slot="{ item, index }">
|
|
661
|
+
<div class="flex flex-row items-center gap-1 bg-base-500 hover:bg-text-50 pl-3">
|
|
662
|
+
<Radio :checked="item.uid === cConfig.viewedUid" class="flex-1 py-3"
|
|
663
|
+
@click="(e) => e.shiftKey ? openPreset(item.uid) : selectPreset(item.uid)">
|
|
664
|
+
{{ item.name }}
|
|
665
|
+
</Radio>
|
|
666
|
+
<button :ref="`sharedPresetItemBtn${index}`"
|
|
667
|
+
class="pr-3"
|
|
668
|
+
type="button"
|
|
669
|
+
@click="$refs.presetItemMenu.open($refs[`sharedPresetItemBtn${index}`], { item, index, sharing:true })">
|
|
670
|
+
<svg class="fill-text-300 hover:fill-primary" height="14" viewBox="0 0 128 512"
|
|
671
|
+
width="14" xmlns="http://www.w3.org/2000/svg">
|
|
672
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
673
|
+
<path
|
|
674
|
+
d="M128 64c0-35.39-28.62-64-64-64S0 28.61 0 64s28.62 64 64 64S128 99.39 128 64zM128 256c0-35.39-28.62-64-64-64S0 220.6 0 256s28.62 64 64 64S128 291.4 128 256zM128 448c0-35.39-28.62-64-64-64s-64 28.61-64 64s28.62 64 64 64S128 483.4 128 448z"/>
|
|
675
|
+
</svg>
|
|
676
|
+
</button>
|
|
677
|
+
</div>
|
|
678
|
+
</template>
|
|
679
|
+
</ListItem>
|
|
680
|
+
</div>
|
|
681
|
+
|
|
682
|
+
<ContextMenu ref="presetItemMenu" position="bottom-right">
|
|
683
|
+
<template #default="{ context }">
|
|
684
|
+
<div v-if="!context.sharing" class="flex flex-col min-w-[200px] divide-y divide-text-50">
|
|
685
|
+
|
|
686
|
+
<div class="divide-y divide-text-50">
|
|
687
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
688
|
+
@click="openPreset(context.item.uid)">
|
|
689
|
+
<div class="w-[30px]">
|
|
690
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 512 512" width="16"
|
|
691
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
692
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
693
|
+
<path
|
|
694
|
+
d="M256 0C114.6 0 0 114.6 0 255.1S114.6 512 255.1 512S512 397.4 512 256S397.4 0 256 0zM210.8 368.1c-22.25 5.24-71.61 15.71-71.61 15.71c-.6309 .127-1.22 .1499-1.83 .1499c-5.711 0-10.33-5.232-9.151-11.13l16.1-71.61c1.551-6.895 5.027-13.21 10.03-18.21l101-101l74.67 74.67l-101.6 101.6C223.5 363.1 217.5 366.5 210.8 368.1zM373.1 213.6l-20.45 20.45l-74.67-74.67l20.4-20.4C305.7 131.6 315.2 128 324.8 128c9.553 0 19.11 3.646 26.4 10.94l21.88 21.88C387.6 175.4 387.7 198.1 373.1 213.6z"/>
|
|
695
|
+
</svg>
|
|
696
|
+
</div>
|
|
697
|
+
Edit
|
|
698
|
+
</button>
|
|
699
|
+
|
|
700
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
701
|
+
@click="duplicate(context.item)">
|
|
702
|
+
<div class="w-[30px]">
|
|
703
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 512 512" width="16"
|
|
704
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
705
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
706
|
+
<path
|
|
707
|
+
d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/>
|
|
708
|
+
</svg>
|
|
709
|
+
</div>
|
|
710
|
+
Duplicate
|
|
711
|
+
</button>
|
|
712
|
+
</div>
|
|
713
|
+
|
|
714
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
715
|
+
@click="confirm('Remove this preset?', () => removePreset(context.item))">
|
|
716
|
+
<div class="w-[30px]">
|
|
717
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 320 512" width="16"
|
|
718
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
719
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
720
|
+
<path
|
|
721
|
+
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"/>
|
|
722
|
+
</svg>
|
|
723
|
+
</div>
|
|
724
|
+
Remove
|
|
725
|
+
</button>
|
|
726
|
+
</div>
|
|
727
|
+
|
|
728
|
+
<div v-else>
|
|
729
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
730
|
+
@click="openPreset(context.item.uid)">
|
|
731
|
+
<div class="w-[30px]">
|
|
732
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 512 512" width="16"
|
|
733
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
734
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
735
|
+
<path
|
|
736
|
+
d="M256 0C114.6 0 0 114.6 0 255.1S114.6 512 255.1 512S512 397.4 512 256S397.4 0 256 0zM210.8 368.1c-22.25 5.24-71.61 15.71-71.61 15.71c-.6309 .127-1.22 .1499-1.83 .1499c-5.711 0-10.33-5.232-9.151-11.13l16.1-71.61c1.551-6.895 5.027-13.21 10.03-18.21l101-101l74.67 74.67l-101.6 101.6C223.5 363.1 217.5 366.5 210.8 368.1zM373.1 213.6l-20.45 20.45l-74.67-74.67l20.4-20.4C305.7 131.6 315.2 128 324.8 128c9.553 0 19.11 3.646 26.4 10.94l21.88 21.88C387.6 175.4 387.7 198.1 373.1 213.6z"/>
|
|
737
|
+
</svg>
|
|
738
|
+
</div>
|
|
739
|
+
Open
|
|
740
|
+
</button>
|
|
741
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
742
|
+
@click="duplicate(context.item)">
|
|
743
|
+
<div class="w-[30px]">
|
|
744
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 512 512" width="16"
|
|
745
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
746
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
747
|
+
<path
|
|
748
|
+
d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/>
|
|
749
|
+
</svg>
|
|
750
|
+
</div>
|
|
751
|
+
Duplicate
|
|
752
|
+
</button>
|
|
753
|
+
<button :class="appStyle.menuItem" class="w-full p-3 text-left flex flex-row items-center"
|
|
754
|
+
@click="removeShared(context.item, context.index)">
|
|
755
|
+
<div class="w-[30px]">
|
|
756
|
+
<svg class="fill-text-300" height="16" viewBox="0 0 320 512" width="16"
|
|
757
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
758
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
759
|
+
<path
|
|
760
|
+
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"/>
|
|
761
|
+
</svg>
|
|
762
|
+
</div>
|
|
763
|
+
Remove
|
|
764
|
+
</button>
|
|
765
|
+
</div>
|
|
766
|
+
</template>
|
|
767
|
+
</ContextMenu>
|
|
768
|
+
|
|
769
|
+
</div>
|
|
770
|
+
<div v-else class="flex-1 flex items-center justify-center">
|
|
771
|
+
<button class="cursor-pointer flex flex-col gap-1 items-center"
|
|
772
|
+
type="button"
|
|
773
|
+
@click="addPreset">
|
|
774
|
+
<svg class="fill-primary" height="32" viewBox="0 0 448 512" width="32" xmlns="http://www.w3.org/2000/svg">
|
|
775
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
776
|
+
<path
|
|
777
|
+
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"/>
|
|
778
|
+
</svg>
|
|
779
|
+
Create New Preset
|
|
780
|
+
</button>
|
|
781
|
+
</div>
|
|
782
|
+
|
|
783
|
+
</div>
|
|
784
|
+
|
|
785
|
+
</TransitionGroup>
|
|
786
|
+
|
|
787
|
+
<div :class="$style.resize1"
|
|
788
|
+
@mousedown="(e) => $util.dragResize(e, resize1)"></div>
|
|
789
|
+
</div>
|
|
790
|
+
|
|
791
|
+
<div v-if="readyState === 0" class="flex-1 flex items-center justify-center">
|
|
792
|
+
<svg class="animate-spin aspect-square w-[64px] h-[64px]" fill="none" viewBox="0 0 24 24"
|
|
793
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
794
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
795
|
+
<path class="opacity-75" 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"
|
|
796
|
+
fill="currentColor"></path>
|
|
797
|
+
</svg>
|
|
798
|
+
</div>
|
|
799
|
+
|
|
800
|
+
<div v-else-if="viewedPreset" class="flex-1 px-8 py-5 overflow-y-auto flex flex-col gap-6">
|
|
801
|
+
|
|
802
|
+
<div ref="title" class="flex flex-row gap-2 md:gap-2 items-center">
|
|
803
|
+
<button :class="sidebar.open ? 'bg-primary' : ''"
|
|
804
|
+
class="p-2 rounded-xl"
|
|
805
|
+
type="button"
|
|
806
|
+
@click="sidebar.open = !sidebar.open">
|
|
807
|
+
<svg :class="sidebar.open ? 'fill-white' : 'fill-white hover:fill-primary'" height="21" viewBox="0 0 512 512"
|
|
808
|
+
width="21" xmlns="http://www.w3.org/2000/svg">
|
|
809
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
810
|
+
<path
|
|
811
|
+
d="M480 384H249.2C236.9 355.8 208.8 336 176 336S115.1 355.8 102.8 384H32c-17.67 0-32 14.33-32 32s14.33 32 32 32h70.75C115.1 476.2 143.2 496 176 496s60.89-19.77 73.25-48H480c17.67 0 32-14.33 32-32S497.7 384 480 384zM176 448c-17.64 0-32-14.36-32-32s14.36-32 32-32s32 14.36 32 32S193.6 448 176 448zM480 224h-70.75C396.9 195.8 368.8 176 336 176S275.1 195.8 262.8 224H32C14.33 224 0 238.3 0 256s14.33 32 32 32h230.8C275.1 316.2 303.2 336 336 336s60.89-19.77 73.25-48H480c17.67 0 32-14.33 32-32S497.7 224 480 224zM336 288c-17.64 0-32-14.36-32-32s14.36-32 32-32s32 14.36 32 32S353.6 288 336 288zM32 128h102.8C147.1 156.2 175.2 176 208 176s60.89-19.77 73.25-48H480c17.67 0 32-14.33 32-32s-14.33-32-32-32h-198.8C268.9 35.77 240.8 16 208 16S147.1 35.77 134.8 64H32C14.33 64 0 78.33 0 96S14.33 128 32 128zM208 64c17.64 0 32 14.36 32 32s-14.36 32-32 32s-32-14.36-32-32S190.4 64 208 64z"/>
|
|
812
|
+
</svg>
|
|
813
|
+
</button>
|
|
814
|
+
|
|
815
|
+
<div class="flex flex-col whitespace-nowrap text-ellipsis overflow-hidden">
|
|
816
|
+
<div class="cursor-pointer group px-2 md:px-0"
|
|
817
|
+
@click="!sidebar.open ? $refs.contextMenu.open($refs.title) : null">
|
|
818
|
+
<small class="text-text-400 text-xs">{{ title ?? 'Untitled' }}</small>
|
|
819
|
+
<div class="flex flex-row items-baseline gap-1">
|
|
820
|
+
<h5 :class="!sidebar.open ? 'group-hover:text-primary' : ''"
|
|
821
|
+
class="whitespace-nowrap relative top-[-2px] text-ellipsis overflow-hidden">
|
|
822
|
+
{{ viewedPreset.name ?? 'Preset Name' }}
|
|
823
|
+
</h5>
|
|
824
|
+
<svg v-if="!sidebar.open" class="fill-text group-hover:fill-primary relative top-[-1px]" height="13"
|
|
825
|
+
viewBox="0 0 320 512" width="13"
|
|
826
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
827
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
828
|
+
<path
|
|
829
|
+
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"/>
|
|
830
|
+
</svg>
|
|
831
|
+
</div>
|
|
832
|
+
</div>
|
|
833
|
+
<ContextMenu ref="contextMenu" class="panel-400">
|
|
834
|
+
<div class="flex flex-col min-w-[300px] divide-y divide-text-50">
|
|
835
|
+
|
|
836
|
+
<div class="p-3 flex flex-col gap-1 bg-base-300">
|
|
837
|
+
<button v-for="(preset, idx) in presets"
|
|
838
|
+
:class="config.presetIdx === idx ? 'bg-primary-200 text-white' : 'hover:bg-primary-100'"
|
|
839
|
+
class="p-2 px-5 text-left flex flex-row items-center rounded-md"
|
|
840
|
+
type="button"
|
|
841
|
+
@click="selectPreset(preset.uid)">
|
|
842
|
+
<label class="flex-1 pr-12">
|
|
843
|
+
{{ preset.name }}
|
|
844
|
+
</label>
|
|
845
|
+
<div class="p-1">
|
|
846
|
+
<div v-if="idx < 10"
|
|
847
|
+
class="border-[1px] border-text-300 px-2 text-mono text-xs text-text-400 rounded-lg">
|
|
848
|
+
Alt {{ idx + 1 }}
|
|
849
|
+
</div>
|
|
850
|
+
</div>
|
|
851
|
+
</button>
|
|
852
|
+
</div>
|
|
853
|
+
|
|
854
|
+
<div class="px-3">
|
|
855
|
+
<button class="text-primary p-5 text-left w-full" type="button" @click="openPreset">Edit</button>
|
|
856
|
+
</div>
|
|
857
|
+
|
|
858
|
+
</div>
|
|
859
|
+
</ContextMenu>
|
|
860
|
+
</div>
|
|
861
|
+
|
|
862
|
+
<div v-if="Object.keys(queryFilters).length > 0" class="flex-1 flex justify-end">
|
|
863
|
+
<div
|
|
864
|
+
class="flex flex-row gap-3 items-start bg-primary-50 p-2 border-[1px] border-primary rounded-xl pl-3 min-w-[240px]">
|
|
865
|
+
<div v-for="(arr, uid) in queryFilters" class="cursor-default flex-1">
|
|
866
|
+
<div class="text-sm text-text-400">{{ viewedPreset.datasource.find(_ => _.uid === uid)?.name }}</div>
|
|
867
|
+
<div>
|
|
868
|
+
<div v-for="filter in arr" class="flex flex-row gap-2">
|
|
869
|
+
<div>{{ filter.key }}</div>
|
|
870
|
+
<div>{{ filter.operator }}</div>
|
|
871
|
+
<div>{{ filter.value }}</div>
|
|
872
|
+
</div>
|
|
873
|
+
</div>
|
|
874
|
+
</div>
|
|
875
|
+
<button type="button" @click="removeQueryFilter">
|
|
876
|
+
<svg class="fill-text-300 hover:fill-red-600" height="16" viewBox="0 0 320 512" width="16"
|
|
877
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
878
|
+
<!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
|
879
|
+
<path
|
|
880
|
+
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"/>
|
|
881
|
+
</svg>
|
|
882
|
+
</button>
|
|
883
|
+
</div>
|
|
884
|
+
</div>
|
|
885
|
+
</div>
|
|
886
|
+
|
|
887
|
+
<div class="flex flex-col gap-6">
|
|
888
|
+
|
|
889
|
+
<component :is="component?.type"
|
|
890
|
+
v-for="component in viewedComponents"
|
|
891
|
+
:="component"/>
|
|
892
|
+
|
|
893
|
+
</div>
|
|
894
|
+
|
|
895
|
+
</div>
|
|
896
|
+
|
|
897
|
+
<DatasourceSelector ref="chooseDatasource"
|
|
898
|
+
:list-src="datasourceListSrc"
|
|
899
|
+
:src="datasourceSrc"
|
|
900
|
+
@add="addDatasource"/>
|
|
901
|
+
|
|
902
|
+
<ViewSelector ref="chooseView"/>
|
|
903
|
+
|
|
904
|
+
<DatasourcePreview ref="datasourcePreview" :src="previewSrc"/>
|
|
905
|
+
|
|
906
|
+
</div>
|
|
907
|
+
</template>
|
|
908
|
+
|
|
909
|
+
<script>
|
|
910
|
+
|
|
911
|
+
import {defineAsyncComponent} from "vue";
|
|
912
|
+
import {generatePivotColumns, getPresetUid} from "../utils/preset-selector.mjs";
|
|
913
|
+
import {invokeAfterIdle} from "../utils/helpers.mjs";
|
|
914
|
+
import {useEmitter} from "../utils/event-bus";
|
|
915
|
+
|
|
916
|
+
const findComponents = (items, uid) => {
|
|
917
|
+
if (!Array.isArray(items)) return
|
|
918
|
+
|
|
919
|
+
for (let item of items) {
|
|
920
|
+
if (item.uid === uid)
|
|
921
|
+
return item
|
|
922
|
+
|
|
923
|
+
if (item.items) {
|
|
924
|
+
const component = findComponents(item.items, uid)
|
|
925
|
+
if (component)
|
|
926
|
+
return component
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
export default {
|
|
932
|
+
|
|
933
|
+
components: {
|
|
934
|
+
VirtualColumnEdit: defineAsyncComponent(() => import('./Dashboard/VirtualColumnEdit.vue')),
|
|
935
|
+
DatasourceFilterSharing: defineAsyncComponent(() => import('./Dashboard/DatasourceFilterSharing.vue')),
|
|
936
|
+
PresetBarPivot: defineAsyncComponent(() => import('../widgets/PresetBarPivot.vue')),
|
|
937
|
+
DatasourcePreview: defineAsyncComponent(() => import('./Dashboard/DatasourcePreview.vue')),
|
|
938
|
+
PresetSelectorFilterItem: defineAsyncComponent(() => import('../components/PresetSelectorFilterItem.vue')),
|
|
939
|
+
SharingModal: defineAsyncComponent(() => import('./Dashboard/SharingModal.vue')),
|
|
940
|
+
DoughnutSetting: defineAsyncComponent(() => import('./Dashboard/DoughnutSetting.vue')),
|
|
941
|
+
GridSetting: defineAsyncComponent(() => import('./WebPageBuilder4/GridSetting.vue')),
|
|
942
|
+
MarginSetting: defineAsyncComponent(() => import('./WebPageBuilder4/MarginSetting.vue')),
|
|
943
|
+
PaddingSetting: defineAsyncComponent(() => import('./WebPageBuilder4/PaddingSetting.vue')),
|
|
944
|
+
MultiValueSetting: defineAsyncComponent(() => import('./WebPageBuilder4/MultiValueSetting.vue')),
|
|
945
|
+
BarChartSetting: defineAsyncComponent(() => import('./Dashboard/BarChartSetting.vue')),
|
|
946
|
+
MetricSetting: defineAsyncComponent(() => import('./Dashboard/MetricSetting.vue')),
|
|
947
|
+
GHeatMapsSetting: defineAsyncComponent(() => import('./Dashboard/GHeatMapsSetting.vue')),
|
|
948
|
+
VirtualTableSetting: defineAsyncComponent(() => import('./Dashboard/VirtualTableSetting.vue')),
|
|
949
|
+
PieSetting: defineAsyncComponent(() => import('./Dashboard/PieSetting.vue')),
|
|
950
|
+
PolarAreaSetting: defineAsyncComponent(() => import('./Dashboard/PolarAreaSetting.vue')),
|
|
951
|
+
TreeView: defineAsyncComponent(() => import('./WebPageBuilder4/TreeView.vue')),
|
|
952
|
+
ViewSelector: defineAsyncComponent(() => import('./Dashboard/ViewSelector.vue')),
|
|
953
|
+
DatasourceSelector: defineAsyncComponent(() => import('./Dashboard/DatasourceSelector.vue'))
|
|
954
|
+
},
|
|
955
|
+
|
|
956
|
+
computed: {
|
|
957
|
+
|
|
958
|
+
cConfig() {
|
|
959
|
+
const config = this.config
|
|
960
|
+
|
|
961
|
+
if (config) {
|
|
962
|
+
if (!config.viewType)
|
|
963
|
+
config.viewType = 'md:'
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
return config
|
|
967
|
+
},
|
|
968
|
+
|
|
969
|
+
componentsConfig() {
|
|
970
|
+
if (!this.cConfig.components)
|
|
971
|
+
this.cConfig.components = {}
|
|
972
|
+
return this.cConfig.components
|
|
973
|
+
},
|
|
974
|
+
|
|
975
|
+
hasPresets() {
|
|
976
|
+
return (this.presets ?? []).length > 0 ||
|
|
977
|
+
(this.sharedPresets ?? []).length > 0
|
|
978
|
+
},
|
|
979
|
+
|
|
980
|
+
selectedDatasource() {
|
|
981
|
+
const datasource = this.selectedPreset?.datasource[this.selectedPreset.datasource.findIndex(_ => _.uid === this.cConfig.selectedDatasource)]
|
|
982
|
+
|
|
983
|
+
if (datasource) {
|
|
984
|
+
if (!datasource.tabIndex) datasource.tabIndex = 2
|
|
985
|
+
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
return datasource
|
|
989
|
+
},
|
|
990
|
+
|
|
991
|
+
selectedDatasourceFilterColumns() {
|
|
992
|
+
if (!this.selectedDatasource) return []
|
|
993
|
+
|
|
994
|
+
return this.selectedDatasource.columns.filter(_ => {
|
|
995
|
+
return _.filterable !== false
|
|
996
|
+
})
|
|
997
|
+
},
|
|
998
|
+
|
|
999
|
+
selectedDatasourceSortColumns() {
|
|
1000
|
+
if (!this.selectedDatasource) return []
|
|
1001
|
+
|
|
1002
|
+
return this.selectedDatasource.columns.filter(_ => _.key && !_.key.startsWith('_'))
|
|
1003
|
+
},
|
|
1004
|
+
|
|
1005
|
+
selectedDatasourcePivotColumns() {
|
|
1006
|
+
if (!this.selectedDatasource) return []
|
|
1007
|
+
return this.selectedDatasource.columns.filter(_ => {
|
|
1008
|
+
return _.pivot !== false
|
|
1009
|
+
})
|
|
1010
|
+
},
|
|
1011
|
+
|
|
1012
|
+
selectedDatasourcePivot() {
|
|
1013
|
+
if (!this.selectedDatasource) return
|
|
1014
|
+
|
|
1015
|
+
if (!this.selectedDatasource.pivot)
|
|
1016
|
+
this.selectedDatasource.pivot = {rows: [], columns: [], values: []}
|
|
1017
|
+
|
|
1018
|
+
return this.selectedDatasource.pivot
|
|
1019
|
+
},
|
|
1020
|
+
|
|
1021
|
+
selectedDatasourceColumns(){
|
|
1022
|
+
return this.selectedDatasource?.columns.filter(column => {
|
|
1023
|
+
if(this.datasourceColumnSearch)
|
|
1024
|
+
return column.key.toLowerCase().includes(this.datasourceColumnSearch.toLowerCase())
|
|
1025
|
+
return true
|
|
1026
|
+
})
|
|
1027
|
+
},
|
|
1028
|
+
|
|
1029
|
+
selectedDatasourceComputedColumns(){
|
|
1030
|
+
return this.selectedDatasource?.computedColumns?.filter(column => {
|
|
1031
|
+
if(this.datasourceColumnSearch)
|
|
1032
|
+
return column.key.toLowerCase().includes(this.datasourceColumnSearch.toLowerCase())
|
|
1033
|
+
return true
|
|
1034
|
+
})
|
|
1035
|
+
},
|
|
1036
|
+
|
|
1037
|
+
selectedPreset() {
|
|
1038
|
+
if(!Array.isArray(this.presets)) return
|
|
1039
|
+
|
|
1040
|
+
const preset = this.presets[this.presets.findIndex(_ => _.uid === this.cConfig.selectedUid)] ??
|
|
1041
|
+
this.sharedPresets[this.sharedPresets.findIndex(_ => _.uid === this.cConfig.selectedUid)]
|
|
1042
|
+
|
|
1043
|
+
if (preset) {
|
|
1044
|
+
if (!Array.isArray(preset.datasource))
|
|
1045
|
+
preset.datasource = []
|
|
1046
|
+
|
|
1047
|
+
if (!Array.isArray(preset.views))
|
|
1048
|
+
preset.views = []
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
return preset
|
|
1052
|
+
},
|
|
1053
|
+
|
|
1054
|
+
selectedView() {
|
|
1055
|
+
return findComponents(this.selectedPreset?.views, this.cConfig.selectedView)
|
|
1056
|
+
},
|
|
1057
|
+
|
|
1058
|
+
sidebar() {
|
|
1059
|
+
if (!this.cConfig.sidebar || !('open' in this.cConfig.sidebar))
|
|
1060
|
+
this.cConfig.sidebar = {
|
|
1061
|
+
open: true,
|
|
1062
|
+
width: 360
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
return this.cConfig.sidebar
|
|
1066
|
+
},
|
|
1067
|
+
|
|
1068
|
+
sidebarStyle() {
|
|
1069
|
+
return {
|
|
1070
|
+
width: !this.sidebar.open ? 0 : this.sidebar.width + 'px'
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
|
|
1074
|
+
viewedPreset() {
|
|
1075
|
+
if(!Array.isArray(this.presets)) return
|
|
1076
|
+
|
|
1077
|
+
return this.presets[this.presets.findIndex(_ => _.uid === this.cConfig.viewedUid)]
|
|
1078
|
+
??
|
|
1079
|
+
this.sharedPresets[this.sharedPresets.findIndex(_ => _.uid === this.cConfig.viewedUid)]
|
|
1080
|
+
},
|
|
1081
|
+
|
|
1082
|
+
viewedComponents() {
|
|
1083
|
+
if (!this.viewedPreset || !this.viewedPreset.views) return []
|
|
1084
|
+
|
|
1085
|
+
return this.viewedPreset.views
|
|
1086
|
+
.map(_ => this.createComponentInstance(_))
|
|
1087
|
+
.filter(_ => _)
|
|
1088
|
+
},
|
|
1089
|
+
|
|
1090
|
+
viewTypeIndex() {
|
|
1091
|
+
return this.viewTypes.findIndex(v => v.value === this.cConfig.viewType)
|
|
1092
|
+
},
|
|
1093
|
+
|
|
1094
|
+
queryFilters() {
|
|
1095
|
+
|
|
1096
|
+
const filters = {}
|
|
1097
|
+
for (let key in this.$route.query) {
|
|
1098
|
+
if (key.indexOf(`.filters.`) > 0) {
|
|
1099
|
+
const [uid, _, filterKey, filterOperator] = key.split('.')
|
|
1100
|
+
const value = this.$route.query[key]
|
|
1101
|
+
|
|
1102
|
+
if (!filters[uid])
|
|
1103
|
+
filters[uid] = []
|
|
1104
|
+
|
|
1105
|
+
filters[uid].push({
|
|
1106
|
+
key: filterKey,
|
|
1107
|
+
operator: filterOperator,
|
|
1108
|
+
value
|
|
1109
|
+
})
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
return filters
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
},
|
|
1117
|
+
|
|
1118
|
+
data() {
|
|
1119
|
+
return {
|
|
1120
|
+
compClasses: [
|
|
1121
|
+
'aspectRatio', 'position', 'left', 'top', 'right', 'bottom',
|
|
1122
|
+
|
|
1123
|
+
'bdSize', 'bdColor', 'bdRadius', 'bdStyle',
|
|
1124
|
+
'divideSize', 'divideColor', 'divideStyle',
|
|
1125
|
+
'outlineWidth', 'outlineColor', 'outlineStyle',
|
|
1126
|
+
'bgColors', 'bgSize', 'bgPosition', 'bgRepeat',
|
|
1127
|
+
'textAlign', 'verticalAlign',
|
|
1128
|
+
'gap',
|
|
1129
|
+
'padding', 'margin',
|
|
1130
|
+
'direction', 'columns', 'rows', 'display', 'wrap',
|
|
1131
|
+
'width', 'minWidth', 'maxWidth',
|
|
1132
|
+
'height', 'minHeight', 'maxHeight',
|
|
1133
|
+
'fontFamily', 'fontSize', 'fontWeight', 'textColor', 'lineHeight', 'overflow',
|
|
1134
|
+
'textTransform', 'whitespace', 'textOverflow', 'textDecoration',
|
|
1135
|
+
'boxShadow', 'opacity',
|
|
1136
|
+
'colSpan', 'rowSpan',
|
|
1137
|
+
'flex', 'flexAlign', 'flexJustify', 'flexBasis', 'flexColumns', 'flexWrap',
|
|
1138
|
+
'flexDirection',
|
|
1139
|
+
'zIndex',
|
|
1140
|
+
|
|
1141
|
+
'autoFlow', 'alignItems', 'justifyContent',
|
|
1142
|
+
'letterSpacing', 'lineClamp',
|
|
1143
|
+
|
|
1144
|
+
'animate',
|
|
1145
|
+
|
|
1146
|
+
'blur', 'grayscale',
|
|
1147
|
+
],
|
|
1148
|
+
containerClasses: [
|
|
1149
|
+
'containerVariant', 'containerGridColumn', 'containerGap'
|
|
1150
|
+
],
|
|
1151
|
+
itemClasses: [
|
|
1152
|
+
'itemMinWidth', 'itemRatio', 'itemVariant'
|
|
1153
|
+
],
|
|
1154
|
+
|
|
1155
|
+
data: {},
|
|
1156
|
+
|
|
1157
|
+
initialConfig: null,
|
|
1158
|
+
|
|
1159
|
+
datasourceTabs: [
|
|
1160
|
+
{ text:"Columns", value:1 },
|
|
1161
|
+
{text: "Filters", value: 2},
|
|
1162
|
+
{text: "Sorts", value: 3},
|
|
1163
|
+
{text: "Pivots", value: 4},
|
|
1164
|
+
],
|
|
1165
|
+
datasourceColumnSearch: '',
|
|
1166
|
+
|
|
1167
|
+
enumCache: {},
|
|
1168
|
+
|
|
1169
|
+
previewData: null,
|
|
1170
|
+
|
|
1171
|
+
readyState: 1,
|
|
1172
|
+
|
|
1173
|
+
selectedViewUid: null,
|
|
1174
|
+
|
|
1175
|
+
viewTypes: [
|
|
1176
|
+
{text: 'Mobile', value: ''},
|
|
1177
|
+
{text: 'Tablet', value: 'md:'},
|
|
1178
|
+
{text: 'Desktop', value: 'xl:'},
|
|
1179
|
+
{text: 'TV', value: '2xl:'},
|
|
1180
|
+
],
|
|
1181
|
+
|
|
1182
|
+
values: {},
|
|
1183
|
+
|
|
1184
|
+
config: {},
|
|
1185
|
+
presets: [],
|
|
1186
|
+
sharedPresets: []
|
|
1187
|
+
}
|
|
1188
|
+
},
|
|
1189
|
+
|
|
1190
|
+
emits: ['change', 'save'],
|
|
1191
|
+
|
|
1192
|
+
inject: ['alert', 'appStyle', 'confirm', 'socket'],
|
|
1193
|
+
|
|
1194
|
+
methods: {
|
|
1195
|
+
|
|
1196
|
+
addComputedColumns(column){
|
|
1197
|
+
if(!Array.isArray(this.selectedDatasource.computedColumns))
|
|
1198
|
+
this.selectedDatasource.computedColumns = []
|
|
1199
|
+
|
|
1200
|
+
this.$util.push(this.selectedDatasource.computedColumns, column, { key: "key" })
|
|
1201
|
+
|
|
1202
|
+
this.load()
|
|
1203
|
+
},
|
|
1204
|
+
|
|
1205
|
+
addDatasource(datasource) {
|
|
1206
|
+
const newDatasource = JSON.parse(JSON.stringify(datasource))
|
|
1207
|
+
delete newDatasource.id
|
|
1208
|
+
newDatasource.datasourceUid = newDatasource.uid
|
|
1209
|
+
newDatasource.uid = getPresetUid()
|
|
1210
|
+
this.selectedPreset.datasource.push(newDatasource)
|
|
1211
|
+
this.load()
|
|
1212
|
+
},
|
|
1213
|
+
|
|
1214
|
+
addFilter(filter) {
|
|
1215
|
+
if (!Array.isArray(this.selectedDatasource.filters))
|
|
1216
|
+
this.selectedDatasource.filters = []
|
|
1217
|
+
this.selectedDatasource.filters.push({key: filter.key, value: [{}]})
|
|
1218
|
+
this.onDatasourceFilterChanged()
|
|
1219
|
+
},
|
|
1220
|
+
|
|
1221
|
+
addPreset() {
|
|
1222
|
+
if (!Array.isArray(this.presets))
|
|
1223
|
+
this.presets = []
|
|
1224
|
+
|
|
1225
|
+
const uid = getPresetUid()
|
|
1226
|
+
|
|
1227
|
+
const newPreset = {
|
|
1228
|
+
name: 'New Preset',
|
|
1229
|
+
uid,
|
|
1230
|
+
}
|
|
1231
|
+
this.presets.push(newPreset)
|
|
1232
|
+
this.cConfig.viewedUid = uid
|
|
1233
|
+
|
|
1234
|
+
this.openPreset(newPreset.uid, {select: true})
|
|
1235
|
+
},
|
|
1236
|
+
|
|
1237
|
+
addSharing(item) {
|
|
1238
|
+
if (!Array.isArray(this.selectedPreset.sharing))
|
|
1239
|
+
this.selectedPreset.sharing = []
|
|
1240
|
+
|
|
1241
|
+
this.$util.push(this.selectedPreset.sharing, item, {key: "id"})
|
|
1242
|
+
},
|
|
1243
|
+
|
|
1244
|
+
addSort(obj) {
|
|
1245
|
+
if (!Array.isArray(this.selectedDatasource.sorts))
|
|
1246
|
+
this.selectedDatasource.sorts = []
|
|
1247
|
+
this.selectedDatasource.sorts.push(obj)
|
|
1248
|
+
},
|
|
1249
|
+
|
|
1250
|
+
addView(item, items, opt = {unshift: false}) {
|
|
1251
|
+
items[opt?.unshift ? 'unshift' : 'push'](item)
|
|
1252
|
+
if (item.openOnAdd !== false)
|
|
1253
|
+
this.$nextTick(() => this.cConfig.selectedView = item.uid)
|
|
1254
|
+
},
|
|
1255
|
+
|
|
1256
|
+
createComponentInstance(component) {
|
|
1257
|
+
|
|
1258
|
+
if (!component.uid) return
|
|
1259
|
+
if (!component.props.enabled) return
|
|
1260
|
+
|
|
1261
|
+
const compUid = '_' + component.uid.substring(0, 4) + ' '
|
|
1262
|
+
|
|
1263
|
+
const instance = {
|
|
1264
|
+
type: component.type,
|
|
1265
|
+
uid: component.uid,
|
|
1266
|
+
|
|
1267
|
+
class: compUid + this.compClasses.map(key => {
|
|
1268
|
+
return Array.isArray(component.props[key]) ? component.props[key].join(' ') : ''
|
|
1269
|
+
})
|
|
1270
|
+
.filter(_ => _)
|
|
1271
|
+
.join(' '),
|
|
1272
|
+
|
|
1273
|
+
containerClass: this.containerClasses.map(key => {
|
|
1274
|
+
return Array.isArray(component.props[key]) ? component.props[key].join(' ') : ''
|
|
1275
|
+
})
|
|
1276
|
+
.filter(_ => _)
|
|
1277
|
+
.join(' '),
|
|
1278
|
+
|
|
1279
|
+
itemClass: this.itemClasses.map(key => {
|
|
1280
|
+
return Array.isArray(component.props[key]) ? component.props[key].join(' ') : ''
|
|
1281
|
+
})
|
|
1282
|
+
.filter(_ => _)
|
|
1283
|
+
.join(' ')
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
for (let key in component.props) {
|
|
1287
|
+
if (!this.compClasses.includes(key) &&
|
|
1288
|
+
!this.containerClasses.includes(key) &&
|
|
1289
|
+
!this.itemClasses.includes(key) &&
|
|
1290
|
+
!['enabled'].includes(key)) {
|
|
1291
|
+
instance[key] = component.props[key]
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
const whitelistProps = [
|
|
1296
|
+
'column', 'datasourceUid', 'rows'
|
|
1297
|
+
]
|
|
1298
|
+
whitelistProps.forEach((key) => {
|
|
1299
|
+
if (component.props[key]) {
|
|
1300
|
+
instance[key] = component.props[key]
|
|
1301
|
+
}
|
|
1302
|
+
})
|
|
1303
|
+
|
|
1304
|
+
if (Array.isArray(component.items)) {
|
|
1305
|
+
instance.items = component.items.map((_) => this.createComponentInstance(_)).filter(_ => _)
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
if (this.values[instance.uid])
|
|
1309
|
+
instance.value = this.values[instance.uid]
|
|
1310
|
+
|
|
1311
|
+
return instance
|
|
1312
|
+
},
|
|
1313
|
+
|
|
1314
|
+
duplicate(preset) {
|
|
1315
|
+
|
|
1316
|
+
const newPreset = JSON.parse(JSON.stringify(preset))
|
|
1317
|
+
newPreset.uid = getPresetUid()
|
|
1318
|
+
newPreset.name += '(Copy)'
|
|
1319
|
+
delete newPreset.readonly
|
|
1320
|
+
delete newPreset.sharing
|
|
1321
|
+
this.presets.push(newPreset)
|
|
1322
|
+
|
|
1323
|
+
this.$nextTick(() => {
|
|
1324
|
+
this.cConfig.viewedUid = newPreset.uid
|
|
1325
|
+
this.openPreset(newPreset.uid)
|
|
1326
|
+
this.selectPreset(newPreset.uid)
|
|
1327
|
+
this.saveConfig()
|
|
1328
|
+
})
|
|
1329
|
+
},
|
|
1330
|
+
|
|
1331
|
+
duplicateComponent(item, parent) {
|
|
1332
|
+
|
|
1333
|
+
const index = parent.findIndex(_ => _ === item)
|
|
1334
|
+
|
|
1335
|
+
const newItem = JSON.parse(JSON.stringify(item))
|
|
1336
|
+
newItem.uid = getPresetUid()
|
|
1337
|
+
newItem.name += ' (Copy)';
|
|
1338
|
+
|
|
1339
|
+
parent.splice(index + 1, null, newItem)
|
|
1340
|
+
|
|
1341
|
+
this.load({[newItem.uid]: {}})
|
|
1342
|
+
},
|
|
1343
|
+
|
|
1344
|
+
duplicateDatasource(index) {
|
|
1345
|
+
|
|
1346
|
+
const newDatasource = JSON.parse(JSON.stringify(this.selectedPreset.datasource[index]))
|
|
1347
|
+
|
|
1348
|
+
newDatasource.uid = getPresetUid()
|
|
1349
|
+
newDatasource.name += ' (Copy)';
|
|
1350
|
+
|
|
1351
|
+
this.selectedPreset.datasource.splice(index + 1, 0, newDatasource)
|
|
1352
|
+
},
|
|
1353
|
+
|
|
1354
|
+
emitRoot(name, component) {
|
|
1355
|
+
|
|
1356
|
+
switch (name) {
|
|
1357
|
+
|
|
1358
|
+
case 'scroll-end':
|
|
1359
|
+
this.loadNext(component)
|
|
1360
|
+
break
|
|
1361
|
+
|
|
1362
|
+
}
|
|
1363
|
+
},
|
|
1364
|
+
|
|
1365
|
+
async load(uids) {
|
|
1366
|
+
if (this.readyState !== 1) return
|
|
1367
|
+
if (!this.viewedComponents) return
|
|
1368
|
+
if (!this.cConfig) return
|
|
1369
|
+
|
|
1370
|
+
const views = this.recurseViews(this.viewedComponents, uids)
|
|
1371
|
+
if (views?.length < 1) return
|
|
1372
|
+
|
|
1373
|
+
const {name, datasource} = this.viewedPreset
|
|
1374
|
+
|
|
1375
|
+
!uids ? this.readyState = 0 : Object.keys(uids).forEach(uid => this.emitter.emit(`${uid}.readyState`, 2))
|
|
1376
|
+
this.socket.send(this.src, {
|
|
1377
|
+
name,
|
|
1378
|
+
views,
|
|
1379
|
+
datasource: datasource.map(_datasource => {
|
|
1380
|
+
return {
|
|
1381
|
+
..._datasource,
|
|
1382
|
+
filters: [
|
|
1383
|
+
...(_datasource.filters ?? []),
|
|
1384
|
+
...(this.queryFilters[_datasource.uid] ?? [])
|
|
1385
|
+
]
|
|
1386
|
+
}
|
|
1387
|
+
})
|
|
1388
|
+
})
|
|
1389
|
+
.then(_ => {
|
|
1390
|
+
Object.assign(this.values, _)
|
|
1391
|
+
})
|
|
1392
|
+
.catch(err => this.alert(err))
|
|
1393
|
+
.finally(_ => {
|
|
1394
|
+
!uids ? this.readyState = 1 : Object.keys(uids).forEach(uid => this.emitter.emit(`${uid}.readyState`, 1))
|
|
1395
|
+
})
|
|
1396
|
+
},
|
|
1397
|
+
|
|
1398
|
+
async loadNext(component) {
|
|
1399
|
+
if (!this.values[component.uid]) return
|
|
1400
|
+
|
|
1401
|
+
const {items} = this.values[component.uid]
|
|
1402
|
+
const afterItem = items[items.length - 1]
|
|
1403
|
+
|
|
1404
|
+
const views = this.recurseViews(this.viewedComponents, {[component.uid]: {afterItem}})
|
|
1405
|
+
|
|
1406
|
+
const {name, datasource} = this.viewedPreset
|
|
1407
|
+
|
|
1408
|
+
this.socket.send(this.src, {
|
|
1409
|
+
name,
|
|
1410
|
+
views,
|
|
1411
|
+
datasource: datasource.map(_datasource => {
|
|
1412
|
+
return {
|
|
1413
|
+
..._datasource,
|
|
1414
|
+
filters: [
|
|
1415
|
+
...(_datasource.filters ?? []),
|
|
1416
|
+
...(this.queryFilters[_datasource.uid] ?? [])
|
|
1417
|
+
]
|
|
1418
|
+
}
|
|
1419
|
+
})
|
|
1420
|
+
})
|
|
1421
|
+
.then(_ => {
|
|
1422
|
+
if(_[component.uid]){
|
|
1423
|
+
const {items, hasNext} = _[component.uid]
|
|
1424
|
+
this.values[component.uid].items.push(...items)
|
|
1425
|
+
this.values[component.uid].hasNext = hasNext
|
|
1426
|
+
}
|
|
1427
|
+
})
|
|
1428
|
+
},
|
|
1429
|
+
|
|
1430
|
+
onDatasourceFilterChanged() {
|
|
1431
|
+
|
|
1432
|
+
let datasourceFilterOK = true
|
|
1433
|
+
for (let filter of this.selectedDatasource.filters) {
|
|
1434
|
+
if (Array.isArray(filter.value)) {
|
|
1435
|
+
for (let value of filter.value) {
|
|
1436
|
+
for (let key in value) {
|
|
1437
|
+
if (!value[key]) {
|
|
1438
|
+
datasourceFilterOK = false
|
|
1439
|
+
break
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
if (!datasourceFilterOK) break
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
if (datasourceFilterOK) {
|
|
1449
|
+
this.load()
|
|
1450
|
+
}
|
|
1451
|
+
},
|
|
1452
|
+
|
|
1453
|
+
openPreset(uid, opt = {}) {
|
|
1454
|
+
this.cConfig.selectedUid = uid
|
|
1455
|
+
this.saveConfig()
|
|
1456
|
+
},
|
|
1457
|
+
|
|
1458
|
+
previewDatasource(datasource) {
|
|
1459
|
+
this.$refs.datasourcePreview?.open(datasource)
|
|
1460
|
+
},
|
|
1461
|
+
|
|
1462
|
+
recurseViews(items, uids) {
|
|
1463
|
+
|
|
1464
|
+
let results = []
|
|
1465
|
+
|
|
1466
|
+
for (let item of items) {
|
|
1467
|
+
if (item.datasourceUid && (!uids || uids[item.uid])) {
|
|
1468
|
+
|
|
1469
|
+
const currentDatasource = this.viewedPreset.datasource.find(_ => _.uid === item.datasourceUid)
|
|
1470
|
+
|
|
1471
|
+
if (currentDatasource) {
|
|
1472
|
+
results.push({
|
|
1473
|
+
type: item.type,
|
|
1474
|
+
uid: item.uid,
|
|
1475
|
+
...item
|
|
1476
|
+
})
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
else if (item.items) {
|
|
1480
|
+
const subResults = this.recurseViews(item.items, uids)
|
|
1481
|
+
results.push(...subResults)
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
return results
|
|
1486
|
+
},
|
|
1487
|
+
|
|
1488
|
+
selectedDatasourceColumn(key) {
|
|
1489
|
+
return this.selectedDatasource.columns.filter(_ => _.key === key).pop() ?? {}
|
|
1490
|
+
},
|
|
1491
|
+
|
|
1492
|
+
typeOf(type) {
|
|
1493
|
+
if (['boolean'].includes(type))
|
|
1494
|
+
return 'boolean'
|
|
1495
|
+
else if (['date'].includes(type))
|
|
1496
|
+
return 'date'
|
|
1497
|
+
else if (['number'].includes(type))
|
|
1498
|
+
return 'number'
|
|
1499
|
+
else if (['enum'].includes(type))
|
|
1500
|
+
return 'enum'
|
|
1501
|
+
else
|
|
1502
|
+
return 'text'
|
|
1503
|
+
},
|
|
1504
|
+
|
|
1505
|
+
removeDatasource(index) {
|
|
1506
|
+
this.selectedPreset.datasource.splice(index, 1)
|
|
1507
|
+
this.load()
|
|
1508
|
+
},
|
|
1509
|
+
|
|
1510
|
+
removeShared(item, index) {
|
|
1511
|
+
if (!this.removeSharingSrc)
|
|
1512
|
+
return this.alert('Unable to remove shared preset.')
|
|
1513
|
+
|
|
1514
|
+
this.confirm('Remove this preset?', () => {
|
|
1515
|
+
this.socket.send(this.removeSharingSrc, item)
|
|
1516
|
+
.then(_ => {
|
|
1517
|
+
this.sharedPresets.splice(index, 1)
|
|
1518
|
+
})
|
|
1519
|
+
})
|
|
1520
|
+
},
|
|
1521
|
+
|
|
1522
|
+
selectPreset(uid, params = {}) {
|
|
1523
|
+
this.$router.push({
|
|
1524
|
+
query: {
|
|
1525
|
+
uid,
|
|
1526
|
+
...params
|
|
1527
|
+
}
|
|
1528
|
+
})
|
|
1529
|
+
this.saveConfig()
|
|
1530
|
+
},
|
|
1531
|
+
|
|
1532
|
+
resize1(w) {
|
|
1533
|
+
if (this.sidebar.width + w >= 270 && this.sidebar.width + w <= 600) {
|
|
1534
|
+
this.sidebar.width += w
|
|
1535
|
+
}
|
|
1536
|
+
},
|
|
1537
|
+
|
|
1538
|
+
typeParamsOf(column) {
|
|
1539
|
+
if (['enum'].includes(column.type)) {
|
|
1540
|
+
return column.typeParams
|
|
1541
|
+
}
|
|
1542
|
+
return []
|
|
1543
|
+
},
|
|
1544
|
+
|
|
1545
|
+
getConfig() {
|
|
1546
|
+
return this.cConfig
|
|
1547
|
+
},
|
|
1548
|
+
|
|
1549
|
+
getPresets() {
|
|
1550
|
+
return this.presets
|
|
1551
|
+
},
|
|
1552
|
+
|
|
1553
|
+
removeQueryFilter() {
|
|
1554
|
+
|
|
1555
|
+
const query = {}
|
|
1556
|
+
for (let key in this.$route.query) {
|
|
1557
|
+
if (key.indexOf('.filters.') < 0) {
|
|
1558
|
+
query[key] = this.$route.query[key]
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
this.$router.replace({query})
|
|
1563
|
+
},
|
|
1564
|
+
|
|
1565
|
+
async preview(datasource) {
|
|
1566
|
+
return new Promise((resolve, reject) => {
|
|
1567
|
+
this.socket.send(this.previewSrc, {datasource})
|
|
1568
|
+
.then(res => {
|
|
1569
|
+
this.previewData = res
|
|
1570
|
+
resolve(res)
|
|
1571
|
+
})
|
|
1572
|
+
.catch(err => reject(err))
|
|
1573
|
+
})
|
|
1574
|
+
},
|
|
1575
|
+
|
|
1576
|
+
updatePivot() {
|
|
1577
|
+
this.preview(this.selectedDatasource)
|
|
1578
|
+
.then(res => {
|
|
1579
|
+
generatePivotColumns(this.selectedDatasource, res.items)
|
|
1580
|
+
})
|
|
1581
|
+
},
|
|
1582
|
+
|
|
1583
|
+
removeSharing(index) {
|
|
1584
|
+
const user = this.selectedPreset.sharing[index]
|
|
1585
|
+
|
|
1586
|
+
for (let datasource of this.selectedPreset.datasource) {
|
|
1587
|
+
for (let filter of datasource.filters) {
|
|
1588
|
+
const index = (filter.sharing ?? []).findIndex(_ => _.id === user.id)
|
|
1589
|
+
if (index > -1) {
|
|
1590
|
+
filter.sharing.splice(index, 1)
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
this.selectedPreset.sharing.splice(index, 1)
|
|
1596
|
+
},
|
|
1597
|
+
|
|
1598
|
+
|
|
1599
|
+
async loadConfig(){
|
|
1600
|
+
return this.socket.send(this.presetSrc, { key:this.presetKey })
|
|
1601
|
+
.then(async ({ config, presets, sharedPresets }) => {
|
|
1602
|
+
|
|
1603
|
+
this.config = config
|
|
1604
|
+
this.presets = presets
|
|
1605
|
+
this.sharedPresets = sharedPresets
|
|
1606
|
+
|
|
1607
|
+
if(this.$route.query?.search)
|
|
1608
|
+
this.preset.search = this.$route.query.search
|
|
1609
|
+
})
|
|
1610
|
+
.catch(() => {})
|
|
1611
|
+
},
|
|
1612
|
+
|
|
1613
|
+
saveConfig: invokeAfterIdle(function(reset = false, preset = false){
|
|
1614
|
+
if(!this.presetKey) return
|
|
1615
|
+
if(!this.config) return
|
|
1616
|
+
|
|
1617
|
+
return this.socket.send(this.presetSrc, {
|
|
1618
|
+
key:this.presetKey,
|
|
1619
|
+
config: {
|
|
1620
|
+
...this.config,
|
|
1621
|
+
presets: undefined
|
|
1622
|
+
},
|
|
1623
|
+
...(reset ? { reset:true, presets: this.presets } : {}),
|
|
1624
|
+
...(preset ? { presets: [ this.preset ] } : {}),
|
|
1625
|
+
})
|
|
1626
|
+
.catch(() => {})
|
|
1627
|
+
}),
|
|
1628
|
+
|
|
1629
|
+
async removePreset(preset){
|
|
1630
|
+
return this.socket.send(this.presetSrc, {
|
|
1631
|
+
key: this.presetKey,
|
|
1632
|
+
removePreset: preset
|
|
1633
|
+
})
|
|
1634
|
+
.then(_ => {
|
|
1635
|
+
this.presets.splice(this.presets.findIndex(_ => _.uid === preset.uid), 1)
|
|
1636
|
+
})
|
|
1637
|
+
.catch(() => {})
|
|
1638
|
+
},
|
|
1639
|
+
|
|
1640
|
+
savePreset: invokeAfterIdle(async function(){
|
|
1641
|
+
if(!this.presetKey) return
|
|
1642
|
+
if(!this.selectedPreset) return
|
|
1643
|
+
|
|
1644
|
+
return this.socket.send(this.presetSrc, {
|
|
1645
|
+
key: this.presetKey,
|
|
1646
|
+
presets: [
|
|
1647
|
+
this.selectedPreset
|
|
1648
|
+
]
|
|
1649
|
+
})
|
|
1650
|
+
.catch(() => {})
|
|
1651
|
+
}),
|
|
1652
|
+
|
|
1653
|
+
},
|
|
1654
|
+
|
|
1655
|
+
mounted() {
|
|
1656
|
+
this.loadConfig()
|
|
1657
|
+
.then(_ => this.load())
|
|
1658
|
+
},
|
|
1659
|
+
|
|
1660
|
+
props: {
|
|
1661
|
+
presetKey: String,
|
|
1662
|
+
presetSrc: {
|
|
1663
|
+
type: String,
|
|
1664
|
+
default: 'user.preset'
|
|
1665
|
+
},
|
|
1666
|
+
|
|
1667
|
+
src: String,
|
|
1668
|
+
|
|
1669
|
+
datasourceSrc: String,
|
|
1670
|
+
datasourceListSrc: String,
|
|
1671
|
+
|
|
1672
|
+
previewSrc: String,
|
|
1673
|
+
|
|
1674
|
+
sharingSrc: String,
|
|
1675
|
+
|
|
1676
|
+
removeSharingSrc: String,
|
|
1677
|
+
|
|
1678
|
+
title: String,
|
|
1679
|
+
},
|
|
1680
|
+
|
|
1681
|
+
provide() {
|
|
1682
|
+
return {
|
|
1683
|
+
listStyle: () => {
|
|
1684
|
+
},
|
|
1685
|
+
viewTypes: this.viewTypes,
|
|
1686
|
+
dashboardStyle: this.$style,
|
|
1687
|
+
previewDatasource: this.previewDatasource,
|
|
1688
|
+
emitRoot: this.emitRoot,
|
|
1689
|
+
getConfig: this.getConfig,
|
|
1690
|
+
getPresets: this.getPresets,
|
|
1691
|
+
selectPreset: this.selectPreset,
|
|
1692
|
+
preview: this.preview
|
|
1693
|
+
}
|
|
1694
|
+
},
|
|
1695
|
+
|
|
1696
|
+
setup(){
|
|
1697
|
+
const emitter = useEmitter()
|
|
1698
|
+
return {
|
|
1699
|
+
emitter
|
|
1700
|
+
}
|
|
1701
|
+
},
|
|
1702
|
+
|
|
1703
|
+
watch: {
|
|
1704
|
+
|
|
1705
|
+
'presets'(to) {
|
|
1706
|
+
this.cConfig.viewedUid = 'uid' in this.$route.query ? this.$route.query.uid : this.cConfig.viewedUid
|
|
1707
|
+
},
|
|
1708
|
+
|
|
1709
|
+
'cConfig.viewedUid'() {
|
|
1710
|
+
this.$emit('change')
|
|
1711
|
+
},
|
|
1712
|
+
|
|
1713
|
+
'cConfig.selectedUid'() {
|
|
1714
|
+
this.saveConfig()
|
|
1715
|
+
},
|
|
1716
|
+
|
|
1717
|
+
'cConfig.selectedDatasource'() {
|
|
1718
|
+
this.saveConfig()
|
|
1719
|
+
},
|
|
1720
|
+
|
|
1721
|
+
'$route.query': {
|
|
1722
|
+
handler(to) {
|
|
1723
|
+
if (this.cConfig) {
|
|
1724
|
+
this.cConfig.viewedUid = 'uid' in to ? to.uid : this.cConfig.viewedUid
|
|
1725
|
+
this.load()
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
},
|
|
1729
|
+
|
|
1730
|
+
config: {
|
|
1731
|
+
deep: true,
|
|
1732
|
+
handler(to, from){
|
|
1733
|
+
if(Object.keys(from ?? {}).length > 0){
|
|
1734
|
+
this.saveConfig()
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
},
|
|
1738
|
+
|
|
1739
|
+
selectedPreset: {
|
|
1740
|
+
deep: true,
|
|
1741
|
+
handler(to) {
|
|
1742
|
+
if(to) {
|
|
1743
|
+
this.savePreset()
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
</script>
|
|
1753
|
+
|
|
1754
|
+
<style module>
|
|
1755
|
+
|
|
1756
|
+
.comp {
|
|
1757
|
+
@apply flex flex-row;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
.resize1 {
|
|
1761
|
+
@apply w-[3px] cursor-ew-resize absolute top-0 right-0 bottom-0;
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
.button {
|
|
1765
|
+
@apply text-left p-3 border-[1px] border-transparent rounded-lg cursor-pointer;
|
|
1766
|
+
@apply hover:border-primary-300 hover:bg-primary-100;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
.columnTextbox input::placeholder {
|
|
1770
|
+
@apply text-text;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
</style>
|