@mixd-id/web-scaffold 0.1.2301231353 → 0.1.2301231355
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 +1 -1
- package/src/components/ListPage1.vue +145 -36
- package/src/components/VirtualTable.vue +4 -3
- package/src/utils/listpage1.js +151 -3
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<Suspense @resolve="patch">
|
|
3
3
|
<div :class="$style.comp">
|
|
4
4
|
|
|
5
|
-
<div class="flex-1 flex flex-col p-6">
|
|
5
|
+
<div class="flex-1 flex flex-col p-6 relative">
|
|
6
6
|
|
|
7
7
|
<div class="pb-0 flex flex-row gap-3 items-center mb-6">
|
|
8
8
|
<slot v-if="$slots['lp-start']" name="lp-start" :preset="preset"/>
|
|
@@ -43,15 +43,19 @@
|
|
|
43
43
|
</div>
|
|
44
44
|
</div>
|
|
45
45
|
|
|
46
|
-
<div class="flex-1 mb-4 flex flex-col bg-base-500 border-text-50 border-[1px]" v-if="summary">
|
|
47
|
-
<VirtualTable v-if="preset.summary.mode === 'table'" :items="
|
|
48
|
-
|
|
46
|
+
<div class="flex-1 mb-4 flex flex-col bg-base-500 border-text-50 border-[1px]" v-if="summary && !isLoading">
|
|
47
|
+
<VirtualTable v-if="preset.summary.mode === 'table'" :items="summaryItems" :columns="summaryColumns" class="flex-1"></VirtualTable>
|
|
49
48
|
<Bar v-else-if="preset.summary.mode === 'bar'" :data="chartData" :options="chartOptions" class="flex-1 w-full p-2"/>
|
|
50
|
-
|
|
49
|
+
<Line v-else-if="preset.summary.mode === 'line'" :data="chartData" :options="chartOptions" class="flex-1 w-full p-2"/>
|
|
51
50
|
</div>
|
|
52
51
|
|
|
53
|
-
<
|
|
52
|
+
<div v-if="isLoading" :class="$style.loadingComp">
|
|
53
|
+
<svg class="animate-spin aspect-square w-[36px] text-primary" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
|
54
|
+
<label>Memuat...</label>
|
|
55
|
+
</div>
|
|
56
|
+
<VirtualTable v-else-if="!hideDetails" class="flex-1" :columns="presetColumns" :items="items" :state="isLoading ? 2 : 1"
|
|
54
57
|
:appearances="appearances" @scroll-end="loadNext" :pinned="pinned">
|
|
58
|
+
|
|
55
59
|
<template v-for="column in presetColumns" #[colOf(column.key)]="{}">
|
|
56
60
|
<div :class="getHeader(column)" @click="openColumnOptions(column.key, $event.target.closest('.' + $style.header))">
|
|
57
61
|
<div>
|
|
@@ -255,7 +259,18 @@
|
|
|
255
259
|
</div>
|
|
256
260
|
|
|
257
261
|
<div class="p-3">
|
|
258
|
-
<label class="text-text-400 flex-1">
|
|
262
|
+
<label class="text-text-400 flex-1">Type</label>
|
|
263
|
+
<div class="mt-2">
|
|
264
|
+
<Dropdown v-model="preset.summary.mode" class="flex-1" @change="load">
|
|
265
|
+
<option value="table">{{ $t('Table') }}</option>
|
|
266
|
+
<option value="bar">{{ $t('Bar Chart') }}</option>
|
|
267
|
+
<option value="line">{{ $t('Line Chart') }}</option>
|
|
268
|
+
</Dropdown>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
|
|
272
|
+
<div class="p-3">
|
|
273
|
+
<label class="text-text-400 flex-1">{{ preset.summary.mode === 'table' ? $t('Row') : $t('X-axis') }}</label>
|
|
259
274
|
<div class="flex flex-row mt-2 gap-2">
|
|
260
275
|
<Dropdown v-model="preset.summary.rows[0].key" class="flex-1" @change="load">
|
|
261
276
|
<option value="" disabled selected>{{ $t('Add Column') }}</option>
|
|
@@ -264,15 +279,21 @@
|
|
|
264
279
|
<Dropdown v-model="preset.summary.rows[0].format" class="w-[100px]" @change="load">
|
|
265
280
|
<option value="">{{ $t('Default') }}</option>
|
|
266
281
|
<option value="date">{{ $t('Date') }}</option>
|
|
282
|
+
<option value="month">{{ $t('Month') }}</option>
|
|
283
|
+
<option value="year">{{ $t('Year') }}</option>
|
|
267
284
|
</Dropdown>
|
|
268
285
|
</div>
|
|
286
|
+
<Checkbox class="mt-2" v-if="preset.summary.mode === 'table'" v-model="preset.summary.showRowTotal">
|
|
287
|
+
Row Total
|
|
288
|
+
</Checkbox>
|
|
269
289
|
</div>
|
|
270
290
|
|
|
271
291
|
<div class="p-3">
|
|
272
|
-
<label class="text-text-400 flex-1">Column</label>
|
|
292
|
+
<label class="text-text-400 flex-1">{{ preset.summary.mode === 'table' ? $t('Column') : $t('Dimension') }}</label>
|
|
273
293
|
<div class="flex flex-row mt-2 gap-2">
|
|
274
294
|
<Dropdown v-model="preset.summary.columns[0].key" class="flex-1" @change="load">
|
|
275
295
|
<option value="" disabled selected>{{ $t('Add Column') }}</option>
|
|
296
|
+
<option value="(none)">{{ $t('None') }}</option>
|
|
276
297
|
<option v-for="column in filterableColumns" :value="column.key">{{ column.label }}</option>
|
|
277
298
|
</Dropdown>
|
|
278
299
|
<Dropdown v-model="preset.summary.columns[0].format" class="w-[100px]" @change="load">
|
|
@@ -280,28 +301,23 @@
|
|
|
280
301
|
<option value="date">{{ $t('Date') }}</option>
|
|
281
302
|
</Dropdown>
|
|
282
303
|
</div>
|
|
304
|
+
<Checkbox class="mt-2" v-if="preset.summary.mode === 'table'" v-model="preset.summary.showColumnTotal">
|
|
305
|
+
Column Total
|
|
306
|
+
</Checkbox>
|
|
307
|
+
<Checkbox class="mt-2" v-else-if="preset.summary.mode === 'bar'" v-model="preset.summary.stacked">
|
|
308
|
+
Stacked
|
|
309
|
+
</Checkbox>
|
|
283
310
|
</div>
|
|
284
311
|
|
|
285
312
|
<div class="p-3">
|
|
286
313
|
<label class="text-text-400 flex-1">Values</label>
|
|
287
314
|
<div class="flex flex-row mt-2 gap-2">
|
|
288
|
-
<Dropdown v-model="preset.summary.values[0].
|
|
289
|
-
<option value="" disabled selected>{{ $t('
|
|
290
|
-
<option v-for="column in filterableColumns" :value="column.key">{{ column.label }}</option>
|
|
291
|
-
</Dropdown>
|
|
292
|
-
<Dropdown v-model="preset.summary.values[0].aggregrate" class="w-[100px]" @change="load">
|
|
293
|
-
<option value="">{{ $t('Default') }}</option>
|
|
315
|
+
<Dropdown v-model="preset.summary.values[0].aggregrate" class="flex-1" @change="load">
|
|
316
|
+
<option value="" disabled selected>{{ $t('Select') }}</option>
|
|
294
317
|
<option value="count">{{ $t('Count') }}</option>
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
<div class="p-3">
|
|
300
|
-
<label class="text-text-400 flex-1">Type</label>
|
|
301
|
-
<div class="mt-2">
|
|
302
|
-
<Dropdown v-model="preset.summary.mode" class="flex-1" @change="load">
|
|
303
|
-
<option value="table">{{ $t('Table') }}</option>
|
|
304
|
-
<option value="bar">{{ $t('Bar Chart') }}</option>
|
|
318
|
+
<option value="max">{{ $t('Max') }}</option>
|
|
319
|
+
<option value="min">{{ $t('Min') }}</option>
|
|
320
|
+
<option value="avg">{{ $t('Avg') }}</option>
|
|
305
321
|
</Dropdown>
|
|
306
322
|
</div>
|
|
307
323
|
</div>
|
|
@@ -310,8 +326,6 @@
|
|
|
310
326
|
|
|
311
327
|
</div>
|
|
312
328
|
|
|
313
|
-
<div class="px-6 py-3 flex flex-row gap-2"></div>
|
|
314
|
-
|
|
315
329
|
</div>
|
|
316
330
|
|
|
317
331
|
</div>
|
|
@@ -325,14 +339,13 @@
|
|
|
325
339
|
|
|
326
340
|
import throttle from "lodash/throttle";
|
|
327
341
|
import {urlQuery} from "../utils/helpers.mjs";
|
|
328
|
-
import { Bar } from 'vue-chartjs'
|
|
329
|
-
import
|
|
330
|
-
|
|
331
|
-
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
|
|
342
|
+
import { Bar, Line } from 'vue-chartjs'
|
|
343
|
+
import Chart from 'chart.js/auto'
|
|
344
|
+
import dayjs from "dayjs";
|
|
332
345
|
|
|
333
346
|
export default{
|
|
334
347
|
|
|
335
|
-
components: { Bar },
|
|
348
|
+
components: { Bar, Line },
|
|
336
349
|
|
|
337
350
|
inject: [ 'socket', 'confirm', 'alert', 'socketEmit', 'toast' ],
|
|
338
351
|
|
|
@@ -421,6 +434,19 @@ export default{
|
|
|
421
434
|
|
|
422
435
|
var style = getComputedStyle(document.body)
|
|
423
436
|
var gridColor = style.getPropertyValue('--text-50')
|
|
437
|
+
var gridColor2 = style.getPropertyValue('--text-200')
|
|
438
|
+
|
|
439
|
+
const baseColumn = this.summary.columns[0]
|
|
440
|
+
const baseColumnType = baseColumn.type
|
|
441
|
+
|
|
442
|
+
let highGrids = []
|
|
443
|
+
if(baseColumnType === 'date'){
|
|
444
|
+
this.summary.items.forEach((item) => {
|
|
445
|
+
if(dayjs(item.dfDate).day() === 1){
|
|
446
|
+
highGrids.push(dayjs(item.dfDate).format('D MMM'))
|
|
447
|
+
}
|
|
448
|
+
})
|
|
449
|
+
}
|
|
424
450
|
|
|
425
451
|
return {
|
|
426
452
|
responsive: true,
|
|
@@ -431,12 +457,20 @@ export default{
|
|
|
431
457
|
scales: {
|
|
432
458
|
x: {
|
|
433
459
|
grid: {
|
|
434
|
-
color:
|
|
435
|
-
|
|
460
|
+
color: function(context){
|
|
461
|
+
if(baseColumnType === 'date' && context.tick && highGrids.includes(context.tick.label)){
|
|
462
|
+
return `rgb(${gridColor2})`
|
|
463
|
+
}
|
|
464
|
+
return `rgb(${gridColor})`
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
stacked: this.preset.summary.stacked
|
|
436
468
|
},
|
|
437
469
|
y: {
|
|
438
470
|
grid: {
|
|
439
|
-
color:
|
|
471
|
+
color: function(context){
|
|
472
|
+
return `rgb(${gridColor})`
|
|
473
|
+
}
|
|
440
474
|
}
|
|
441
475
|
}
|
|
442
476
|
}
|
|
@@ -447,9 +481,21 @@ export default{
|
|
|
447
481
|
|
|
448
482
|
//console.log(this.summary)
|
|
449
483
|
|
|
484
|
+
const column = this.summary.columns.filter((_) => _.key === 'dfDate').pop()
|
|
485
|
+
|
|
450
486
|
const labels = []
|
|
451
487
|
this.summary.items.forEach((item) => {
|
|
452
|
-
|
|
488
|
+
|
|
489
|
+
let label = item.dfDate
|
|
490
|
+
switch(column.type){
|
|
491
|
+
|
|
492
|
+
case 'date':
|
|
493
|
+
const dateFormat = column.format ?? 'D MMM YY HH:mm:ss'
|
|
494
|
+
const djs = dayjs(item.dfDate)
|
|
495
|
+
label = djs.isValid() ? djs.format(dateFormat) : item.dfDate
|
|
496
|
+
break
|
|
497
|
+
}
|
|
498
|
+
labels.push(label)
|
|
453
499
|
})
|
|
454
500
|
|
|
455
501
|
const datasets = []
|
|
@@ -489,6 +535,52 @@ export default{
|
|
|
489
535
|
if(this.preset && this.preset.summary && this.preset.summary.hideDetails)
|
|
490
536
|
return this.preset.summary.hideDetails
|
|
491
537
|
return false;
|
|
538
|
+
},
|
|
539
|
+
|
|
540
|
+
summaryColumns(){
|
|
541
|
+
|
|
542
|
+
const columns = [ ...this.summary.columns ]
|
|
543
|
+
|
|
544
|
+
if(this.preset.summary.showColumnTotal){
|
|
545
|
+
columns.push({ key:"_total", label:"Total", visible:true, type:"number" })
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
return columns
|
|
549
|
+
},
|
|
550
|
+
|
|
551
|
+
summaryItems(){
|
|
552
|
+
|
|
553
|
+
const items = [ ...this.summary.items ]
|
|
554
|
+
|
|
555
|
+
//console.log('#1', this.preset.summary.showColumnTotal, this.preset.summary.showRowTotal, items.length)
|
|
556
|
+
|
|
557
|
+
if(this.preset.summary.showColumnTotal){
|
|
558
|
+
items.forEach((item) => {
|
|
559
|
+
let total = 0
|
|
560
|
+
for(let key in item){
|
|
561
|
+
if([ 'dfDate', '_total' ].includes(key)) continue
|
|
562
|
+
total += parseInt(item[key])
|
|
563
|
+
}
|
|
564
|
+
item._total = total
|
|
565
|
+
})
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
if(this.preset.summary.showRowTotal){
|
|
569
|
+
const totalItem = { dfDate:"Total" }
|
|
570
|
+
this.summary.items.forEach((item) => {
|
|
571
|
+
|
|
572
|
+
for(let key in item){
|
|
573
|
+
if([ 'dfDate' ].includes(key)) continue
|
|
574
|
+
|
|
575
|
+
if(!(key in totalItem))
|
|
576
|
+
totalItem[key] = 0
|
|
577
|
+
totalItem[key] += parseInt(item[key])
|
|
578
|
+
}
|
|
579
|
+
})
|
|
580
|
+
items.push(totalItem)
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
return items
|
|
492
584
|
}
|
|
493
585
|
|
|
494
586
|
},
|
|
@@ -512,6 +604,7 @@ export default{
|
|
|
512
604
|
{ text:'Sorts', value:'sort' },
|
|
513
605
|
{ text:'Summary', value:'summary' },
|
|
514
606
|
],
|
|
607
|
+
isLoading: false,
|
|
515
608
|
name: null,
|
|
516
609
|
columns: [],
|
|
517
610
|
selectedColumn: null,
|
|
@@ -542,6 +635,7 @@ export default{
|
|
|
542
635
|
|
|
543
636
|
patch(){
|
|
544
637
|
|
|
638
|
+
this.isLoading = true
|
|
545
639
|
this.socketEmit(`${this.computedDataSource}.patch`, {
|
|
546
640
|
...(urlQuery().reset ? { reset:1 } : {})
|
|
547
641
|
}, (res) => {
|
|
@@ -557,10 +651,14 @@ export default{
|
|
|
557
651
|
this.summary = data.summary
|
|
558
652
|
this.hasNext = data.hasNext
|
|
559
653
|
this.count = data.count
|
|
654
|
+
this.isLoading = false
|
|
560
655
|
})
|
|
561
656
|
|
|
562
657
|
if(this.name)
|
|
563
658
|
this.socketEmit(this.name + '.subscribe', { name:this.name })
|
|
659
|
+
}, (err) => {
|
|
660
|
+
this.isLoading = false
|
|
661
|
+
this.toast(err)
|
|
564
662
|
})
|
|
565
663
|
},
|
|
566
664
|
|
|
@@ -604,6 +702,7 @@ export default{
|
|
|
604
702
|
},
|
|
605
703
|
|
|
606
704
|
load(){
|
|
705
|
+
this.isLoading = true
|
|
607
706
|
this.socketEmit(`${this.computedDataSource}.load`, {
|
|
608
707
|
preset: this.preset
|
|
609
708
|
}, (res) => {
|
|
@@ -612,6 +711,10 @@ export default{
|
|
|
612
711
|
this.summary = data.summary
|
|
613
712
|
this.hasNext = data.hasNext
|
|
614
713
|
this.count = data.count
|
|
714
|
+
this.isLoading = false
|
|
715
|
+
}, (err) => {
|
|
716
|
+
this.isLoading = false
|
|
717
|
+
this.toast(err)
|
|
615
718
|
})
|
|
616
719
|
},
|
|
617
720
|
|
|
@@ -843,7 +946,7 @@ export default{
|
|
|
843
946
|
<style module>
|
|
844
947
|
|
|
845
948
|
.comp{
|
|
846
|
-
@apply flex-1 flex flex-row;
|
|
949
|
+
@apply flex-1 flex flex-row relative;
|
|
847
950
|
}
|
|
848
951
|
|
|
849
952
|
.header{
|
|
@@ -861,4 +964,10 @@ export default{
|
|
|
861
964
|
@apply hover:bg-primary hover:text-white;
|
|
862
965
|
}
|
|
863
966
|
|
|
967
|
+
.loadingComp{
|
|
968
|
+
@apply absolute left-0 top-0 right-0 bottom-0;
|
|
969
|
+
@apply flex flex-col gap-4 items-center justify-center;
|
|
970
|
+
background: rgba(0, 0, 0, .3);
|
|
971
|
+
}
|
|
972
|
+
|
|
864
973
|
</style>
|
|
@@ -331,12 +331,13 @@ export default{
|
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
let text = value
|
|
334
|
+
let dateFormat, val
|
|
334
335
|
switch(column.type){
|
|
335
336
|
|
|
336
337
|
case 'date':
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
text = val.isValid() ? val.format(dateFormat) :
|
|
338
|
+
dateFormat = column.format ?? 'D MMM YY HH:mm:ss'
|
|
339
|
+
val = dayjs(value)
|
|
340
|
+
text = val.isValid() ? val.format(dateFormat) : value
|
|
340
341
|
break
|
|
341
342
|
|
|
342
343
|
case 'currency':
|
package/src/utils/listpage1.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { Op } = module.parent.require('sequelize')
|
|
2
2
|
const Sequelize = module.parent.require('sequelize')
|
|
3
3
|
const dayjs = require("dayjs");
|
|
4
|
-
const util = require("util");
|
|
5
4
|
|
|
6
5
|
let ListPage1 = {
|
|
7
6
|
|
|
@@ -107,11 +106,12 @@ let ListPage1 = {
|
|
|
107
106
|
}
|
|
108
107
|
|
|
109
108
|
if(preset.search){
|
|
109
|
+
const tableName = this.model.tableName
|
|
110
110
|
where = {
|
|
111
111
|
...where,
|
|
112
|
-
[Op.and]: Sequelize.literal(
|
|
112
|
+
[Op.and]: Sequelize.literal(`MATCH(\`${tableName}\`.tag) AGAINST (? IN BOOLEAN MODE)`)
|
|
113
113
|
}
|
|
114
|
-
replacements.push(
|
|
114
|
+
replacements.push(preset.search)
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
if(afterItem){
|
|
@@ -164,6 +164,154 @@ let ListPage1 = {
|
|
|
164
164
|
}
|
|
165
165
|
},
|
|
166
166
|
|
|
167
|
+
async loadSummary(preset, modelParams){
|
|
168
|
+
|
|
169
|
+
const { columns, rows, values } = preset.summary
|
|
170
|
+
|
|
171
|
+
if(!Array.isArray(columns) || columns.length !== 1) return
|
|
172
|
+
if(!Array.isArray(rows) || rows.length !== 1) return
|
|
173
|
+
if(!Array.isArray(values) || values.length !== 1) return
|
|
174
|
+
|
|
175
|
+
const col = columns[0]
|
|
176
|
+
let columnValues = []
|
|
177
|
+
let colKey
|
|
178
|
+
if(col.key !== '(none)'){
|
|
179
|
+
colKey = this.model.rawAttributes[col.key].field
|
|
180
|
+
columnValues = await this.model.findAll({
|
|
181
|
+
attributes: [
|
|
182
|
+
[ Sequelize.fn("DISTINCT", Sequelize.col(colKey)), 'cols' ]
|
|
183
|
+
],
|
|
184
|
+
order: [
|
|
185
|
+
[ colKey, 'asc' ]
|
|
186
|
+
],
|
|
187
|
+
...modelParams
|
|
188
|
+
})
|
|
189
|
+
//console.log(columnValues)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const attributes = []
|
|
193
|
+
const group = []
|
|
194
|
+
const summaryColumns = [
|
|
195
|
+
/*{ key:"dfDate", label:"Date", width:"200px", visible:true },
|
|
196
|
+
{ key:"type-1", label:"Type 1", type:"number", visible:true },
|
|
197
|
+
{ key:"type-2", label:"Type 2", type:"number", visible:true },
|
|
198
|
+
{ key:"type-3", label:"Type 3", type:"number", visible:true },
|
|
199
|
+
{ key:"type-4", label:"Type 4", type:"number", visible:true },
|
|
200
|
+
{ key:"type-8", label:"Type 8", type:"number", visible:true },*/
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
const row = rows[0]
|
|
204
|
+
const rowKey = this.model.rawAttributes[row.key].field
|
|
205
|
+
const rowLabel = this.columns[row.key].label
|
|
206
|
+
switch(row.format){
|
|
207
|
+
case 'date':
|
|
208
|
+
attributes.push([Sequelize.fn("DATE_FORMAT", Sequelize.col(rowKey), '%Y-%m-%d'), "dfDate"])
|
|
209
|
+
group.push([Sequelize.fn("DATE_FORMAT", Sequelize.col(rowKey), '%Y-%m-%d'), "dfDate"])
|
|
210
|
+
summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true, type:"date", format:"D MMM" })
|
|
211
|
+
break
|
|
212
|
+
|
|
213
|
+
case 'month':
|
|
214
|
+
attributes.push([Sequelize.fn("DATE_FORMAT", Sequelize.col(rowKey), '%Y-%m'), "dfDate"])
|
|
215
|
+
group.push([Sequelize.fn("DATE_FORMAT", Sequelize.col(rowKey), '%Y-%m'), "dfDate"])
|
|
216
|
+
summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true, type:"date", format:"MMM YYYY" })
|
|
217
|
+
break
|
|
218
|
+
|
|
219
|
+
case 'year':
|
|
220
|
+
attributes.push([Sequelize.fn("DATE_FORMAT", Sequelize.col(rowKey), '%Y'), "dfDate"])
|
|
221
|
+
group.push([Sequelize.fn("DATE_FORMAT", Sequelize.col(rowKey), '%Y'), "dfDate"])
|
|
222
|
+
summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true, type:"date", format:"YYYY" })
|
|
223
|
+
break
|
|
224
|
+
|
|
225
|
+
default:
|
|
226
|
+
attributes.push([Sequelize.col(rowKey), "dfDate"])
|
|
227
|
+
group.push([Sequelize.col(rowKey), "dfDate"])
|
|
228
|
+
summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true })
|
|
229
|
+
break
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const value = values[0]
|
|
233
|
+
if(columnValues.length > 0){
|
|
234
|
+
columnValues.forEach((obj) => {
|
|
235
|
+
const columnValue = obj.dataValues['cols']
|
|
236
|
+
|
|
237
|
+
switch(value.aggregrate){
|
|
238
|
+
case 'count':
|
|
239
|
+
attributes.push([Sequelize.fn("SUM", Sequelize.fn("IF", Sequelize.literal(`${colKey} = '${columnValue}'`), 1, 0)), colKey + "-" + columnValue])
|
|
240
|
+
summaryColumns.push({ key:colKey + "-" + columnValue, label:(columnValue ?? '').toString(), visible:true, aggregrate:"count" })
|
|
241
|
+
break
|
|
242
|
+
|
|
243
|
+
case 'min':
|
|
244
|
+
attributes.push([Sequelize.fn("MIN", colKey), colKey + "-" + columnValue])
|
|
245
|
+
summaryColumns.push({ key:colKey + "-" + columnValue, label:(columnValue ?? '').toString(), visible:true, aggregrate:"count" })
|
|
246
|
+
break
|
|
247
|
+
|
|
248
|
+
case 'max':
|
|
249
|
+
attributes.push([Sequelize.fn("MAX", colKey), colKey + "-" + columnValue])
|
|
250
|
+
summaryColumns.push({ key:colKey + "-" + columnValue, label:(columnValue ?? '').toString(), visible:true, aggregrate:"count" })
|
|
251
|
+
break
|
|
252
|
+
|
|
253
|
+
case 'avg':
|
|
254
|
+
attributes.push([Sequelize.fn("AVG", colKey), colKey + "-" + columnValue])
|
|
255
|
+
summaryColumns.push({ key:colKey + "-" + columnValue, label:(columnValue ?? '').toString(), visible:true, aggregrate:"count" })
|
|
256
|
+
break
|
|
257
|
+
}
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
else{
|
|
261
|
+
switch(value.aggregrate) {
|
|
262
|
+
case 'count':
|
|
263
|
+
default:
|
|
264
|
+
attributes.push([Sequelize.fn('count', '*'), 'Count'])
|
|
265
|
+
summaryColumns.push({ key:'Count', label:'Count', type:"number", visible:true, aggregrate:"count" })
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
//console.log(attributes)
|
|
270
|
+
|
|
271
|
+
const summaryItems = await this.model.findAll({
|
|
272
|
+
attributes,
|
|
273
|
+
group,
|
|
274
|
+
order: [
|
|
275
|
+
[ 'dfDate', 'asc' ]
|
|
276
|
+
],
|
|
277
|
+
...modelParams
|
|
278
|
+
})
|
|
279
|
+
/*const summaryItems = await this.model.findAll({
|
|
280
|
+
attributes: [
|
|
281
|
+
[Sequelize.fn("DATE_FORMAT", Sequelize.col("created_at"), '%Y-%m-%d'), "dfDate"],
|
|
282
|
+
[Sequelize.fn("SUM", Sequelize.fn("IF", Sequelize.literal("type = 1"), 1, 0)), "type-1"],
|
|
283
|
+
[Sequelize.literal("SUM(IF(type = 2, 1, 0))"), "type-2"],
|
|
284
|
+
[Sequelize.literal("SUM(IF(type = 3, 1, 0))"), "type-3"],
|
|
285
|
+
[Sequelize.literal("SUM(IF(type = 4, 1, 0))"), "type-4"],
|
|
286
|
+
[Sequelize.literal("SUM(IF(type = 8, 1, 0))"), "type-8"],
|
|
287
|
+
],
|
|
288
|
+
group: [
|
|
289
|
+
[Sequelize.fn("DATE_FORMAT", Sequelize.col("created_at"), '%Y-%m-%d')]
|
|
290
|
+
],
|
|
291
|
+
order: [
|
|
292
|
+
[ 'dfDate', 'asc' ]
|
|
293
|
+
],
|
|
294
|
+
...modelParams
|
|
295
|
+
})*/
|
|
296
|
+
//console.log(summaryItems)
|
|
297
|
+
|
|
298
|
+
const summary = {
|
|
299
|
+
type: "table",
|
|
300
|
+
columns: summaryColumns,
|
|
301
|
+
items: summaryItems
|
|
302
|
+
/*items: [
|
|
303
|
+
{ date:"21 Jan 23", "type-1":12, "type-2":11, "type-3":16, "type-4":2, "type-8":8 },
|
|
304
|
+
{ date:"22 Jan 23", "type-1":51, "type-2":87, "type-3":86, "type-4":3, "type-8":9 },
|
|
305
|
+
{ date:"23 Jan 23", "type-1":14, "type-2":66, "type-3":77, "type-4":4, "type-8":18 },
|
|
306
|
+
{ date:"24 Jan 23", "type-1":7, "type-2":3, "type-3":63, "type-4":5, "type-8":28 },
|
|
307
|
+
{ date:"25 Jan 23", "type-1":88, "type-2":55, "type-3":68, "type-4":6, "type-8":38 },
|
|
308
|
+
{ date:"26 Jan 23", "type-1":172, "type-2":13, "type-3":6, "type-4":7, "type-8":48 }
|
|
309
|
+
]*/
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return summary
|
|
313
|
+
},
|
|
314
|
+
|
|
167
315
|
async subscribe(params, socket){
|
|
168
316
|
const { name } = params
|
|
169
317
|
if(name){
|