@mixd-id/web-scaffold 0.1.230406288 → 0.1.230406290

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.230406288",
4
+ "version": "0.1.230406290",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -120,7 +120,7 @@
120
120
  </div>
121
121
  </slot>
122
122
 
123
- <VirtualTable v-if="presetView === 'table'"
123
+ <VirtualTable v-if="presetView === 'table' || pivotEnabled"
124
124
  ref="table"
125
125
  :columns="columns"
126
126
  class="flex-1 rounded-lg panel-400"
@@ -170,13 +170,13 @@
170
170
  <div v-if="extBar.open && pivotEnabled"
171
171
  :style="extStyle" class="border-t-[1px] border-text-50 flex flex-col relative md:p-5">
172
172
 
173
- <div :class="$style.resize2"
173
+ <div :class="$style.resize2" class="group"
174
174
  @mousedown="(e) => $util.dragResize(e, resize2)">
175
175
  <button type="button" @click.prevent="extBar.open = false"
176
- :class="$style.extClose">
176
+ :class="$style.extClose" class="group-hover:bg-primary">
177
177
  <svg width="14"
178
178
  height="14"
179
- class="fill-text-300 cursor-pointer"
179
+ class="fill-text-300 group-hover:fill-white cursor-pointer"
180
180
  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M432.6 209.3l-191.1 183.1C235.1 397.8 229.1 400 224 400s-11.97-2.219-16.59-6.688L15.41 209.3C5.814 200.2 5.502 184.1 14.69 175.4c9.125-9.625 24.38-9.938 33.91-.7187L224 342.8l175.4-168c9.5-9.219 24.78-8.906 33.91 .7187C442.5 184.1 442.2 200.2 432.6 209.3z"/></svg>
181
181
  </button>
182
182
  </div>
@@ -244,7 +244,7 @@ import VirtualGrid from "./VirtualGrid.vue";
244
244
  import throttle from "lodash/throttle";
245
245
  import PresetSelector from "../widgets/PresetSelector.vue";
246
246
  import groupBy from "lodash/groupBy";
247
- import {sortsFn} from "../utils/preset-selector.mjs";
247
+ import { generatePivotColumns, sortsFn } from "../utils/preset-selector.mjs";
248
248
  import PresetBar from "../widgets/PresetBar.vue";
249
249
 
250
250
  export default{
@@ -304,101 +304,6 @@ export default{
304
304
  .join(' ')
305
305
  },
306
306
 
307
- generatePivotColumns(items){
308
- if(!this.preset.pivot || !this.preset.pivot.enabled) return
309
- if(!Array.isArray(items) && items.length < 1) return
310
-
311
- const tableColumns = (this.preset.columns ?? this.config.columns)
312
- .reduce((cur, obj) => {
313
- cur[obj.key] = obj
314
- return cur
315
- }, {})
316
-
317
- const currentPivotColumns = [ ...(this.preset.pivot.columns ?? []) ]
318
- .reduce((cur, obj) => {
319
- cur[obj.key] = obj
320
- return cur
321
- }, {})
322
-
323
- const pivotColumns = []
324
-
325
- for(let row of this.preset.pivot.rows){
326
-
327
- let format
328
- switch(row.aggregrate){
329
- case 'year':
330
- format = 'YYYY'
331
- break
332
-
333
- case 'month':
334
- format = 'MMM YYYY'
335
- break
336
-
337
- case 'date':
338
- format = 'D MMM YYYY'
339
- break
340
- }
341
-
342
- if(currentPivotColumns[row.key]){
343
- Object.assign(currentPivotColumns[row.key], {
344
- format,
345
- visible: true
346
- })
347
-
348
- pivotColumns.push(currentPivotColumns[row.key])
349
- }
350
- else{
351
- pivotColumns.push({
352
- ...tableColumns[row.key],
353
- format,
354
- visible: true
355
- })
356
- }
357
- }
358
-
359
- for(let key in items[0]){
360
- if(key.startsWith('_')){
361
- let [ k1, ...k2 ] = key.substring(1).split('-')
362
- k2 = k2.join('-')
363
-
364
- let label = k2.replace(/_/gi, ' ')
365
- const column = tableColumns[k1]
366
- if(column){
367
- switch(column.type){
368
- case 'enum':
369
- label = (column.typeParams ?? []).find(_ => `${_.value}` === `${k2}`)?.text ?? label
370
- break
371
- }
372
- }
373
-
374
- if(currentPivotColumns[key]){
375
- Object.assign(currentPivotColumns[key], {
376
- visible: true
377
- })
378
-
379
- pivotColumns.push(currentPivotColumns[key])
380
- }
381
- else{
382
- pivotColumns.push({
383
- key,
384
- label,
385
- label2: (((tableColumns[k1] ?? {}).label ?? '') + ': ' + label).trim(),
386
- type: 'number',
387
- })
388
- }
389
- }
390
- }
391
-
392
- (this.preset.pivot.columns ?? []).filter(_ => !pivotColumns.find(i => i.key === _.key))
393
- .forEach(_ => {
394
- _.visible = false
395
- pivotColumns.push(_)
396
- })
397
-
398
- this.preset.pivot.columns = pivotColumns
399
-
400
- },
401
-
402
307
  load(){
403
308
  if(this.src){
404
309
  if(!this.preset.columns){
@@ -411,7 +316,7 @@ export default{
411
316
  })
412
317
  .then(data => {
413
318
 
414
- this.generatePivotColumns(data.items)
319
+ generatePivotColumns(this.preset, data.items)
415
320
  this.loadEnums(data.items)
416
321
  Object.assign(this.data, data ?? {})
417
322
  this.$emit('after-load')
@@ -529,7 +434,7 @@ export default{
529
434
  },
530
435
 
531
436
  loadExt(){
532
- if(!this.preset.filters || !this.extBar.open) return
437
+ if(!this.extBar.open) return
533
438
 
534
439
  this.readyState = 3
535
440
  return this.socket.send(this.src, {
@@ -620,7 +525,6 @@ export default{
620
525
 
621
526
  onSignal(event, items){
622
527
  if(this.pivotEnabled){
623
- console.log('no background update due ti pivot')
624
528
  return
625
529
  }
626
530
 
@@ -654,11 +558,22 @@ export default{
654
558
  const filters = []
655
559
 
656
560
  for(let idx in this.preset.pivot.rows){
561
+ const key = this.preset.pivot.rows[idx].key
562
+ const presetColumn = this.preset.columns.find(_ => _.key === key)
563
+ let value = item[this.preset.pivot.rows[idx].key]
564
+ switch(presetColumn.type){
565
+
566
+ case 'bool':
567
+ case 'boolean':
568
+ value = value === 'true'
569
+ break
570
+ }
571
+
657
572
  filters.push({
658
- key: this.preset.pivot.rows[idx].key,
573
+ key,
659
574
  value: [{
660
575
  operator: '=',
661
- value: item[this.preset.pivot.rows[idx].key]
576
+ value
662
577
  }]
663
578
  })
664
579
  }
@@ -667,11 +582,23 @@ export default{
667
582
  vv = vv.join('-')
668
583
 
669
584
  if(![ 'count' ].includes(vv)){
585
+
586
+ const key = kk.substring(1)
587
+ const presetColumn = this.preset.columns.find(_ => _.key === key)
588
+ let value = vv
589
+ switch(presetColumn.type){
590
+
591
+ case 'bool':
592
+ case 'boolean':
593
+ value = value === 'true'
594
+ break
595
+ }
596
+
670
597
  filters.push({
671
- key: kk.substring(1),
598
+ key,
672
599
  value: [{
673
600
  operator: '=',
674
- value: vv
601
+ value
675
602
  }]
676
603
  })
677
604
  }
@@ -922,11 +849,12 @@ export default{
922
849
  }
923
850
 
924
851
  .resize2{
925
- @apply h-[3px] cursor-n-resize absolute top-0 left-0 right-0 flex items-center justify-center;
852
+ @apply h-[5px] hover:bg-primary bg-text-50 cursor-n-resize absolute top-0 left-0 right-0 flex items-center justify-center;
853
+ @apply z-20;
926
854
  }
927
855
 
928
856
  .extClose{
929
- @apply w-[21px] h-[21px] rounded-full bg-base-300 flex items-center justify-center hover:bg-red-600;
857
+ @apply w-[21px] h-[21px] rounded-full bg-text-50 flex items-center justify-center hover:bg-red-600;
930
858
  }
931
859
 
932
860
  </style>
@@ -7,7 +7,7 @@
7
7
  <th v-for="column in visibleColumns" :style="thStyle(column)">
8
8
  <slot v-if="$slots['col-' + column.key]" :name="'col-' + column.key" :column="column"></slot>
9
9
  <div v-else :class="headerColumnClass(column)">
10
- <span>{{ column.label ?? column.key }}</span>
10
+ <span>{{ column.label2 ? column.label2 : (column.label ? column.label : column.key) }}</span>
11
11
  </div>
12
12
  <div :class="$style.separator" @mousedown="startResize($event, column)"></div>
13
13
  </th>
@@ -201,7 +201,6 @@ export default{
201
201
  this.resize()
202
202
 
203
203
  const observer = new MutationObserver((mutationsList) => {
204
- console.log(mutationsList)
205
204
  this.resize()
206
205
  });
207
206
  observer.observe(this.$el, { attributes: true });
@@ -254,7 +253,7 @@ export default{
254
253
  this.itemHeight = parseInt(window.getComputedStyle(this.$refs.calc).height)
255
254
  this.maxVisibleItems = elHeight > 0 ? Math.ceil(elHeight / this.itemHeight) + 1 : this.items.length
256
255
 
257
- if(this.itemHeight <= 0){
256
+ if(this.itemHeight <= 0 && import.meta.env.DEV){
258
257
  console.error('[VirtualTable] Unable to calculate item height, make sure not async component.')
259
258
  }
260
259
  }
@@ -4,7 +4,7 @@ const {inspect} = require("util");
4
4
  const {ftWildcard} = require("./helpers");
5
5
  const util = require("util");
6
6
  const {snakeCase} = require("lodash");
7
- const {Op, literal, fn} = module.parent.require("sequelize");
7
+ const {Op, literal, fn, DataTypes} = module.parent.require("sequelize");
8
8
 
9
9
  const getValue = (filter, opt) => {
10
10
 
@@ -756,6 +756,11 @@ const pivotToSequelizeWhere = async (pivot, opt) => {
756
756
  attributes.push([ fn('MAX', literal(`${model.name}.${value.key}`)), `_${value.key}-${value.aggregrate}` ])
757
757
  break
758
758
 
759
+ case 'countDistinct':
760
+ attributes.push([ literal(`COUNT(DISTINCT ${model.name}.${value.key})`), `_${value.key}-${value.aggregrate}` ])
761
+ sortKeyToOrders[`_${value.key}-${value.aggregrate}`] = literal(`COUNT(DISTINCT ${model.name}.${value.key})`)
762
+ break
763
+
759
764
  case 'count':
760
765
  attributes.push([ fn('COUNT', literal(`${model.name}.${value.key}`)), `_${value.key}-${value.aggregrate}` ])
761
766
  sortKeyToOrders[`_${value.key}-${value.aggregrate}`] = fn('COUNT', literal(`${model.name}.${value.key}`))
@@ -780,7 +785,10 @@ const pivotToSequelizeWhere = async (pivot, opt) => {
780
785
 
781
786
  const field = model.rawAttributes[value.key].field
782
787
 
788
+
783
789
  groups.forEach(group => {
790
+
791
+ let groupValue
784
792
  if(group[value.key] === null){
785
793
  attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} is null THEN 1 ELSE 0 END)`), `_${value.key}-(null)` ])
786
794
  }
@@ -788,8 +796,14 @@ const pivotToSequelizeWhere = async (pivot, opt) => {
788
796
  attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = '' THEN 1 ELSE 0 END)`), `_${value.key}-(empty)` ])
789
797
  }
790
798
  else{
791
- const groupValue = (group[value.key] ?? '').toString().replace(/\s/g, '_')
792
- attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = '${group[value.key]}' THEN 1 ELSE 0 END)`), `_${value.key}-${groupValue}` ])
799
+ if(model.rawAttributes[value.key].type instanceof DataTypes.BOOLEAN){
800
+ groupValue = group[value.key]
801
+ attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = ${groupValue === true ? 1 : 0} THEN 1 ELSE 0 END)`), `_${value.key}-${groupValue}` ])
802
+ }
803
+ else{
804
+ groupValue = (group[value.key] ?? '').toString().replace(/\s/g, '_')
805
+ attributes.push([ literal(`SUM(CASE WHEN ${model.name}.${field} = '${group[value.key]}' THEN 1 ELSE 0 END)`), `_${value.key}-${groupValue}` ])
806
+ }
793
807
  }
794
808
  })
795
809
 
@@ -55,8 +55,108 @@ const setupConfig = (config) => {
55
55
  return config
56
56
  }
57
57
 
58
+ const generatePivotColumns = (preset, items) => {
59
+ if(!preset.pivot || !preset.pivot.enabled) return
60
+ if(!Array.isArray(items) && items.length < 1) return
61
+
62
+ if(preset.pivot.manualColumns === true){
63
+ return
64
+ }
65
+
66
+ const tableColumns = (preset.columns ?? [])
67
+ .reduce((cur, obj) => {
68
+ cur[obj.key] = obj
69
+ return cur
70
+ }, {})
71
+
72
+ const currentPivotColumns = [ ...(preset.pivot.columns ?? []) ]
73
+ .reduce((cur, obj) => {
74
+ cur[obj.key] = obj
75
+ return cur
76
+ }, {})
77
+
78
+ const pivotColumns = []
79
+
80
+ for(let row of preset.pivot.rows){
81
+
82
+ let format
83
+ switch(row.aggregrate){
84
+ case 'year':
85
+ format = 'YYYY'
86
+ break
87
+
88
+ case 'month':
89
+ format = 'MMM YYYY'
90
+ break
91
+
92
+ case 'date':
93
+ format = 'D MMM YYYY'
94
+ break
95
+ }
96
+
97
+ if(currentPivotColumns[row.key]){
98
+ Object.assign(currentPivotColumns[row.key], {
99
+ format,
100
+ visible: true
101
+ })
102
+
103
+ pivotColumns.push(currentPivotColumns[row.key])
104
+ }
105
+ else{
106
+ pivotColumns.push({
107
+ ...tableColumns[row.key],
108
+ format,
109
+ visible: true
110
+ })
111
+ }
112
+ }
113
+
114
+ for(let key in items[0]){
115
+ if(key.startsWith('_')){
116
+ let [ k1, ...k2 ] = key.substring(1).split('-')
117
+ k2 = k2.join('-')
118
+
119
+ let label = k2.replace(/_/gi, ' ')
120
+ const column = tableColumns[k1]
121
+ if(column){
122
+ switch(column.type){
123
+ case 'enum':
124
+ label = (column.typeParams ?? []).find(_ => `${_.value}` === `${k2}`)?.text ?? label
125
+ break
126
+ }
127
+ }
128
+
129
+ if(currentPivotColumns[key]){
130
+ Object.assign(currentPivotColumns[key], {
131
+ visible: true
132
+ })
133
+
134
+ pivotColumns.push(currentPivotColumns[key])
135
+ }
136
+ else{
137
+ pivotColumns.push({
138
+ key,
139
+ label,
140
+ label2: (((tableColumns[k1] ?? {}).label ?? '') + ': ' + label).trim(),
141
+ type: 'number',
142
+ })
143
+ }
144
+ }
145
+ }
146
+
147
+ (preset.pivot.columns ?? []).filter(_ => !pivotColumns.find(i => i.key === _.key))
148
+ .forEach(_ => {
149
+ _.visible = false
150
+ pivotColumns.push(_)
151
+ })
152
+
153
+ preset.pivot.columns = pivotColumns
154
+
155
+ }
156
+
58
157
  export {
59
158
  sortsFn,
60
159
  pickColumns,
61
- setupConfig
160
+ setupConfig,
161
+ generatePivotColumns
62
162
  }
@@ -509,7 +509,8 @@
509
509
  </div>
510
510
  <ListItem :items="presetPivot.values"
511
511
  @reorder="(from, to) => { presetPivot.values.splice(to, 0, presetPivot.values.splice(from, 1)[0]); }"
512
- class="mt-2 h-[25vh] overflow-y-auto border-[1px] border-text-200 bg-base-400 rounded-lg p-0.5">
512
+ class="mt-2 h-[25vh] overflow-y-auto border-[1px] border-text-200 bg-base-400 rounded-lg p-0.5"
513
+ container-class="divide-y divide-text-50">
513
514
  <template v-slot="{ item, index }">
514
515
  <div class="flex flex-row items-center gap-3 p-2 bg-base-500 hover:bg-primary-100 first:rounded-t-md last:rounded-b-md">
515
516
  <div data-reorder v-if="(presetPivot.values ?? []).length > 1">
@@ -521,10 +522,11 @@
521
522
  {{ item.label ? item.label : item.key }}
522
523
  </strong>
523
524
  <select v-model="item.aggregrate"
524
- class="px-1 appearance-none bg-base-300 rounded-md border-[1px] border-text-50 outline-none"
525
+ class="px-1 appearance-none bg-base-300 w-[80px] rounded-md border-[1px] border-text-50 outline-none"
525
526
  @change="apply()">
526
527
  <option value="">Default</option>
527
528
  <option value="count">Count</option>
529
+ <option value="countDistinct">Distinct Count</option>
528
530
  <option v-if="[ 'number' ].includes(item.type)" value="sum">Sum</option>
529
531
  <option v-if="[ 'number' ].includes(item.type)" value="avg">Average</option>
530
532
  <option v-if="[ 'number' ].includes(item.type)" value="min">Min</option>
@@ -539,6 +541,33 @@
539
541
  </ListItem>
540
542
  </div>
541
543
 
544
+ <div>
545
+ <div class="flex flex-row items-center gap-2">
546
+ <label class="flex-1">Columns</label>
547
+ <button v-if="presetPivot.manualColumns"
548
+ type="button"
549
+ class="text-primary"
550
+ @click="delete presetPivot.manualColumns; apply()">Reset</button>
551
+ </div>
552
+ <ListItem :items="presetPivot.columns"
553
+ @reorder="(from, to) => { presetPivot.columns.splice(to, 0, presetPivot.columns.splice(from, 1)[0]); presetPivot.manualColumns = true; apply() }"
554
+ class="mt-2 h-[25vh] overflow-y-auto border-[1px] border-text-200 bg-base-400 rounded-lg p-0.5"
555
+ container-class="divide-y divide-text-50">
556
+ <template v-slot="{ item, index }">
557
+ <div class="flex flex-row gap-2 items-center px-2 bg-base-500">
558
+ <div data-reorder>
559
+ <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path 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"/></svg>
560
+ </div>
561
+ <Textbox class="flex-1 border-none" v-model="item.label2" :placeholder="item.label"
562
+ item-class="p-1"/>
563
+ <button type="button" @click="presetPivot.columns.splice(index, 1); presetPivot.manualColumns = true; apply()">
564
+ <svg width="16" height="16" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path 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"/></svg>
565
+ </button>
566
+ </div>
567
+ </template>
568
+ </ListItem>
569
+ </div>
570
+
542
571
  </div>
543
572
 
544
573
  </div>