@mixd-id/web-scaffold 0.1.230406341 → 0.1.230406342
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- 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/Grid.vue +2 -0
- package/src/components/VirtualTable.vue +5 -1
- package/src/configs/dashboard/bar.js +9 -0
- package/src/configs/dashboard/collection-1.js +5 -0
- package/src/configs/dashboard/doughnut.js +7 -0
- package/src/configs/dashboard/grid-2.js +32 -0
- package/src/configs/dashboard/grid-3.js +32 -0
- package/src/configs/dashboard/grid-4.js +32 -0
- package/src/configs/dashboard/grid.js +13 -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/utils/dashboard.js +100 -0
- package/src/widgets/Dashboard/BarChart.vue +7 -6
- package/src/widgets/Dashboard/BarChartSetting.vue +30 -25
- package/src/widgets/Dashboard/DatasourcePreview.vue +83 -0
- package/src/widgets/Dashboard/DatasourceSelector.vue +19 -5
- package/src/widgets/Dashboard/Doughnut.vue +1 -0
- package/src/widgets/Dashboard/DoughnutSetting.vue +30 -9
- package/src/widgets/Dashboard/InteractionEdit.vue +194 -0
- package/src/widgets/Dashboard/Metric.vue +11 -1
- package/src/widgets/Dashboard/MetricSetting.vue +54 -7
- package/src/widgets/Dashboard/Pie.vue +32 -1
- package/src/widgets/Dashboard/PieSetting.vue +127 -19
- package/src/widgets/Dashboard/PolarArea.vue +1 -0
- package/src/widgets/Dashboard/PolarAreaSetting.vue +30 -9
- package/src/widgets/Dashboard/SharingModal.vue +12 -9
- package/src/widgets/Dashboard/ViewSelector.vue +104 -36
- package/src/widgets/Dashboard/VirtualTableSetting.vue +71 -39
- package/src/widgets/Dashboard.vue +251 -132
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mixd-id/web-scaffold",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.230406342",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite serve",
|
|
7
7
|
"build": "vite build",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"./importer": "./src/utils/importer.js",
|
|
28
28
|
"./listpage1": "./src/utils/listpage1.js",
|
|
29
|
+
"./dashboard": "./src/utils/dashboard.js",
|
|
29
30
|
"./listview": "./src/utils/listview.js",
|
|
30
31
|
"./preset-selector": {
|
|
31
32
|
"require": "./src/utils/preset-selector.js",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/components/Grid.vue
CHANGED
|
@@ -103,7 +103,7 @@ export default{
|
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
|
|
106
|
-
inject: [ 'listStyle' ],
|
|
106
|
+
inject: [ 'emitRoot', 'listStyle' ],
|
|
107
107
|
|
|
108
108
|
emits: [ 'scroll-end', 'item-click' ],
|
|
109
109
|
|
|
@@ -114,6 +114,8 @@ export default{
|
|
|
114
114
|
|
|
115
115
|
itemClass: String,
|
|
116
116
|
|
|
117
|
+
uid: String,
|
|
118
|
+
|
|
117
119
|
items: Array,
|
|
118
120
|
|
|
119
121
|
pinned: Function,
|
|
@@ -314,6 +316,8 @@ export default{
|
|
|
314
316
|
if(this.scrollTop > this.$refs.scroller.offsetHeight - this.$refs.cont.clientHeight - this.itemHeight){
|
|
315
317
|
if(!this.isOnEndScroll){
|
|
316
318
|
this.$emit('scroll-end')
|
|
319
|
+
if(typeof this.emitRoot === 'function')
|
|
320
|
+
this.emitRoot.apply(this, [ 'scroll-end', this.$props ])
|
|
317
321
|
this.isOnEndScroll = true
|
|
318
322
|
}
|
|
319
323
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const component = {
|
|
2
|
+
|
|
3
|
+
type:'Grid',
|
|
4
|
+
|
|
5
|
+
isContainer:true,
|
|
6
|
+
|
|
7
|
+
props:{
|
|
8
|
+
|
|
9
|
+
columns:[
|
|
10
|
+
'grid-cols-1',
|
|
11
|
+
'md:grid-cols-2',
|
|
12
|
+
'',
|
|
13
|
+
''
|
|
14
|
+
],
|
|
15
|
+
|
|
16
|
+
gap:[
|
|
17
|
+
'gap-5',
|
|
18
|
+
'md:gap-5',
|
|
19
|
+
'',
|
|
20
|
+
''
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
alignItems:[
|
|
24
|
+
'items-start',
|
|
25
|
+
'md:items-start',
|
|
26
|
+
'',
|
|
27
|
+
''
|
|
28
|
+
],
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const component = {
|
|
2
|
+
|
|
3
|
+
type:'Grid',
|
|
4
|
+
|
|
5
|
+
isContainer:true,
|
|
6
|
+
|
|
7
|
+
props:{
|
|
8
|
+
|
|
9
|
+
columns:[
|
|
10
|
+
'grid-cols-1',
|
|
11
|
+
'md:grid-cols-3',
|
|
12
|
+
'',
|
|
13
|
+
''
|
|
14
|
+
],
|
|
15
|
+
|
|
16
|
+
gap:[
|
|
17
|
+
'gap-5',
|
|
18
|
+
'md:gap-5',
|
|
19
|
+
'',
|
|
20
|
+
''
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
alignItems:[
|
|
24
|
+
'items-start',
|
|
25
|
+
'md:items-start',
|
|
26
|
+
'',
|
|
27
|
+
''
|
|
28
|
+
],
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const component = {
|
|
2
|
+
|
|
3
|
+
type:'Grid',
|
|
4
|
+
|
|
5
|
+
isContainer:true,
|
|
6
|
+
|
|
7
|
+
props:{
|
|
8
|
+
|
|
9
|
+
columns:[
|
|
10
|
+
'grid-cols-2',
|
|
11
|
+
'md:grid-cols-4',
|
|
12
|
+
'',
|
|
13
|
+
''
|
|
14
|
+
],
|
|
15
|
+
|
|
16
|
+
gap:[
|
|
17
|
+
'gap-5',
|
|
18
|
+
'md:gap-5',
|
|
19
|
+
'',
|
|
20
|
+
''
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
alignItems:[
|
|
24
|
+
'items-start',
|
|
25
|
+
'md:items-start',
|
|
26
|
+
'',
|
|
27
|
+
''
|
|
28
|
+
],
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const {presetToSequelizeList} = require("./preset-selector");
|
|
2
|
+
|
|
3
|
+
const backgroundColors = [
|
|
4
|
+
'#5D9CEC',
|
|
5
|
+
'#A0D468',
|
|
6
|
+
'#FFCE54',
|
|
7
|
+
'#FC6E51',
|
|
8
|
+
'#48CFAD',
|
|
9
|
+
'#AC92EC',
|
|
10
|
+
'#4FC1E9',
|
|
11
|
+
'#FFCE54',
|
|
12
|
+
'#ED5565',
|
|
13
|
+
'#EC87C0'
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
const getModelFromDatasource = async (datasource, opt) => {
|
|
17
|
+
if(!opt.conn.models[datasource.datasourceUid]){
|
|
18
|
+
const tableColumns = await getSequelizeColumns(datasource.columns, opt)
|
|
19
|
+
|
|
20
|
+
opt.conn.define(datasource.datasourceUid, tableColumns, {
|
|
21
|
+
tableName: `datasource_${datasource.datasourceUid}`
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return opt.conn.models[datasource.datasourceUid]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const getDatasourceItems = async (datasource, opt) => {
|
|
29
|
+
|
|
30
|
+
const Model = await getModelFromDatasource(datasource, opt)
|
|
31
|
+
const config = {
|
|
32
|
+
columns: datasource.columns
|
|
33
|
+
}
|
|
34
|
+
const findOpt = await presetToSequelizeList(datasource, {
|
|
35
|
+
config,
|
|
36
|
+
model: Model,
|
|
37
|
+
conn: opt.conn,
|
|
38
|
+
limit: 100
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
return await Model.findAll({
|
|
42
|
+
...findOpt,
|
|
43
|
+
raw: true
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const getSequelizeColumns = async (columns, opt) => {
|
|
48
|
+
|
|
49
|
+
const { DataTypes } = opt.Sequelize
|
|
50
|
+
|
|
51
|
+
const tableColumns = {
|
|
52
|
+
id: {
|
|
53
|
+
type: DataTypes.INTEGER,
|
|
54
|
+
autoIncrement: true,
|
|
55
|
+
primaryKey: true,
|
|
56
|
+
allowNull: false,
|
|
57
|
+
},
|
|
58
|
+
createdAt: { type: DataTypes.DATE },
|
|
59
|
+
updatedAt: { type: DataTypes.DATE },
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
for(let column of columns){
|
|
63
|
+
|
|
64
|
+
let type
|
|
65
|
+
switch(column.type){
|
|
66
|
+
case 'date':
|
|
67
|
+
type = DataTypes.DATE
|
|
68
|
+
break
|
|
69
|
+
case 'number':
|
|
70
|
+
type = DataTypes.BIGINT
|
|
71
|
+
break
|
|
72
|
+
|
|
73
|
+
default:
|
|
74
|
+
type = DataTypes.STRING(column.maxLength ?? 40)
|
|
75
|
+
break
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
tableColumns[column.key] = {
|
|
79
|
+
type
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return tableColumns
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
getModelFromDatasource,
|
|
89
|
+
getDatasourceItems,
|
|
90
|
+
getSequelizeColumns,
|
|
91
|
+
|
|
92
|
+
backgroundColors,
|
|
93
|
+
|
|
94
|
+
/*loadBarChart,
|
|
95
|
+
loadMetric,
|
|
96
|
+
loadDoughnut,
|
|
97
|
+
loadPie,
|
|
98
|
+
loadPolarArea,
|
|
99
|
+
loadVirtualTable*/
|
|
100
|
+
}
|
|
@@ -49,6 +49,7 @@ export default{
|
|
|
49
49
|
return {
|
|
50
50
|
responsive: true,
|
|
51
51
|
maintainAspectRatio: false,
|
|
52
|
+
borderRadius: 4,
|
|
52
53
|
plugins: {
|
|
53
54
|
legend: {
|
|
54
55
|
display: false // This hides the legend
|
|
@@ -69,7 +70,8 @@ export default{
|
|
|
69
70
|
},
|
|
70
71
|
minRotation: 0,
|
|
71
72
|
maxRotation: 0
|
|
72
|
-
}
|
|
73
|
+
},
|
|
74
|
+
stacked: !!this.stacked,
|
|
73
75
|
},
|
|
74
76
|
y: {
|
|
75
77
|
beginAtZero: true,
|
|
@@ -82,6 +84,7 @@ export default{
|
|
|
82
84
|
return `rgba(255,255,255, .1)`
|
|
83
85
|
}
|
|
84
86
|
},
|
|
87
|
+
stacked: !!this.stacked,
|
|
85
88
|
}
|
|
86
89
|
},
|
|
87
90
|
onClick: function(evt, evt2) {
|
|
@@ -98,7 +101,7 @@ export default{
|
|
|
98
101
|
},
|
|
99
102
|
|
|
100
103
|
yLegends(){
|
|
101
|
-
return this.value
|
|
104
|
+
return this.value?.yLegends ?? []
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
},
|
|
@@ -126,10 +129,8 @@ export default{
|
|
|
126
129
|
|
|
127
130
|
datasourceUid: String,
|
|
128
131
|
|
|
129
|
-
usePercentage:
|
|
130
|
-
|
|
131
|
-
default: false
|
|
132
|
-
},
|
|
132
|
+
usePercentage: [ Boolean, Number ],
|
|
133
|
+
stacked: [ Boolean, Number ],
|
|
133
134
|
|
|
134
135
|
barHeight: {
|
|
135
136
|
type: Number,
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="flex flex-col gap-5 p-6">
|
|
3
3
|
|
|
4
|
-
<div class="flex flex-
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
v-model="value.props.datasourceUid"
|
|
10
|
-
@change="delete value.props.columns">
|
|
11
|
-
<option v-for="obj in datasource"
|
|
12
|
-
:value="obj.uid">
|
|
13
|
-
{{ obj.name }}
|
|
14
|
-
</option>
|
|
15
|
-
</Dropdown>
|
|
4
|
+
<div class="flex flex-col gap-1">
|
|
5
|
+
<div class="flex flex-row gap-2">
|
|
6
|
+
<label class="flex-1">Datasource</label>
|
|
7
|
+
<button type="button" class="text-primary"
|
|
8
|
+
@click="previewDatasource(selectedDatasource)">Preview</button>
|
|
16
9
|
</div>
|
|
10
|
+
<Dropdown class="min-w-[150px]"
|
|
11
|
+
:readonly="readonly"
|
|
12
|
+
v-model="value.props.datasourceUid"
|
|
13
|
+
@change="delete value.props.columns">
|
|
14
|
+
<option v-for="obj in datasource"
|
|
15
|
+
:value="obj.uid">
|
|
16
|
+
{{ obj.name }}
|
|
17
|
+
</option>
|
|
18
|
+
</Dropdown>
|
|
17
19
|
</div>
|
|
18
20
|
|
|
19
21
|
<div class="flex flex-col gap-1">
|
|
@@ -60,9 +62,9 @@
|
|
|
60
62
|
</div>
|
|
61
63
|
<div class="flex-1">
|
|
62
64
|
<Dropdown v-model="item.key" :readonly="readonly">
|
|
63
|
-
<option v-for="column in
|
|
65
|
+
<option v-for="column in selectedDatasourceColumns"
|
|
64
66
|
:value="column.key">
|
|
65
|
-
{{ column.label }}
|
|
67
|
+
{{ selectedDatasource.pivot?.enabled ? column.key : column.label }}
|
|
66
68
|
</option>
|
|
67
69
|
</Dropdown>
|
|
68
70
|
</div>
|
|
@@ -111,9 +113,9 @@
|
|
|
111
113
|
</div>
|
|
112
114
|
<div class="flex-1">
|
|
113
115
|
<Dropdown v-model="item.key">
|
|
114
|
-
<option v-for="column in
|
|
116
|
+
<option v-for="column in selectedDatasourceColumns"
|
|
115
117
|
:value="column.key">
|
|
116
|
-
{{ column.label }}
|
|
118
|
+
{{ selectedDatasource.pivot?.enabled ? column.key : column.label }}
|
|
117
119
|
</option>
|
|
118
120
|
</Dropdown>
|
|
119
121
|
</div>
|
|
@@ -138,14 +140,9 @@
|
|
|
138
140
|
<Switch v-model="value.props.usePercentage" />
|
|
139
141
|
</div>
|
|
140
142
|
|
|
141
|
-
<div class="flex flex-row items-center gap-2">
|
|
142
|
-
<label class="flex-1">
|
|
143
|
-
<
|
|
144
|
-
v-model.number="value.props.barHeight">
|
|
145
|
-
<option :value="200">200px</option>
|
|
146
|
-
<option :value="300">300px</option>
|
|
147
|
-
<option :value="400">400px</option>
|
|
148
|
-
</Dropdown>
|
|
143
|
+
<div v-if="value.props.yAxeMultiple" class="flex flex-row items-center gap-2">
|
|
144
|
+
<label class="flex-1">Stacked</label>
|
|
145
|
+
<Switch v-model="value.props.stacked" />
|
|
149
146
|
</div>
|
|
150
147
|
|
|
151
148
|
</div>
|
|
@@ -164,6 +161,14 @@ export default{
|
|
|
164
161
|
return this.datasource.find(d => d.uid === this.value.props.datasourceUid)
|
|
165
162
|
},
|
|
166
163
|
|
|
164
|
+
selectedDatasourceColumns(){
|
|
165
|
+
if(!this.selectedDatasource) return []
|
|
166
|
+
|
|
167
|
+
return this.selectedDatasource.pivot?.enabled ?
|
|
168
|
+
this.selectedDatasource.pivot.columns :
|
|
169
|
+
this.selectedDatasource.columns
|
|
170
|
+
},
|
|
171
|
+
|
|
167
172
|
xAxes(){
|
|
168
173
|
if(!Array.isArray(this.value.props.xAxes))
|
|
169
174
|
this.value.props.xAxes = [{ key:"" }]
|
|
@@ -188,7 +193,7 @@ export default{
|
|
|
188
193
|
|
|
189
194
|
},
|
|
190
195
|
|
|
191
|
-
inject: [ 'appStyle' ],
|
|
196
|
+
inject: [ 'appStyle', 'previewDatasource' ],
|
|
192
197
|
|
|
193
198
|
methods: {
|
|
194
199
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Modal ref="modal"
|
|
3
|
+
dismissable="true"
|
|
4
|
+
width="600"
|
|
5
|
+
height="600"
|
|
6
|
+
@dismiss="close">
|
|
7
|
+
<template v-slot:head>
|
|
8
|
+
<div class="relative p-6">
|
|
9
|
+
<h3>Data Preview</h3>
|
|
10
|
+
<div class="absolute top-0 right-0 p-2">
|
|
11
|
+
<button type="button" class="p-2" @click="close">
|
|
12
|
+
<svg width="24" height="24" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
|
|
13
|
+
<path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
|
|
14
|
+
</svg>
|
|
15
|
+
</button>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
<div class="flex-1 p-6 flex flex-col">
|
|
20
|
+
|
|
21
|
+
<VirtualTable class="flex-1" :columns="columns" :items="res?.items" />
|
|
22
|
+
|
|
23
|
+
</div>
|
|
24
|
+
</Modal>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
|
|
29
|
+
export default{
|
|
30
|
+
|
|
31
|
+
inject: [ 'alert', 'socket' ],
|
|
32
|
+
|
|
33
|
+
props: {
|
|
34
|
+
src: String
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
data(){
|
|
38
|
+
return {
|
|
39
|
+
columns: [],
|
|
40
|
+
datasource: null,
|
|
41
|
+
res: null
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
methods: {
|
|
46
|
+
|
|
47
|
+
close(){
|
|
48
|
+
this.$refs.modal.close()
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
load(){
|
|
52
|
+
this.socket.send(this.src, {
|
|
53
|
+
datasource: this.datasource
|
|
54
|
+
})
|
|
55
|
+
.then(res => {
|
|
56
|
+
this.res = res
|
|
57
|
+
|
|
58
|
+
this.columns = this.datasource.pivot?.enabled ?
|
|
59
|
+
this.datasource.pivot.columns :
|
|
60
|
+
this.datasource.columns
|
|
61
|
+
})
|
|
62
|
+
.catch(err => this.alert(err))
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
open(datasource){
|
|
66
|
+
this.datasource = datasource
|
|
67
|
+
this.$refs.modal.open()
|
|
68
|
+
this.load()
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<style module>
|
|
78
|
+
|
|
79
|
+
.comp{
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
</style>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
:class="dashboardStyle.button"
|
|
37
37
|
class="flex flex-row items-start gap-2">
|
|
38
38
|
<button type="button" class="flex-1 text-left" @click="add(datasource)">{{ datasource.name }}</button>
|
|
39
|
-
<button type="button" class="py-1" :ref="`btn${idx}`" @click="$refs.contextMenu.open($refs[`btn${idx}`][0], { datasource })">
|
|
39
|
+
<button v-if="contextMenuItems.length > 0" type="button" class="py-1" :ref="`btn${idx}`" @click="$refs.contextMenu.open($refs[`btn${idx}`][0], { datasource })">
|
|
40
40
|
<svg width="14" height="14" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path 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"/></svg>
|
|
41
41
|
</button>
|
|
42
42
|
</div>
|
|
@@ -44,10 +44,13 @@
|
|
|
44
44
|
<ContextMenu ref="contextMenu" position="bottom-right">
|
|
45
45
|
<template #default="{ context }">
|
|
46
46
|
<div class="flex flex-col min-w-[200px]">
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
<div v-for="item in contextMenuItems">
|
|
48
|
+
<button v-if="item.type === 'remove'" class="w-full p-3 text-left flex flex-row" :class="appStyle.menuItem"
|
|
49
|
+
@click="remove(context.datasource)">
|
|
50
|
+
{{ $t('Remove') }}
|
|
51
|
+
</button>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
51
54
|
</div>
|
|
52
55
|
</template>
|
|
53
56
|
</ContextMenu>
|
|
@@ -87,6 +90,17 @@ export default{
|
|
|
87
90
|
|
|
88
91
|
src: String,
|
|
89
92
|
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
computed: {
|
|
96
|
+
|
|
97
|
+
contextMenuItems(){
|
|
98
|
+
return [
|
|
99
|
+
this.removeSrc ? { type:'remove' } : null
|
|
100
|
+
]
|
|
101
|
+
.filter(_=>_)
|
|
102
|
+
}
|
|
103
|
+
|
|
90
104
|
},
|
|
91
105
|
|
|
92
106
|
data(){
|