@mixd-id/web-scaffold 0.1.230406384 → 0.1.230406386

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mixd-id/web-scaffold",
3
3
  "private": false,
4
- "version": "0.1.230406384",
4
+ "version": "0.1.230406386",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -14,6 +14,7 @@
14
14
  "./components/*": "./src/components/*",
15
15
  "./widgets/*": "./src/widgets/*",
16
16
  "./mixin/component": "./src/mixin/component.js",
17
+
17
18
  "./mixin/edit-mode": "./src/mixin/edit-mode.js",
18
19
  "./middleware/http/trim-string": "./src/middleware/http/trim-string.js",
19
20
  "./helpers": {
@@ -27,7 +27,6 @@
27
27
  </div>
28
28
 
29
29
  <div class="flex-1 flex flex-col relative">
30
- <div class="absolute bottom-0 left-0 w-[20px] h-[20px] z-10" @click="log(dataItems);log(sorts)"></div>
31
30
 
32
31
  <div class="flex-1 flex flex-col" :class="containerClass">
33
32
  <slot name="head"
@@ -268,12 +267,11 @@
268
267
 
269
268
  import VirtualTable from "./VirtualTable.vue";
270
269
  import VirtualGrid from "./VirtualGrid.vue";
271
- import throttle from "lodash/throttle";
272
270
  import PresetSelector from "../widgets/PresetSelector.vue";
273
271
  import groupBy from "lodash/groupBy";
274
272
  import {generatePivotColumns, generateTotalColumns, sortsFn} from "../utils/preset-selector.mjs";
275
273
  import PresetBar from "../widgets/PresetBar.vue";
276
- import {queueForLater} from "../utils/helpers.mjs";
274
+ import {invokeAfterIdle, queueForLater} from "../utils/helpers.mjs";
277
275
 
278
276
  export default{
279
277
 
@@ -369,6 +367,7 @@ export default{
369
367
  this.readyState = 2
370
368
  return this.socket.send(this.src, {
371
369
  ...this.preset,
370
+ id: undefined,
372
371
  itemsPerPage: this.data.itemsPerPage,
373
372
  })
374
373
  .then(data => {
@@ -402,6 +401,7 @@ export default{
402
401
  this.readyState = 4
403
402
  this.socket.send(this.src, {
404
403
  ...this.preset,
404
+ id: undefined,
405
405
  itemsPerPage: this.data.itemsPerPage,
406
406
  afterItem,
407
407
  })
@@ -544,8 +544,8 @@ export default{
544
544
  },
545
545
 
546
546
  resize1(w){
547
- if(this.config.sidebar.width + w >= 270 && this.config.sidebar.width + w <= 600){
548
- this.config.sidebar.width += w
547
+ if(this.sidebar.width + w >= 270 && this.sidebar.width + w <= 600){
548
+ this.sidebar.width += w
549
549
  }
550
550
  },
551
551
 
@@ -558,12 +558,12 @@ export default{
558
558
  }
559
559
  },
560
560
 
561
- savePreset: throttle(function() {
561
+ savePreset: invokeAfterIdle(function() {
562
562
  if(this.presetKey) {
563
563
  this.socket.send('user.preset',
564
564
  {key: this.presetKey, config: this.config})
565
565
  }
566
- }, 1000, { leading:true }),
566
+ }),
567
567
 
568
568
  openPreset(){
569
569
 
@@ -597,6 +597,22 @@ export default{
597
597
  }
598
598
  },
599
599
 
600
+ sortItems(items){
601
+
602
+ if((this.sorts ?? []).length > 0){
603
+ return (items ?? []).sort((a, b) => {
604
+ return sortsFn(a, b, this.sorts, 0)
605
+ })
606
+ }
607
+ else if((this.preset.sorts ?? []).length > 0){
608
+ return (items ?? []).sort((a, b) => {
609
+ return sortsFn(a, b, this.preset.sorts, 0)
610
+ })
611
+ }
612
+ return items
613
+
614
+ },
615
+
600
616
  loadQueued(items){
601
617
  const key = items[0] && items[0].uid ? 'uid' : 'id'
602
618
 
@@ -605,10 +621,21 @@ export default{
605
621
  [key]: items.map(item => item[key])
606
622
  })
607
623
  .then(({ items:nextItems }) => {
608
- nextItems.forEach(item => this.$util.unshift(this.data.items, item, { highlight: true }))
609
624
 
610
625
  const destroyedItems = items.filter(_ => !nextItems.find(i => i[key] === _[key]))
611
626
  this.$util.remove(this.data.items, destroyedItems)
627
+
628
+ let currentFirstItem = this.dataItems[0]
629
+ const sortedItems = this.sortItems([
630
+ ...nextItems,
631
+ currentFirstItem
632
+ ]
633
+ .filter(_ => _))
634
+
635
+ for(let item of sortedItems){
636
+ if(item === currentFirstItem) break
637
+ this.$util.unshift(this.data.items, item, { highlight: true })
638
+ }
612
639
  })
613
640
  },
614
641
 
@@ -920,20 +947,7 @@ export default{
920
947
  },
921
948
 
922
949
  dataItems(){
923
-
924
- if((this.sorts ?? []).length > 0){
925
- return (this.data.items ?? []).sort((a, b) => {
926
- return sortsFn(a, b, this.sorts, 0)
927
- })
928
- }
929
- else if((this.preset.sorts ?? []).length > 0){
930
- return (this.data.items ?? []).sort((a, b) => {
931
- return sortsFn(a, b, this.preset.sorts, 0)
932
- })
933
- }
934
- else{
935
- return this.data.items ?? []
936
- }
950
+ return this.sortItems(this.data.items)
937
951
  },
938
952
 
939
953
  preset(){
@@ -945,14 +959,21 @@ export default{
945
959
  (this.view ?? this.preset.view)
946
960
  },
947
961
 
962
+ configParams(){
963
+ if(!this.config.params)
964
+ this.config.params = {}
965
+ return this.config.params
966
+ },
967
+
948
968
  sidebar(){
949
- if(!this.config.sidebar || !('open' in this.config.sidebar))
950
- this.config.sidebar = {
969
+
970
+ if(!this.configParams.sidebar || !('open' in this.configParams.sidebar))
971
+ this.configParams.sidebar = {
951
972
  open: false,
952
973
  width: 270
953
974
  }
954
975
 
955
- return this.config.sidebar
976
+ return this.configParams.sidebar
956
977
  },
957
978
 
958
979
  sidebarStyle(){
@@ -88,7 +88,10 @@ export default{
88
88
  default: 'bottom'
89
89
  },
90
90
 
91
- state: [ Number, Boolean, String ],
91
+ state: {
92
+ type: [ Number, Boolean, String ],
93
+ default: undefined
94
+ },
92
95
 
93
96
  transition: String,
94
97
 
@@ -244,7 +247,7 @@ export default{
244
247
 
245
248
  computedState(){
246
249
  return (this.debugState && this.editMode) ? Boolean(this.debugState) :
247
- (this.state ? Boolean(this.state) : this._state)
250
+ (this.state !== undefined ? Boolean(this.state) : this._state)
248
251
  },
249
252
 
250
253
  currentState(){
@@ -258,7 +258,7 @@ export default{
258
258
  }
259
259
 
260
260
  this.scrollerCache = {
261
- id: this.items[this.visibleStartIndex]?.id,
261
+ id: (this.items ?? [])[this.visibleStartIndex]?.id,
262
262
  index: this.visibleStartIndex
263
263
  }
264
264
  },
@@ -614,7 +614,7 @@ export default{
614
614
  }
615
615
 
616
616
  this.scrollerCache = {
617
- id: this.items[this.visibleStartIndex]?.id,
617
+ id: (this.items ?? [])[this.visibleStartIndex]?.id,
618
618
  index: this.visibleStartIndex
619
619
  }
620
620
  },
@@ -319,6 +319,17 @@ function unslugAndCapitalize(slug) {
319
319
  .join(' ');
320
320
  }
321
321
 
322
+ function slugify(text) {
323
+ return text
324
+ .toString() // Ensure the input is a string
325
+ .normalize('NFD') // Normalize to decompose diacritic marks
326
+ .replace(/[\u0300-\u036f]/g, '') // Remove diacritic marks
327
+ .replace(/[^a-zA-Z0-9\s-]/g, '') // Remove special characters
328
+ .trim() // Trim leading/trailing spaces
329
+ .replace(/\s+/g, '-') // Replace spaces with dashes
330
+ .toLowerCase(); // Convert to lowercase
331
+ }
332
+
322
333
  const hexToRgb = (hex) => {
323
334
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
324
335
  return result ? {
@@ -393,7 +404,7 @@ const invokeAfterIdle = (callback, delay = 1300) => {
393
404
  const queueForLater = (params) => {
394
405
 
395
406
  const instance = {
396
- delay: 1500,
407
+ delay: 1200,
397
408
  ...params,
398
409
 
399
410
  items: [],
@@ -443,6 +454,7 @@ export {
443
454
  removeStyleFromTag,
444
455
  createFormData,
445
456
  unslugAndCapitalize,
457
+ slugify,
446
458
  applyDatasourceReplacer,
447
459
  strVars,
448
460
  invokeAfterIdle,
@@ -1,8 +1,7 @@
1
1
  const groupBy = require("lodash/groupBy");
2
2
  const dayjs = require("dayjs");
3
- const {Op, literal, fn, col, where, DataTypes} = require("sequelize");
3
+ const {Op, literal, fn, DataTypes} = module.parent.require("sequelize");
4
4
  const {ftWildcard} = require("./helpers");
5
- const util = require("util");
6
5
 
7
6
  const getValue = (filter, opt) => {
8
7
 
@@ -1010,7 +1009,6 @@ const chartToSequelizeWhere = async (chart, opt) => {
1010
1009
  }
1011
1010
 
1012
1011
  const pivotToSequelizeWhere = async (pivot, opt) => {
1013
-
1014
1012
  const { model, sorts = [] } = opt
1015
1013
 
1016
1014
  const attributes = []
@@ -1018,120 +1016,123 @@ const pivotToSequelizeWhere = async (pivot, opt) => {
1018
1016
  const order = []
1019
1017
  const sortExists = sorts.length > 0
1020
1018
 
1021
- const groupedSorts = groupBy(sorts, 'key')
1022
-
1023
- for(let row of pivot.rows){
1019
+ if(Array.isArray(pivot.rows)){
1020
+ const groupedSorts = groupBy(sorts, 'key')
1024
1021
 
1025
- const field = model.rawAttributes[row.key].field
1022
+ for(let row of pivot.rows){
1023
+ const field = model.rawAttributes[row.key].field
1026
1024
 
1027
- switch(row.aggregrate){
1025
+ switch(row.aggregrate){
1028
1026
 
1029
- case 'date':
1030
- attributes.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m-%d'), row.key ])
1031
- group.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m-%d'), row.key ])
1032
- if(!sortExists) order.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m-%d'), 'asc' ])
1033
- break
1027
+ case 'date':
1028
+ attributes.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m-%d'), row.key ])
1029
+ group.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m-%d'), row.key ])
1030
+ if(!sortExists) order.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m-%d'), 'asc' ])
1031
+ break
1034
1032
 
1035
- case 'month':
1036
- attributes.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m'), row.key ])
1037
- group.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m'), row.key ])
1038
- if(!sortExists) order.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m'), 'asc' ])
1039
- break
1033
+ case 'month':
1034
+ attributes.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m'), row.key ])
1035
+ group.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m'), row.key ])
1036
+ if(!sortExists) order.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y-%m'), 'asc' ])
1037
+ break
1040
1038
 
1041
- case 'year':
1042
- attributes.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y'), row.key ])
1043
- group.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y'), row.key ])
1044
- if(!sortExists) order.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y'), 'asc' ])
1045
- break
1039
+ case 'year':
1040
+ attributes.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y'), row.key ])
1041
+ group.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y'), row.key ])
1042
+ if(!sortExists) order.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%Y'), 'asc' ])
1043
+ break
1046
1044
 
1047
- case 'hour':
1048
- attributes.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%H:00-%H:59'), row.key ])
1049
- group.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%H:00-%H:59'), row.key ])
1050
- if(!sortExists) order.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%H:00-%H:59'), 'asc' ])
1051
- break
1045
+ case 'hour':
1046
+ attributes.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%H:00-%H:59'), row.key ])
1047
+ group.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%H:00-%H:59'), row.key ])
1048
+ if(!sortExists) order.push([ fn('DATE_FORMAT', literal(`${model.name}.${field}`), '%H:00-%H:59'), 'asc' ])
1049
+ break
1052
1050
 
1053
- default:
1054
- attributes.push([ literal(`${model.name}.${field}`), row.key ])
1055
- group.push(`${model.name}.${field}`)
1056
- if(!sortExists) order.push([ row.key, groupedSorts[row.key] ? groupedSorts[row.key][0].type : 'asc' ])
1057
- break
1051
+ default:
1052
+ attributes.push([ literal(`${model.name}.${field}`), row.key ])
1053
+ group.push(`${model.name}.${field}`)
1054
+ if(!sortExists) order.push([ row.key, groupedSorts[row.key] ? groupedSorts[row.key][0].type : 'asc' ])
1055
+ break
1056
+ }
1058
1057
  }
1059
1058
  }
1060
1059
 
1061
1060
  const sortKeyToOrders = {} // Helper to determine group ordering
1062
- for(let value of pivot.values){
1063
- const valueKey = model.rawAttributes[value.key].field
1061
+ if(Array.isArray(pivot.values)){
1062
+ for(let value of pivot.values){
1063
+ const valueKey = model.rawAttributes[value.key].field
1064
1064
 
1065
- switch(value.aggregrate){
1065
+ switch(value.aggregrate){
1066
1066
 
1067
- case 'sum':
1068
- attributes.push([ fn('SUM', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1069
- break
1067
+ case 'sum':
1068
+ attributes.push([ fn('SUM', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1069
+ break
1070
1070
 
1071
- case 'avg':
1072
- attributes.push([ fn('AVG', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1073
- break
1071
+ case 'avg':
1072
+ attributes.push([ fn('AVG', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1073
+ break
1074
1074
 
1075
- case 'min':
1076
- attributes.push([ fn('MIN', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1077
- break
1075
+ case 'min':
1076
+ attributes.push([ fn('MIN', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1077
+ break
1078
1078
 
1079
- case 'max':
1080
- attributes.push([ fn('MAX', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1081
- break
1079
+ case 'max':
1080
+ attributes.push([ fn('MAX', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1081
+ break
1082
1082
 
1083
- case 'countDistinct':
1084
- attributes.push([ literal(`COUNT(DISTINCT ${model.name}.${valueKey})`), `_${value.key}-${value.aggregrate}` ])
1085
- sortKeyToOrders[`_${value.key}-${value.aggregrate}`] = literal(`COUNT(DISTINCT ${model.name}.${valueKey})`)
1086
- break
1083
+ case 'countDistinct':
1084
+ attributes.push([ literal(`COUNT(DISTINCT ${model.name}.${valueKey})`), `_${value.key}-${value.aggregrate}` ])
1085
+ sortKeyToOrders[`_${value.key}-${value.aggregrate}`] = literal(`COUNT(DISTINCT ${model.name}.${valueKey})`)
1086
+ break
1087
1087
 
1088
- case 'count':
1089
- attributes.push([ fn('COUNT', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1090
- sortKeyToOrders[`_${value.key}-${value.aggregrate}`] = fn('COUNT', literal(`${model.name}.${valueKey}`))
1091
- break
1088
+ case 'count':
1089
+ attributes.push([ fn('COUNT', literal(`${model.name}.${valueKey}`)), `_${value.key}-${value.aggregrate}` ])
1090
+ sortKeyToOrders[`_${value.key}-${value.aggregrate}`] = fn('COUNT', literal(`${model.name}.${valueKey}`))
1091
+ break
1092
1092
 
1093
- default:
1094
- const { where, replacements } = opt
1095
- const groups = await model.findAll({
1096
- attributes: [ value.key ],
1097
- where: {
1098
- [Op.and]: [
1099
- where
1100
- ]
1101
- },
1102
- group: [ value.key ],
1103
- replacements
1104
- })
1093
+ default:
1094
+ const { where, replacements } = opt
1095
+ const groups = await model.findAll({
1096
+ attributes: [ value.key ],
1097
+ where: {
1098
+ [Op.and]: [
1099
+ where
1100
+ ]
1101
+ },
1102
+ group: [ value.key ],
1103
+ replacements
1104
+ })
1105
1105
 
1106
- if(groups.length > 50){
1107
- throw new Error('Pivot value group is too large, max 50 items allowed.')
1108
- }
1106
+ if(groups.length > 50){
1107
+ throw new Error('Pivot value group is too large, max 50 items allowed.')
1108
+ }
1109
1109
 
1110
- const field = model.rawAttributes[value.key].field
1110
+ const field = model.rawAttributes[value.key].field
1111
1111
 
1112
1112
 
1113
- groups.forEach(group => {
1113
+ groups.forEach(group => {
1114
1114
 
1115
- let groupValue
1116
- if(group[value.key] === null){
1117
- attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} is null THEN 1 ELSE 0 END)`), `_${value.key}-(null)` ])
1118
- }
1119
- else if(group[value.key] === ''){
1120
- attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = '' THEN 1 ELSE 0 END)`), `_${value.key}-(empty)` ])
1121
- }
1122
- else{
1123
- if(model.rawAttributes[value.key].type instanceof DataTypes.BOOLEAN){
1124
- groupValue = group[value.key]
1125
- attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = ${groupValue === true ? 1 : 0} THEN 1 ELSE 0 END)`), `_${value.key}-${groupValue}` ])
1115
+ let groupValue
1116
+ if(group[value.key] === null){
1117
+ attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} is null THEN 1 ELSE 0 END)`), `_${value.key}-(null)` ])
1118
+ }
1119
+ else if(group[value.key] === ''){
1120
+ attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = '' THEN 1 ELSE 0 END)`), `_${value.key}-(empty)` ])
1126
1121
  }
1127
1122
  else{
1128
- groupValue = (group[value.key] ?? '').toString().replace(/\s/g, '_')
1129
- attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = '${group[value.key]}' THEN 1 ELSE 0 END)`), `_${value.key}-${groupValue}` ])
1123
+ if(model.rawAttributes[value.key].type instanceof DataTypes.BOOLEAN){
1124
+ groupValue = group[value.key]
1125
+ attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = ${groupValue === true ? 1 : 0} THEN 1 ELSE 0 END)`), `_${value.key}-${groupValue}` ])
1126
+ }
1127
+ else{
1128
+ groupValue = (group[value.key] ?? '').toString().replace(/\s/g, '_')
1129
+ attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = '${group[value.key]}' THEN 1 ELSE 0 END)`), `_${value.key}-${groupValue}` ])
1130
+ }
1130
1131
  }
1131
- }
1132
- })
1132
+ })
1133
1133
 
1134
- break
1134
+ break
1135
+ }
1135
1136
  }
1136
1137
  }
1137
1138
 
@@ -85,12 +85,12 @@
85
85
  </div>
86
86
 
87
87
  <div class="flex items-center justify-center border-b-[1px] border-text-100 px-3">
88
- <Tabs :items="tabItems[config.type ?? 'list']" v-model="config.presetBarTabIndex" />
88
+ <Tabs :items="tabItems[config.type ?? 'list']" v-model="configParams.presetBarTabIndex" />
89
89
  </div>
90
90
 
91
91
  <div class="flex-1 overflow-y-auto">
92
92
 
93
- <div v-if="config.presetBarTabIndex === 1" class="flex-1 flex flex-col p-5">
93
+ <div v-if="configParams.presetBarTabIndex === 1" class="flex-1 flex flex-col p-5">
94
94
  <ListItem :items="presetColumns"
95
95
  body-class="divide-y divide-text-50 rounded-lg border-[1px] border-text-50 bg-base-300"
96
96
  @reorder="(from, to) => { presetColumns.splice(to, 0, presetColumns.splice(from, 1)[0]); }">
@@ -113,7 +113,7 @@
113
113
  </ListItem>
114
114
  </div>
115
115
 
116
- <div v-else-if="config.presetBarTabIndex === 2" class="flex-1 flex flex-col p-5">
116
+ <div v-else-if="configParams.presetBarTabIndex === 2" class="flex-1 flex flex-col p-5">
117
117
 
118
118
  <div class="flex-1 flex flex-col gap-6">
119
119
 
@@ -186,7 +186,7 @@
186
186
 
187
187
  </div>
188
188
 
189
- <div v-else-if="config.presetBarTabIndex === 3" class="flex-1 flex flex-col p-5">
189
+ <div v-else-if="configParams.presetBarTabIndex === 3" class="flex-1 flex flex-col p-5">
190
190
 
191
191
  <ListItem v-if="Array.isArray(preset.sorts) && preset.sorts.length > 0"
192
192
  :items="preset.sorts"
@@ -237,7 +237,7 @@
237
237
 
238
238
  </div>
239
239
 
240
- <div v-else-if="config.presetBarTabIndex === 4" class="flex-1 flex flex-col gap-6 p-6">
240
+ <div v-else-if="configParams.presetBarTabIndex === 4" class="flex-1 flex flex-col gap-6 p-6">
241
241
 
242
242
  <div>
243
243
  <label>Select Type:</label>
@@ -454,13 +454,24 @@
454
454
 
455
455
  </div>
456
456
 
457
- <div v-else-if="config.presetBarTabIndex === 5" class="flex-1 p-6">
457
+ <div v-else-if="configParams.presetBarTabIndex === 5" class="flex-1 p-6">
458
458
 
459
459
  <PresetBarPivot :pivot="presetPivot" :columns="pivotColumns" @apply="apply"/>
460
460
 
461
461
  </div>
462
462
 
463
- <div v-else-if="config.presetBarTabIndex === 9" class="flex-1 p-6 flex flex-col gap-6">
463
+ <div v-else-if="configParams.presetBarTabIndex === 6" class="flex-1 p-6">
464
+
465
+ <button class="text-primary" type="button"
466
+ @click="$refs.sharingModal.open([], { callback:addSharing })">
467
+ Share
468
+ </button>
469
+
470
+ <SharingModal ref="sharingModal" :src="configParams.sharingSrc"/>
471
+
472
+ </div>
473
+
474
+ <div v-else-if="configParams.presetBarTabIndex === 9" class="flex-1 p-6 flex flex-col gap-6">
464
475
 
465
476
  <div>
466
477
  <div class="flex flex-row">
@@ -495,10 +506,11 @@
495
506
 
496
507
  import PresetSelectorFilterItem from "../components/PresetSelectorFilterItem.vue";
497
508
  import PresetBarPivot from "./PresetBarPivot.vue";
509
+ import SharingModal from "./Dashboard/SharingModal.vue";
498
510
 
499
511
  export default{
500
512
 
501
- components: {PresetBarPivot, PresetSelectorFilterItem},
513
+ components: {SharingModal, PresetBarPivot, PresetSelectorFilterItem},
502
514
 
503
515
  emits: [ 'apply' ],
504
516
 
@@ -508,7 +520,9 @@ export default{
508
520
 
509
521
  config: Object,
510
522
 
511
- enumCache: Object
523
+ enumCache: Object,
524
+
525
+ sharingSrc: String,
512
526
 
513
527
  },
514
528
 
@@ -521,6 +535,13 @@ export default{
521
535
  this.apply()
522
536
  },
523
537
 
538
+ addSharing(item) {
539
+ if (!Array.isArray(this.preset.sharing))
540
+ this.preset.sharing = []
541
+
542
+ this.$util.push(this.preset.sharing, item, {key: "id"})
543
+ },
544
+
524
545
  addSort(obj){
525
546
  if(!Array.isArray(this.preset.sorts))
526
547
  this.preset.sorts = []
@@ -537,7 +558,7 @@ export default{
537
558
  canApply(){
538
559
 
539
560
  if(this.preset){
540
- if(this.config.presetBarTabIndex === 2){
561
+ if(this.configParams.presetBarTabIndex === 2){
541
562
  return true
542
563
  /*if(Array.isArray(this.preset.filters)){
543
564
  if(this.preset.filters.filter(_ => !_.key).length > 0){
@@ -545,14 +566,14 @@ export default{
545
566
  }
546
567
  }*/
547
568
  }
548
- else if(this.config.presetBarTabIndex === 3){
569
+ else if(this.configParams.presetBarTabIndex === 3){
549
570
  if(Array.isArray(this.preset.sorts)){
550
571
  if(this.preset.sorts.filter(_ => !_.key).length > 0){
551
572
  return false
552
573
  }
553
574
  }
554
575
  }
555
- else if(this.config.presetBarTabIndex === 4){
576
+ else if(this.configParams.presetBarTabIndex === 4){
556
577
  if(Array.isArray(this.chartOpt.xAxis)){
557
578
  if(this.chartOpt.xAxis.filter(_ => !_.key).length > 0){
558
579
  return false
@@ -596,7 +617,7 @@ export default{
596
617
  },
597
618
 
598
619
  deselect(){
599
- this.config.presetBar.view = 1
620
+ this.presetBar.view = 1
600
621
  },
601
622
 
602
623
  filterColumnAdded(column){
@@ -639,6 +660,12 @@ export default{
639
660
  return this.presetChart[this.chartType]
640
661
  },
641
662
 
663
+ configParams(){
664
+ if(!this.config.params)
665
+ this.config.params = {}
666
+ return this.config.params
667
+ },
668
+
642
669
  filterColumns(){
643
670
  return this.config.columns.filter(_ => {
644
671
  return _.filterable !== false
@@ -697,12 +724,12 @@ export default{
697
724
  },
698
725
 
699
726
  presetBar(){
700
- if(!this.config.presetBar || !this.config.presetBar.view)
701
- this.config.presetBar = {
727
+ if(!this.configParams.presetBar || !this.configParams.presetBar.view)
728
+ this.configParams.presetBar = {
702
729
  view: 2
703
730
  }
704
731
 
705
- return this.config.presetBar
732
+ return this.configParams.presetBar
706
733
  }
707
734
 
708
735
  },
@@ -715,6 +742,7 @@ export default{
715
742
  ...((this.config ?? {}).filters !== false ? [{ text:'Filters', value:2 }] : []),
716
743
  ...((this.config ?? {}).sorts !== false ? [{ text:'Sorts', value:3 }] : []),
717
744
  ...((this.config ?? {}).pivot !== false ? [{ text:'Pivot', value:5 }] : []),
745
+ ...(this.sharingSrc ? [{ text:'Sharing', value:6 }] : []),
718
746
  ...('debug' in this.$route.query || import.meta.env.DEV ? [{ text:'Debug', value:9 }] : []),
719
747
  ],
720
748
  chart: [
@@ -726,8 +754,8 @@ export default{
726
754
  },
727
755
 
728
756
  mounted() {
729
- if(!this.config.presetBarTabIndex){
730
- this.config.presetBarTabIndex = this.config.type === 'chart' ? 4 : 1
757
+ if(!this.configParams.presetBarTabIndex){
758
+ this.configParams.presetBarTabIndex = this.config.type === 'chart' ? 4 : 1
731
759
  }
732
760
  }
733
761
 
@@ -76,10 +76,10 @@
76
76
  <option value="">Default</option>
77
77
  <option value="count">Count</option>
78
78
  <option value="countDistinct">Distinct Count</option>
79
- <option v-if="[ 'number' ].includes(item.type)" value="sum">Sum</option>
80
- <option v-if="[ 'number' ].includes(item.type)" value="avg">Average</option>
81
- <option v-if="[ 'number' ].includes(item.type)" value="min">Min</option>
82
- <option v-if="[ 'number' ].includes(item.type)" value="max">Max</option>
79
+ <option v-if="[ 'number', 'currency' ].includes(item.type)" value="sum">Sum</option>
80
+ <option v-if="[ 'number', 'currency' ].includes(item.type)" value="avg">Average</option>
81
+ <option v-if="[ 'number', 'currency' ].includes(item.type)" value="min">Min</option>
82
+ <option v-if="[ 'number', 'currency' ].includes(item.type)" value="max">Max</option>
83
83
  </select>
84
84
  </div>
85
85
  <button type="button" @click="pivot.values.splice(index, 1); apply()">
@@ -154,7 +154,9 @@ export default{
154
154
  },
155
155
 
156
156
  addPivot(type, obj){
157
- console.log(this.pivot, type)
157
+ if(!this.pivot[type])
158
+ this.pivot[type] = []
159
+
158
160
  this.pivot[type].push(Object.assign({}, obj))
159
161
  this.apply()
160
162
  },