@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.
Files changed (92) hide show
  1. package/docs/schema/user-action.json +266 -0
  2. package/package.json +6 -2
  3. package/public/assets/dashboard/bar.png +0 -0
  4. package/public/assets/dashboard/doughnut.png +0 -0
  5. package/public/assets/dashboard/metric.png +0 -0
  6. package/public/assets/dashboard/pie.png +0 -0
  7. package/public/assets/dashboard/polar-area.png +0 -0
  8. package/public/assets/dashboard/virtual-table.png +0 -0
  9. package/public/static/dashboard/bar.png +0 -0
  10. package/public/static/dashboard/doughnut.png +0 -0
  11. package/public/static/dashboard/metric.png +0 -0
  12. package/public/static/dashboard/pie.png +0 -0
  13. package/public/static/dashboard/polar-area.png +0 -0
  14. package/public/static/dashboard/virtual-table.png +0 -0
  15. package/src/components/Button.vue +179 -160
  16. package/src/components/Checkbox.vue +0 -1
  17. package/src/components/Datepicker.vue +8 -6
  18. package/src/components/GHeatMaps.vue +317 -0
  19. package/src/components/GmapsDirection.vue +191 -0
  20. package/src/components/Grid.vue +2 -0
  21. package/src/components/HTMLEditor.vue +2 -2
  22. package/src/components/List.vue +384 -308
  23. package/src/components/Modal.vue +2 -3
  24. package/src/components/PresetSelectorFilterItem.vue +15 -2
  25. package/src/components/Switch.vue +3 -0
  26. package/src/components/Tabs.vue +1 -1
  27. package/src/components/TextWithTag.vue +67 -25
  28. package/src/components/Textbox.vue +5 -0
  29. package/src/components/VirtualGrid.vue +224 -228
  30. package/src/components/VirtualTable.vue +46 -28
  31. package/src/configs/dashboard/bar.js +10 -0
  32. package/src/configs/dashboard/collection-1.js +5 -0
  33. package/src/configs/dashboard/doughnut.js +7 -0
  34. package/src/configs/dashboard/gheatmaps.js +9 -0
  35. package/src/configs/dashboard/grid-2.js +34 -0
  36. package/src/configs/dashboard/grid-3.js +34 -0
  37. package/src/configs/dashboard/grid-4.js +34 -0
  38. package/src/configs/dashboard/grid.js +15 -0
  39. package/src/configs/dashboard/metric.js +10 -0
  40. package/src/configs/dashboard/pie.js +7 -0
  41. package/src/configs/dashboard/polar-area.js +7 -0
  42. package/src/configs/dashboard/virtual-table.js +9 -0
  43. package/src/defs/dashboard-preset.js +22 -0
  44. package/src/index.js +35 -23
  45. package/src/mixin/ready-state.js +37 -0
  46. package/src/stores/datasource.js +11 -0
  47. package/src/themes/default/index.js +1 -1
  48. package/src/utils/dashboard.js +1080 -0
  49. package/src/utils/event-bus.js +8 -0
  50. package/src/utils/helpers.js +56 -10
  51. package/src/utils/helpers.mjs +35 -1
  52. package/src/utils/preset-selector.js +5 -2
  53. package/src/utils/preset-selector.mjs +23 -13
  54. package/src/widgets/Dashboard/BarChart.vue +330 -0
  55. package/src/widgets/Dashboard/BarChartSetting.vue +317 -0
  56. package/src/widgets/Dashboard/DatasourceFilterSharing.vue +93 -0
  57. package/src/widgets/Dashboard/DatasourcePreview.vue +93 -0
  58. package/src/widgets/Dashboard/DatasourceSelector.vue +122 -0
  59. package/src/widgets/Dashboard/Doughnut.vue +157 -0
  60. package/src/widgets/Dashboard/DoughnutSetting.vue +196 -0
  61. package/src/widgets/Dashboard/GHeatMapsSetting.vue +108 -0
  62. package/src/widgets/Dashboard/InteractionEdit.vue +228 -0
  63. package/src/widgets/Dashboard/Metric.vue +76 -0
  64. package/src/widgets/Dashboard/MetricSetting.vue +174 -0
  65. package/src/widgets/Dashboard/Pie.vue +139 -0
  66. package/src/widgets/Dashboard/PieSetting.vue +247 -0
  67. package/src/widgets/Dashboard/PolarArea.vue +159 -0
  68. package/src/widgets/Dashboard/PolarAreaSetting.vue +195 -0
  69. package/src/widgets/Dashboard/SharingModal.vue +116 -0
  70. package/src/widgets/Dashboard/ViewSelector.vue +183 -0
  71. package/src/widgets/Dashboard/VirtualColumnEdit.vue +97 -0
  72. package/src/widgets/Dashboard/VirtualTableSetting.vue +234 -0
  73. package/src/widgets/Dashboard.vue +1773 -0
  74. package/src/widgets/PresetBar.vue +136 -175
  75. package/src/widgets/PresetBarPivot.vue +186 -0
  76. package/src/widgets/UserActionBuilder/UserActionCondition.vue +97 -0
  77. package/src/widgets/UserActionBuilder/UserActionConsole.vue +77 -0
  78. package/src/widgets/UserActionBuilder/UserActionItem.vue +163 -58
  79. package/src/widgets/UserActionBuilder/UserActionOutput.vue +35 -9
  80. package/src/widgets/UserActionBuilder/UserActionOutputDelay.vue +27 -0
  81. package/src/widgets/UserActionBuilder/UserActionOutputLog.vue +28 -0
  82. package/src/widgets/UserActionBuilder/UserActionOutputReply.vue +135 -0
  83. package/src/widgets/UserActionBuilder/UserActionProps.vue +211 -0
  84. package/src/widgets/UserActionBuilder.vue +68 -199
  85. package/src/widgets/WebPageBuilder4/GridSetting.vue +123 -73
  86. package/src/widgets/WebPageBuilder4/HeightSetting.vue +14 -11
  87. package/src/widgets/WebPageBuilder4/MarginSetting.vue +4 -1
  88. package/src/widgets/WebPageBuilder4/MultiValueSetting.vue +12 -4
  89. package/src/widgets/WebPageBuilder4/PaddingSetting.vue +4 -0
  90. package/src/widgets/WebPageBuilder4/TreeView.vue +6 -3
  91. package/src/widgets/WebPageBuilder4/TreeViewItem.vue +32 -58
  92. package/tailwind.config.js +2 -2
@@ -0,0 +1,8 @@
1
+ // eventBus.js
2
+ import mitt from 'mitt'
3
+
4
+ const emitter = mitt()
5
+
6
+ export const useEmitter = () => {
7
+ return emitter
8
+ }
@@ -1,10 +1,9 @@
1
- import {Duplex} from "stream";
2
-
3
1
  const md5 = require("md5");
4
2
  const fs = require("fs");
5
3
  const { Op } = require('sequelize')
6
4
  const axios = require('axios')
7
5
  const dayjs = require('dayjs')
6
+ const { camelCase } = require('lodash')
8
7
 
9
8
 
10
9
  const ceil = (num, precision = 0) => {
@@ -142,13 +141,14 @@ const strSlug = (title, separator) => {
142
141
  return title.replace(new RegExp('^[' + separator + '\\s]+|[' + separator + '\\s]+$', 'g'),'');
143
142
  }
144
143
 
145
- const strVars = (text, vars, opt = { emptyUndefined:true }) => {
146
-
147
- (text.match(/\{.*?(?=\})\}/gi) ?? []).forEach((match) => {
148
- const key = match.substring(1, match.length - 1)
149
- const value = vars[key] ?? (opt?.emptyUndefined ? '' : `{${key}}`)
150
- text = text.replace(match, value)
151
- })
144
+ const strVars = (text, vars = {}, opt = { emptyUndefined:true }) => {
145
+ if(text){
146
+ (text.match(/\{.*?(?=\})\}/gi) ?? []).forEach((match) => {
147
+ const key = match.substring(1, match.length - 1)
148
+ const value = vars[key] ?? (opt?.emptyUndefined ? '' : `{${key}}`)
149
+ text = text.replace(match, value)
150
+ })
151
+ }
152
152
 
153
153
  return text
154
154
  }
@@ -262,7 +262,7 @@ const unflatten = (flatObject) => {
262
262
  }
263
263
 
264
264
  const accessNestedObject = function(obj, path) {
265
- if(!obj || typeof path !== 'string') return undefined
265
+ if(!obj || typeof path !== 'string') return
266
266
 
267
267
  const keys = path.split('.');
268
268
  let nestedObj = obj;
@@ -279,6 +279,43 @@ const accessNestedObject = function(obj, path) {
279
279
  return nestedObj;
280
280
  }
281
281
 
282
+ const accessNestedSequelize = async(obj, path, opt = { defaultValue:'' }) => {
283
+ if(!obj || typeof path !== 'string') return
284
+
285
+ const keys = path.split('.');
286
+ let value = obj;
287
+
288
+ for (let i in keys) {
289
+ const key = keys[i]
290
+ const hasNext = i < keys.length - 1
291
+
292
+ if(hasNext){
293
+
294
+ if(!value[key]){
295
+ try{
296
+ value = await value[camelCase(`get-${key}`)]()
297
+ }
298
+ catch(e){}
299
+ }
300
+ else{
301
+ value = value[key]
302
+ }
303
+
304
+ if(!value){
305
+ return
306
+ }
307
+ }
308
+
309
+ else{
310
+ value = key in value.dataValues ?
311
+ value[key] :
312
+ opt.defaultValue
313
+ }
314
+ }
315
+
316
+ return value;
317
+ }
318
+
282
319
  const createObjectFromPath = (obj, path, value) => {
283
320
  const keys = path.split('.');
284
321
 
@@ -526,8 +563,16 @@ const dayTimeRange = (params, value) => {
526
563
  })
527
564
  }
528
565
 
566
+ function capitalize(str) {
567
+ return (str ?? '')
568
+ .toString()
569
+ .split(' ')
570
+ .map(_ => _.charAt(0).toUpperCase() + _.slice(1).toLowerCase())
571
+ .join(' ')
572
+ }
529
573
 
530
574
  module.exports = {
575
+ capitalize,
531
576
  ceil,
532
577
  floor,
533
578
  ftWildcard,
@@ -546,6 +591,7 @@ module.exports = {
546
591
  getPresetSortWhereParams,
547
592
  unflatten,
548
593
  accessNestedObject,
594
+ accessNestedSequelize,
549
595
  createObjectFromPath,
550
596
  generateStylesheet,
551
597
  hexToRgb,
@@ -360,7 +360,40 @@ function applyDatasourceReplacer(value, datasource){
360
360
  return value
361
361
  }
362
362
 
363
+ function capitalize(str) {
364
+ return str.replace(/\b\w/g, function(char) {
365
+ return char.toUpperCase();
366
+ });
367
+ }
368
+
369
+ const round = (num, precision = 0) => {
370
+ var p = Math.pow(10, precision)
371
+ var n = (num * p) * (1 + Number.EPSILON)
372
+ return Math.round(n) / p
373
+ }
374
+
375
+ let invokeAfterIdleStore = []
376
+ const invokeAfterIdle = (callback, delay = 1300) => {
377
+ let timeoutId
378
+
379
+ return function(){
380
+ if(invokeAfterIdleStore.includes(callback))
381
+ return
382
+
383
+ invokeAfterIdleStore.push(callback)
384
+
385
+ window.clearTimeout(timeoutId)
386
+ timeoutId = window.setTimeout(() => {
387
+ callback.apply(this, arguments)
388
+ invokeAfterIdleStore.splice(invokeAfterIdleStore.indexOf(callback), 1)
389
+ }, delay)
390
+ }
391
+ }
392
+
393
+
363
394
  export {
395
+ capitalize,
396
+ round,
364
397
  downsizeImage,
365
398
  hexToRgb,
366
399
  rgbToHex,
@@ -382,7 +415,8 @@ export {
382
415
  createFormData,
383
416
  unslugAndCapitalize,
384
417
  applyDatasourceReplacer,
385
- strVars
418
+ strVars,
419
+ invokeAfterIdle
386
420
  }
387
421
 
388
422
  function observeInit(){
@@ -925,9 +925,11 @@ const presetToSequelizeList = async(preset = {}, {
925
925
  order:initialOrder
926
926
  }) => {
927
927
 
928
+ const updatedAtField = model.rawAttributes['updatedAt'] ?? model.rawAttributes['updated_at']
929
+
928
930
  if(!initialOrder){
929
931
  initialOrder = [
930
- [ 'updatedAt', 'desc' ],
932
+ ...(updatedAtField ? [[ updatedAtField.fieldName, 'desc' ]] : []),
931
933
  [ 'id', 'desc' ],
932
934
  ]
933
935
  }
@@ -1036,7 +1038,8 @@ const presetToSequelizeList = async(preset = {}, {
1036
1038
  ...replacements,
1037
1039
  ...filterReplacements,
1038
1040
  ...searchReplacements
1039
- ]
1041
+ ],
1042
+ itemsPerPage
1040
1043
  }
1041
1044
  }
1042
1045
  }
@@ -1,3 +1,5 @@
1
+ import md5 from "md5";
2
+
1
3
  const sortsFn = function(a, b, sorts, index){
2
4
 
3
5
  const sort = sorts[index]
@@ -31,24 +33,31 @@ const pickColumns = function(columns, keys){
31
33
  return picked
32
34
  }
33
35
 
36
+ const getPresetUid = function(extra = ''){
37
+ return md5('preset-' + new Date().getTime() + extra)
38
+ }
39
+
34
40
  const setupConfig = (config) => {
35
41
 
36
42
  if(Array.isArray(config.presets)){
37
43
  for(let idx in config.presets){
38
- if(!Array.isArray(config.presets[idx].columns)){
39
- config.presets[idx].columns = []
44
+ if(!Array.isArray(config.presets[idx].params.columns)){
45
+ config.presets[idx].params.columns = []
40
46
  }
41
47
 
42
- if(config.presets[idx].columns[0] && typeof config.presets[idx].columns[0] === 'string'){
43
- config.presets[idx].columns = pickColumns(config.columns ?? [], config.presets[idx].columns)
48
+ if(config.presets[idx].params.columns[0] && typeof config.presets[idx].params.columns[0] === 'string'){
49
+ config.presets[idx].params.columns = pickColumns(config.params.columns ?? [], config.presets[idx].params.columns)
44
50
  }
45
51
 
46
- if(!config.presets[idx].view)
47
- config.presets[idx].view = 'table'
52
+ if(!config.presets[idx].params.view)
53
+ config.presets[idx].params.view = 'table'
54
+
55
+ if(!config.presets[idx].uid)
56
+ config.presets[idx].uid = getPresetUid(idx)
48
57
  }
49
58
 
50
- if(!config.presetIdx && config.presets.length > 0){
51
- config.presetIdx = 0
59
+ if(!config.params.presetIdx && config.presets.length > 0){
60
+ config.params.presetIdx = config.presets[0].uid
52
61
  }
53
62
  }
54
63
 
@@ -147,11 +156,11 @@ const generatePivotColumns = (preset, items) => {
147
156
  }
148
157
  }
149
158
 
150
- (preset.pivot.columns ?? []).filter(_ => !pivotColumns.find(i => i.key === _.key))
159
+ /*(preset.pivot.columns ?? []).filter(_ => !pivotColumns.find(i => i.key === _.key))
151
160
  .forEach(_ => {
152
161
  _.visible = false
153
162
  pivotColumns.push(_)
154
- })
163
+ })*/
155
164
 
156
165
  preset.pivot.columns = pivotColumns
157
166
 
@@ -177,9 +186,10 @@ const generateTotalColumns = (preset, items) => {
177
186
  }
178
187
 
179
188
  export {
180
- sortsFn,
189
+ getPresetUid,
190
+ generatePivotColumns,
191
+ generateTotalColumns,
181
192
  pickColumns,
182
193
  setupConfig,
183
- generatePivotColumns,
184
- generateTotalColumns
194
+ sortsFn,
185
195
  }
@@ -0,0 +1,330 @@
1
+ <template>
2
+ <div :class="$style.comp" :style="cStyle">
3
+
4
+ <div v-if="readyState === 2" class="flex-1 flex items-center justify-center">
5
+ <label class="text-text-300">Loading...</label>
6
+ </div>
7
+
8
+ <div v-else-if="isError" class="flex-1 flex">
9
+ <div :style="barStyles" class="flex-1 flex items-center justify-center">
10
+ <p class="text-text-300">{{ value.message }}</p>
11
+ </div>
12
+ </div>
13
+
14
+ <div v-else class="flex flex-col gap-3">
15
+ <div class="flex flex-row items-center gap-4">
16
+ <label class="text-text-400 text-ellipsis overflow-hidden whitespace-nowrap flex-1">{{ label }}</label>
17
+ </div>
18
+
19
+ <div class="flex-1">
20
+ <Bar :style="barStyles"
21
+ :options="chartOptions"
22
+ :data="chartData"/>
23
+ </div>
24
+
25
+ <div v-if="yAxeMultiple && yLegends?.length > 0" class="flex flex-row items-center flex-wrap justify-center gap-1">
26
+ <div v-for="yLegend in showedYLegends"
27
+ @click="toggleExcludes(yLegend)"
28
+ class="p-0.5 px-1 rounded-full text-black cursor-default text-xs min-w-[50px] max-w-[60px] text-center text-ellipsis overflow-hidden whitespace-nowrap capitalize"
29
+ :class="excluded.includes(yLegend.key) ? 'bg-text-200' : ''"
30
+ :style="{ backgroundColor:excluded.includes(yLegend.key) ? '' : yLegend.color }">
31
+ {{ yLegend.key }}
32
+ </div>
33
+ <button v-if="yLegends.length > showedYLegends.length" @click="$refs.legendModal.open()"
34
+ class="bg-text-200 hover:bg-primary-600 w-[21px] h-[21px] rounded-full flex items-center justify-center">
35
+ <svg width="14" height="14" class="fill-white opacity-70" 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="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"/></svg>
36
+ </button>
37
+ </div>
38
+
39
+ <Modal ref="legendModal" width="320" height="360" :dismissable="true" @dismiss="$refs.legendModal.close()">
40
+ <template v-slot:head>
41
+ <div class="relative p-5">
42
+ <h3>Legend</h3>
43
+ <div class="absolute top-0 right-0 p-2">
44
+ <button type="button" class="p-2" @click="$refs.legendModal.close()">
45
+ <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">
46
+ <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"/>
47
+ </svg>
48
+ </button>
49
+ </div>
50
+ </div>
51
+ </template>
52
+ <div class="flex-1 p-5 pt-0">
53
+
54
+ <div class="flex flex-col divide-y divide-text-50">
55
+ <div v-for="yLegend in yLegends" class="flex flex-row items-center gap-2 py-2">
56
+ <div class="w-[19px] h-[19px] rounded-full" :style="{ backgroundColor:yLegend.color }"></div>
57
+ <div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden">{{ yLegend.key }}</div>
58
+ <Checkbox :value="!excluded.includes(yLegend.key)" @click.prevent="toggleExcludes(yLegend)" />
59
+ </div>
60
+ </div>
61
+
62
+ <br />
63
+
64
+ </div>
65
+ </Modal>
66
+ </div>
67
+
68
+ </div>
69
+ </template>
70
+
71
+ <script>
72
+
73
+ import {Bar} from 'vue-chartjs'
74
+ import {color} from 'chart.js/helpers'
75
+ import {strVars} from "../../utils/helpers.mjs";
76
+ import {readyStateMixin} from "../../mixin/ready-state";
77
+
78
+ export default{
79
+
80
+ components: {
81
+ Bar
82
+ },
83
+
84
+ computed: {
85
+
86
+ barStyles(){
87
+ return {
88
+ position: "relative",
89
+ height: `${this.barHeight}px`
90
+ }
91
+ },
92
+
93
+ cStyle(){
94
+ return {
95
+ minHeight: this.height
96
+ }
97
+ },
98
+
99
+ chartData(){
100
+ if(!this.value?.datasets)
101
+ return { labels:[], datasets:[] }
102
+
103
+ return {
104
+ labels: this.value?.labels ?? [],
105
+ datasets: this.value.datasets
106
+ .filter(_ => !this.excluded.includes(_.label))
107
+ .map(_ => {
108
+ return {
109
+ ..._,
110
+ borderWidth: 0,
111
+ borderColor: function(context, options) {
112
+ const hex = options.color;
113
+ return color(hex).darken(0.5).rgbString()
114
+ }
115
+ }
116
+ })
117
+ }
118
+ },
119
+
120
+ chartOptions(){
121
+ return {
122
+ responsive: true,
123
+ maintainAspectRatio: false,
124
+ borderRadius: 4,
125
+ plugins: {
126
+ legend: {
127
+ display: false // This hides the legend
128
+ },
129
+ tooltip: {
130
+ callbacks: {
131
+ title: function(tooltipItems) {
132
+ return `${tooltipItems[0].label}`;
133
+ },
134
+ label: (tooltipItem) => {
135
+ if(this.yAxeMultiple && this.usePercentage)
136
+ return `${tooltipItem.dataset.label}: ${tooltipItem.dataset.data0[tooltipItem.dataIndex]} (${tooltipItem.raw}%)`
137
+ else{
138
+ if(this.stacked){
139
+ const total = this.value.datasets.reduce((acc, cur) => acc + cur.data[tooltipItem.dataIndex], 0)
140
+ const percentage = ((tooltipItem.raw / total) * 100).toFixed(1)
141
+
142
+ return `${tooltipItem.dataset.label}: ${tooltipItem.raw} (${percentage}%)`;
143
+ }
144
+ return `${tooltipItem.dataset.label}: ${tooltipItem.raw}`;
145
+ }
146
+ }
147
+ },
148
+ }
149
+ },
150
+ scales: {
151
+ x: {
152
+ grid: {
153
+ display: true,
154
+ color: function(context){
155
+ return `rgba(255,255,255, .1)`
156
+ }
157
+ },
158
+ ticks: {
159
+ callback: function(value) {
160
+ const label = this.getLabelForValue(value) ?? '';
161
+ return label.length > 10 ? label.slice(0, 30) + '...' : label;
162
+ },
163
+ minRotation: 0,
164
+ maxRotation: 0,
165
+ font: {
166
+ size: 11
167
+ }
168
+ },
169
+ stacked: !!this.stacked,
170
+ },
171
+ y: {
172
+ beginAtZero: true,
173
+ ticks: {
174
+ display: true,
175
+ font: {
176
+ size: 11,
177
+ },
178
+ callback: (value, index, ticks) => {
179
+ if(this.usePercentage)
180
+ return Math.round(index / (ticks.length - 1) * 100) + '%'
181
+ return value
182
+ },
183
+ },
184
+ grid: {
185
+ display: true,
186
+ color: function(context){
187
+ return `rgba(255,255,255, .1)`
188
+ }
189
+ },
190
+ stacked: !!this.stacked
191
+ }
192
+ },
193
+ onClick: this.onClick
194
+ }
195
+ },
196
+
197
+ isError(){
198
+ return this.value?.error === 1
199
+ },
200
+
201
+ yLegends(){
202
+ return this.value?.yLegends ?? []
203
+ },
204
+
205
+ showedYLegends(){
206
+ return this.yLegends.slice(0, 5)
207
+ },
208
+
209
+ },
210
+
211
+ data(){
212
+ return {
213
+ backgroundColors: [
214
+ '#5D9CEC',
215
+ '#A0D468',
216
+ '#FFCE54',
217
+ '#FC6E51',
218
+ '#48CFAD',
219
+ '#AC92EC',
220
+ '#4FC1E9',
221
+ '#FFCE54',
222
+ '#ED5565',
223
+ '#EC87C0'
224
+ ],
225
+
226
+ height: '',
227
+ datasets: null
228
+ }
229
+ },
230
+
231
+ inject: [ 'selectPreset' ],
232
+
233
+ methods: {
234
+
235
+ onClick(e, segments){
236
+
237
+ const clickInteractions = (this.interactions ?? []).filter(_ => _.event === 'click')
238
+ const segment = segments[0]
239
+ if(!segment) return
240
+
241
+ const dataset = this.value.datasets[segment.datasetIndex]
242
+ const obj = {
243
+ segment: this.value.labels[segment.index],
244
+ key: dataset.label,
245
+ value: dataset.data[segment.index]
246
+ }
247
+
248
+ for(let click of clickInteractions){
249
+ const { action, presetUid, filters } = click
250
+
251
+ const params = filters.reduce((res, cur) => {
252
+ res[cur.datasourceUid + '.filters.' + cur.key + '.' + cur.operator] = strVars(cur.value, obj)
253
+ return res
254
+ }, {})
255
+
256
+ switch(action){
257
+
258
+ case 'openDashboardPreset':
259
+ if(typeof this.selectPreset === 'function')
260
+ this.selectPreset(presetUid, params)
261
+ break
262
+ }
263
+ }
264
+
265
+ },
266
+
267
+ toggleExcludes(yLegend){
268
+ if(this.excluded.includes(yLegend.key))
269
+ this.excluded.splice(this.excluded.indexOf(yLegend.key), 1)
270
+ else
271
+ this.excluded.push(yLegend.key)
272
+ }
273
+
274
+ },
275
+
276
+ mounted() {
277
+ this.height = this.$el.clientHeight + 'px'
278
+ },
279
+
280
+ mixins: [ readyStateMixin ],
281
+
282
+ props: {
283
+
284
+ datasourceUid: String,
285
+
286
+ usePercentage: [ Boolean, Number ],
287
+ stacked: [ Boolean, Number ],
288
+
289
+ barHeight: {
290
+ type: Number,
291
+ default: 200
292
+ },
293
+
294
+ label: String,
295
+
296
+ xAxes: Array,
297
+ yAxes: Array,
298
+ xAxeMultiple: Boolean,
299
+ yAxeMultiple: Boolean,
300
+
301
+ excluded: {
302
+ type: Array,
303
+ default: []
304
+ },
305
+
306
+ segments: Array,
307
+ xAxesGroup: String,
308
+
309
+ yAxeOnClick: Array,
310
+
311
+ value: Object,
312
+
313
+ interactions: Array,
314
+
315
+ uid: String
316
+
317
+ },
318
+
319
+ }
320
+
321
+ </script>
322
+
323
+ <style module>
324
+
325
+ .comp{
326
+ @apply border-[1px] border-text-50 bg-base-500 rounded-lg;
327
+ @apply p-3 flex flex-col min-h-[200px];
328
+ }
329
+
330
+ </style>