@mixd-id/web-scaffold 0.1.230406289 → 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
package/src/components/List.vue
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
|
573
|
+
key,
|
|
659
574
|
value: [{
|
|
660
575
|
operator: '=',
|
|
661
|
-
value
|
|
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
|
|
598
|
+
key,
|
|
672
599
|
value: [{
|
|
673
600
|
operator: '=',
|
|
674
|
-
value
|
|
601
|
+
value
|
|
675
602
|
}]
|
|
676
603
|
})
|
|
677
604
|
}
|
|
@@ -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
|
|
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
|
-
|
|
792
|
-
|
|
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>
|