@mixd-id/web-scaffold 0.1.2301231365 → 0.1.2301231367

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.2301231365",
4
+ "version": "0.1.2301231367",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -20,6 +20,7 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@faker-js/faker": "^7.3.0",
23
+ "@googlemaps/js-api-loader": "^1.15.1",
23
24
  "@tailwindcss/line-clamp": "^0.4.0",
24
25
  "@vueuse/core": "^9.0.2",
25
26
  "adm-zip": "^0.5.10",
@@ -1,6 +1,8 @@
1
1
  <template>
2
2
  <button :class="computedClass" :disabled="isDisabled">
3
- <slot></slot>
3
+ <div>
4
+ <slot></slot>
5
+ </div>
4
6
  <div v-if="isLoading" :class="$style.loadingPane">
5
7
  <svg :class="$style.spinner" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
6
8
  <circle :class="$style.svgBg" cx="12" cy="12" r="10" stroke-width="4"></circle>
@@ -31,7 +33,10 @@ export default{
31
33
  default: '' // 0|1|2|3, default: 2
32
34
  },
33
35
 
34
- state: [ String, Number ], // -1:disabled, 1:normal, 2:loading, default: normal
36
+ state: {
37
+ type: [ String, Number ],
38
+ default: 1
39
+ }, // -1:disabled, 1:normal, 2:loading, default: normal
35
40
 
36
41
  },
37
42
 
@@ -50,11 +55,7 @@ export default{
50
55
  },
51
56
 
52
57
  isDisabled(){
53
- return parseInt(this.computedState) === -1
54
- },
55
-
56
- isNormal(){
57
- return parseInt(this.computedState) !== 2
58
+ return parseInt(this.computedState) !== 1
58
59
  },
59
60
 
60
61
  isLoading(){
@@ -227,6 +228,12 @@ export default{
227
228
  .loading:active{
228
229
  @apply top-0 left-0;
229
230
  }
231
+ .loading>*{
232
+ opacity: 0;
233
+ }
234
+ .loading .loadingPane{
235
+ opacity: 1;
236
+ }
230
237
 
231
238
  .spacing-,
232
239
  .spacing-2{
@@ -0,0 +1,119 @@
1
+ <template>
2
+ <div :class="$style.comp">
3
+ <div ref="map" class="flex-1"></div>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+
9
+ import { Loader } from '@googlemaps/js-api-loader';
10
+
11
+ export default{
12
+
13
+ props: {
14
+ data: Array,
15
+ radius: Number
16
+ },
17
+
18
+ data(){
19
+ return {
20
+ map: null
21
+ }
22
+ },
23
+
24
+ mounted() {
25
+ this.load()
26
+ },
27
+
28
+ methods: {
29
+
30
+ load(){
31
+
32
+ if(!Array.isArray(this.data) || this.data.length < 1)
33
+ return
34
+
35
+ const loader = new Loader({
36
+ apiKey: "AIzaSyBmzMlmrR5St-njtN--64y_oLTa9FDLYfQ"
37
+ })
38
+
39
+ loader.load()
40
+ .then(async () => {
41
+ const { Map } = await google.maps.importLibrary([ "maps" ]);
42
+ await google.maps.importLibrary("visualization", ["HeatmapLayer"]);
43
+
44
+ var center = new google.maps.LatLng(-6.2088, 106.8456);
45
+
46
+ this.map = new Map(this.$refs.map, {
47
+ center: center,
48
+ zoom: 7,
49
+ mapTypeId: 'roadmap',
50
+ streetViewControl: false
51
+ });
52
+
53
+ var heatMapData = [
54
+ /*{location: new google.maps.LatLng(37.782, -122.447), weight: 0.5},
55
+ new google.maps.LatLng(37.782, -122.445),
56
+ {location: new google.maps.LatLng(37.782, -122.443), weight: 2},
57
+ {location: new google.maps.LatLng(37.782, -122.441), weight: 3},
58
+ {location: new google.maps.LatLng(37.782, -122.439), weight: 2},
59
+ new google.maps.LatLng(37.782, -122.437),
60
+ {location: new google.maps.LatLng(37.782, -122.435), weight: 0.5},
61
+
62
+ {location: new google.maps.LatLng(37.785, -122.447), weight: 3},
63
+ {location: new google.maps.LatLng(37.785, -122.445), weight: 2},
64
+ new google.maps.LatLng(37.785, -122.443),
65
+ {location: new google.maps.LatLng(37.785, -122.441), weight: 0.5},
66
+ new google.maps.LatLng(37.785, -122.439),
67
+ {location: new google.maps.LatLng(37.785, -122.437), weight: 2},
68
+ {location: new google.maps.LatLng(37.785, -122.435), weight: 3}*/
69
+ ];
70
+
71
+ this.data.forEach((item) => {
72
+ heatMapData.push({
73
+ location: new google.maps.LatLng(item[0], item[1]),
74
+ weight: item[2]
75
+ })
76
+ })
77
+
78
+ var heatmap = new google.maps.visualization.HeatmapLayer({
79
+ data: heatMapData,
80
+ dissipating: true
81
+ });
82
+ heatmap.set('radius', this.radius ?? 12)
83
+ heatmap.setMap(this.map);
84
+
85
+ const gradient = [
86
+ "rgba(0, 255, 255, 0)",
87
+ "rgba(0, 255, 255, 1)",
88
+ "rgba(0, 191, 255, 1)",
89
+ "rgba(0, 127, 255, 1)",
90
+ "rgba(0, 63, 255, 1)",
91
+ "rgba(0, 0, 255, 1)",
92
+ "rgba(0, 0, 223, 1)",
93
+ "rgba(0, 0, 191, 1)",
94
+ "rgba(0, 0, 159, 1)",
95
+ "rgba(0, 0, 127, 1)",
96
+ "rgba(63, 0, 91, 1)",
97
+ "rgba(127, 0, 63, 1)",
98
+ "rgba(191, 0, 31, 1)",
99
+ "rgba(255, 0, 0, 1)",
100
+ ];
101
+ heatmap.set("gradient", gradient);
102
+
103
+ console.log('Gmap, data count:', this.data.length)
104
+ });
105
+ }
106
+
107
+ }
108
+
109
+ }
110
+
111
+ </script>
112
+
113
+ <style module>
114
+
115
+ .comp{
116
+ @apply flex-1 flex flex-col;
117
+ }
118
+
119
+ </style>
@@ -47,6 +47,7 @@
47
47
  <VirtualTable v-if="preset.summary.mode === 'table'" :items="summaryItems" :columns="summaryColumns" class="flex-1"></VirtualTable>
48
48
  <Bar v-else-if="preset.summary.mode === 'bar'" :data="chartData" :options="chartOptions" class="flex-1 w-full p-2"/>
49
49
  <Line v-else-if="preset.summary.mode === 'line'" :data="chartData" :options="chartOptions" class="flex-1 w-full p-2"/>
50
+ <Gmaps v-else-if="preset.summary.mode === 'map'" :data="summary.items" :radius="preset.summary.mapRadius" class="flex-1 w-full p-2" />
50
51
  </div>
51
52
 
52
53
  <div v-if="isLoading" :class="$style.loadingComp">
@@ -270,11 +271,12 @@
270
271
  <option value="table">{{ $t('Table') }}</option>
271
272
  <option value="bar">{{ $t('Bar Chart') }}</option>
272
273
  <option value="line">{{ $t('Line Chart') }}</option>
274
+ <option value="map">{{ $t('Maps') }}</option>
273
275
  </Dropdown>
274
276
  </div>
275
277
  </div>
276
278
 
277
- <div class="p-3">
279
+ <div class="p-3" v-if="[ 'table', 'bar', 'line' ].includes(preset.summary.type)">
278
280
  <label class="text-text-400 flex-1">{{ preset.summary.mode === 'table' ? $t('Row') : $t('X-axis') }}</label>
279
281
  <div class="flex flex-row mt-2 gap-2">
280
282
  <Dropdown v-model="preset.summary.rows[0].key" class="flex-1" @change="load">
@@ -295,18 +297,26 @@
295
297
  </div>
296
298
 
297
299
  <div class="p-3">
298
- <label class="text-text-400 flex-1">{{ preset.summary.mode === 'table' ? $t('Column') : $t('Dimension') }}</label>
299
- <div class="flex flex-row mt-2 gap-2">
300
+ <label class="text-text-400 flex-1" v-if="preset.summary.mode === 'table'">{{$t('Column') }}</label>
301
+ <label class="text-text-400 flex-1" v-else-if="[ 'bar', 'line' ].includes(preset.summary.mode)">{{$t('Column') }}</label>
302
+ <label class="text-text-400 flex-1" v-else-if="[ 'map' ].includes(preset.summary.mode)">{{$t('Property') }}</label>
303
+ <div class="flex flex-row mt-2 gap-2" v-if="[ 'bar', 'line', 'table' ].includes(preset.summary.mode)">
300
304
  <Dropdown v-model="preset.summary.columns[0].key" class="flex-1" @change="load">
301
305
  <option value="" disabled selected>{{ $t('Add Column') }}</option>
302
306
  <option value="(none)">{{ $t('None') }}</option>
303
307
  <option v-for="column in filterableColumns" :value="column.key">{{ column.label }}</option>
304
308
  </Dropdown>
305
- <Dropdown v-model="preset.summary.columns[0].format" class="w-[100px]" @change="load">
309
+ <Dropdown v-if="preset.summary.mode !== 'map'" v-model="preset.summary.columns[0].format" class="w-[100px]" @change="load">
306
310
  <option value="">{{ $t('Default') }}</option>
307
311
  <option value="date">{{ $t('Date') }}</option>
308
312
  </Dropdown>
309
313
  </div>
314
+ <div v-else>
315
+ <Dropdown v-model="preset.summary.columns[0].key" class="flex-1" @change="load">
316
+ <option value="" disabled selected>{{ $t('Add Column') }}</option>
317
+ <option v-for="column in coordinateColumns" :value="column.key">{{ column.label }}</option>
318
+ </Dropdown>
319
+ </div>
310
320
  <Checkbox class="mt-2" v-if="preset.summary.mode === 'table'" v-model="preset.summary.showColumnTotal">
311
321
  Column Total
312
322
  </Checkbox>
@@ -315,7 +325,7 @@
315
325
  </Checkbox>
316
326
  </div>
317
327
 
318
- <div class="p-3">
328
+ <div class="p-3" v-if="preset.summary.mode !== 'map'">
319
329
  <label class="text-text-400 flex-1">Values</label>
320
330
  <div class="flex flex-row mt-2 gap-2">
321
331
  <Dropdown v-model="preset.summary.values[0].aggregrate" class="flex-1" @change="load">
@@ -328,6 +338,13 @@
328
338
  </div>
329
339
  </div>
330
340
 
341
+ <div class="p-3" v-if="preset.summary.mode === 'map'">
342
+ <label class="text-text-400 flex-1">Radius</label>
343
+ <div class="flex flex-row mt-2 gap-2">
344
+ <Textbox v-model="preset.summary.mapRadius" class="w-[60px]" @blur="load" @keyup.enter="load" />
345
+ </div>
346
+ </div>
347
+
331
348
  </div>
332
349
 
333
350
  </div>
@@ -399,6 +416,10 @@ export default{
399
416
  return Object.values(this.columns).filter((_) => _.filterable)
400
417
  },
401
418
 
419
+ coordinateColumns(){
420
+ return Object.values(this.columns).filter((_) => _.type === 'coord')
421
+ },
422
+
402
423
  sortableColumns(){
403
424
  return Object.values(this.columns).filter((_) => _.sortable)
404
425
  },
@@ -537,7 +558,7 @@ export default{
537
558
  })
538
559
 
539
560
  const dataset = {
540
- label: column.key,
561
+ label: column.label,
541
562
  data,
542
563
  backgroundColor: this.chartOpt.backgroundColors[datasets.length % 9],
543
564
  borderColor: this.chartOpt.borderColors[datasets.length % 9]
@@ -546,6 +567,8 @@ export default{
546
567
  datasets.push(dataset)
547
568
  })
548
569
 
570
+ console.log(this.columns)
571
+ console.log(this.summary.columns)
549
572
  //console.log(labels)
550
573
  //console.log(datasets)
551
574
 
@@ -755,6 +778,13 @@ export default{
755
778
  },
756
779
 
757
780
  load(){
781
+
782
+ if(this.preset.summary){
783
+ if(!this.preset.summary.enabled && this.preset.summary.hideDetails){
784
+ this.preset.summary.hideDetails = false
785
+ }
786
+ }
787
+
758
788
  this.isLoading = true
759
789
  this.socketEmit(`${this.computedDataSource}.load`, {
760
790
  preset: this.preset
@@ -28,7 +28,9 @@
28
28
  <option value="">Select</option>
29
29
  <option value="today">Today</option>
30
30
  <option value="thisWeek">This Week</option>
31
+ <option value="weekAgo">1 Week Ago</option>
31
32
  <option value="thisMonth">This Month</option>
33
+ <option value="monthAgo">1 Month Ago</option>
32
34
  <option value="lastMonth">Last Month</option>
33
35
  <option value="thisMonth">This Year</option>
34
36
  <option value="lastYear">Last Year</option>
package/src/index.js CHANGED
@@ -219,6 +219,7 @@ export default{
219
219
  app.component('DynamicTemplate', defineAsyncComponent(() => import("./components/DynamicTemplate.vue")))
220
220
  app.component('ErrorText', defineAsyncComponent(() => import("./components/ErrorText.vue")))
221
221
  app.component('Feed', defineAsyncComponent(() => import("./components/Feed.vue")))
222
+ app.component('Gmaps', defineAsyncComponent(() => import("./components/Gmaps.vue")))
222
223
  app.component('HTMLEditor', defineAsyncComponent(() => import("./components/HTMLEditor.vue")))
223
224
  app.component('Ahref', defineAsyncComponent(() => import("./components/Ahref.vue")))
224
225
  app.component('Switch', defineAsyncComponent(() => import("./components/Switch.vue")))
@@ -79,6 +79,11 @@ let ListPage1 = {
79
79
  [ 'id', 'desc' ],
80
80
  ]
81
81
 
82
+ let attributeIncludes
83
+ if(this.getAttributeIncludes){
84
+ attributeIncludes = this.getAttributeIncludes(preset)
85
+ }
86
+
82
87
  let attributes = { id:1, updatedAt:1 }
83
88
  if(preset.columns){
84
89
  let modelAttributes = this.model.getAttributes();
@@ -86,6 +91,20 @@ let ListPage1 = {
86
91
  if(column.visible && modelAttributes[column.key]){
87
92
  attributes[column.key] = 1
88
93
  }
94
+ else if(column.virtual){
95
+ switch(column.virtual.type){
96
+
97
+ case 'sql':
98
+ if(!Array.isArray(attributeIncludes)){
99
+ attributeIncludes = []
100
+ }
101
+
102
+ attributeIncludes.push([
103
+ Sequelize.literal(`(${column.virtual.value})`), column.key
104
+ ])
105
+ break
106
+ }
107
+ }
89
108
  })
90
109
  }
91
110
  attributes = Object.keys(attributes)
@@ -122,11 +141,7 @@ let ListPage1 = {
122
141
  }
123
142
  }
124
143
 
125
- let attributeIncludes
126
- if(this.getAttributeIncludes){
127
- attributeIncludes = this.getAttributeIncludes(preset)
128
- }
129
-
144
+ let derivedSql
130
145
  const { rows:items, count } = await this.model.findAndCountAll({
131
146
  where,
132
147
  attributes: {
@@ -136,7 +151,10 @@ let ListPage1 = {
136
151
  order,
137
152
  limit: itemsPerPage + 1,
138
153
  replacements,
139
- include: this.getModelIncludes ? this.getModelIncludes(preset) : undefined
154
+ include: this.getModelIncludes ? this.getModelIncludes(preset) : undefined,
155
+ logging: (sql, queryObject, p) => {
156
+ derivedSql = sql
157
+ }
140
158
  })
141
159
 
142
160
  const hasNext = items.length > itemsPerPage
@@ -146,10 +164,19 @@ let ListPage1 = {
146
164
 
147
165
  let summary
148
166
  if(!afterItem && preset.summary && preset.summary.enabled){
149
- summary = await this.loadSummary(preset, {
150
- where,
151
- replacements
152
- })
167
+ if(preset.summary.mode === 'map' && this.loadMapSummary){
168
+ summary = await this.loadMapSummary(preset, {
169
+ where,
170
+ replacements
171
+ })
172
+ }
173
+ else{
174
+ derivedSql = derivedSql.replace('Executing (default): ', '').replace('LIMIT ' + (this.itemsPerPage + 1), '').slice(0, -1)
175
+ summary = await this.loadSummary(preset, {
176
+ where,
177
+ replacements
178
+ }, derivedSql)
179
+ }
153
180
  }
154
181
 
155
182
  if(this.socket){
@@ -164,7 +191,170 @@ let ListPage1 = {
164
191
  }
165
192
  },
166
193
 
167
- async loadSummary(preset, modelParams){
194
+ async loadSummary(preset, modelParams, derivedSql){
195
+
196
+ if(!this.conn) return
197
+
198
+ const { mode, columns, rows, values } = preset.summary
199
+
200
+ if(!Array.isArray(columns) || columns.length !== 1) return
201
+ if(!Array.isArray(rows) || rows.length !== 1) return
202
+ if(!Array.isArray(values) || values.length !== 1) return
203
+
204
+ const col = columns[0]
205
+ let columnValues = []
206
+ let colKey
207
+ if(col.key !== '(none)'){
208
+ colKey = col.key
209
+ const [ _columnValues ] = await this.conn.query(`
210
+ SELECT
211
+ DISTINCT(${colKey}) AS cols
212
+ FROM (${derivedSql}) AS derived
213
+ ORDER BY cols ASC
214
+ `)
215
+
216
+ columnValues = _columnValues
217
+ }
218
+ if(columnValues.length > 100){
219
+ throw new Error('Too many columns')
220
+ }
221
+
222
+ const attributes = []
223
+ const group = []
224
+ const summaryColumns = [
225
+ /*{ key:"dfDate", label:"Date", width:"200px", visible:true },
226
+ { key:"type-1", label:"Type 1", type:"number", visible:true },
227
+ { key:"type-2", label:"Type 2", type:"number", visible:true },
228
+ { key:"type-3", label:"Type 3", type:"number", visible:true },
229
+ { key:"type-4", label:"Type 4", type:"number", visible:true },
230
+ { key:"type-8", label:"Type 8", type:"number", visible:true },*/
231
+ ]
232
+
233
+ const row = rows[0]
234
+ const rowKey = row.key
235
+ const rowLabel = this.columns[row.key].label
236
+ switch(row.format){
237
+ case 'date':
238
+ attributes.push(`DATE_FORMAT(${rowKey}, '%Y-%m-%d') as dfDate`)
239
+ group.push(`DATE_FORMAT(${rowKey}, '%Y-%m-%d')`)
240
+ summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true, type:"date", format:"D MMM" })
241
+ break
242
+
243
+ case 'month':
244
+ attributes.push(`DATE_FORMAT(${rowKey}, '%Y-%m') as dfDate`)
245
+ group.push(`DATE_FORMAT(${rowKey}, '%Y-%m')`)
246
+ summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true, type:"date", format:"MMM YYYY" })
247
+ break
248
+
249
+ case 'quarter':
250
+ attributes.push(`CONCAT(YEAR(${rowKey}), ' Q', QUARTER(${rowKey})) as dfDate`)
251
+ group.push(`CONCAT(YEAR(${rowKey}), ' Q', QUARTER(${rowKey}))`)
252
+ summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true, type:"date", format:"MMM YYYY" })
253
+ break
254
+
255
+ case 'year':
256
+ attributes.push(`DATE_FORMAT(${rowKey}, '%Y') as dfDate`)
257
+ group.push(`DATE_FORMAT(${rowKey}, '%Y')`)
258
+ summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true, type:"date", format:"YYYY" })
259
+ break
260
+
261
+ default:
262
+ attributes.push(`${rowKey} as dfDate`)
263
+ group.push(`${rowKey}`)
264
+ summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true })
265
+ break
266
+ }
267
+
268
+ const value = values[0]
269
+ if(columnValues.length > 0){
270
+ columnValues.forEach((obj) => {
271
+ const columnValue = obj.cols
272
+
273
+ let columnLabel = (columnValue ?? '').toString()
274
+ const baseColumn = this.columns[colKey]
275
+ switch(baseColumn.type){
276
+
277
+ case 'enum':
278
+ const enumValue = baseColumn.typeParams.filter((_) => _.value === columnValue).pop()
279
+ if(enumValue) columnLabel = enumValue.text
280
+ break
281
+ }
282
+
283
+ switch(value.aggregrate){
284
+ case 'count':
285
+ const fn = columnValue === null ? `${colKey} is null` : `${colKey} = '${columnValue}'`
286
+ attributes.push(`SUM(IF(${fn}, 1, 0)) as \`${colKey}-${columnValue}\``)
287
+ summaryColumns.push({ key:colKey + "-" + columnValue, label:columnLabel, visible:true, aggregrate:"count" })
288
+ break
289
+
290
+ case 'min':
291
+ attributes.push(`MIN(${colKey}) as \`${colKey}-${columnValue}\``)
292
+ summaryColumns.push({ key:colKey + "-" + columnValue, label:columnLabel, visible:true, aggregrate:"count" })
293
+ break
294
+
295
+ case 'max':
296
+ attributes.push(`MAX(${colKey}) as \`${colKey}-${columnValue}\``)
297
+ summaryColumns.push({ key:colKey + "-" + columnValue, label:columnLabel, visible:true, aggregrate:"count" })
298
+ break
299
+
300
+ case 'avg':
301
+ attributes.push(`AVG(${colKey}) as \`${colKey}-${columnValue}\``)
302
+ summaryColumns.push({ key:colKey + "-" + columnValue, label:columnLabel, visible:true, aggregrate:"count" })
303
+ break
304
+ }
305
+ })
306
+ }
307
+ else{
308
+ switch(value.aggregrate) {
309
+ case 'count':
310
+ default:
311
+ attributes.push(`COUNT(*) as \`Count\``)
312
+ summaryColumns.push({ key:'Count', label:'Count', type:"number", visible:true, aggregrate:"count" })
313
+ }
314
+ }
315
+
316
+ //console.log(attributes)
317
+
318
+ let [ summaryItems ] = await this.conn.query(`
319
+ SELECT
320
+ ${attributes.join(', ')}
321
+ FROM (
322
+ ${derivedSql}
323
+ ) as t1
324
+ GROUP BY ${group[0]}
325
+ ORDER BY dfDate ASC
326
+ `)
327
+
328
+ if(this.columns[rowKey] && this.columns[rowKey].type === 'enum'){
329
+ summaryItems = summaryItems.map((_) => {
330
+
331
+ const typeParam = this.columns[rowKey].typeParams.filter((__) => __.value === _.dfDate).pop()
332
+ if(typeParam){
333
+ _.dfDate = typeParam.text
334
+ }
335
+
336
+ return _
337
+ })
338
+ }
339
+
340
+ const summary = {
341
+ type: "table",
342
+ columns: summaryColumns,
343
+ items: summaryItems
344
+ /*items: [
345
+ { date:"21 Jan 23", "type-1":12, "type-2":11, "type-3":16, "type-4":2, "type-8":8 },
346
+ { date:"22 Jan 23", "type-1":51, "type-2":87, "type-3":86, "type-4":3, "type-8":9 },
347
+ { date:"23 Jan 23", "type-1":14, "type-2":66, "type-3":77, "type-4":4, "type-8":18 },
348
+ { date:"24 Jan 23", "type-1":7, "type-2":3, "type-3":63, "type-4":5, "type-8":28 },
349
+ { date:"25 Jan 23", "type-1":88, "type-2":55, "type-3":68, "type-4":6, "type-8":38 },
350
+ { date:"26 Jan 23", "type-1":172, "type-2":13, "type-3":6, "type-4":7, "type-8":48 }
351
+ ]*/
352
+ }
353
+
354
+ return summary
355
+ },
356
+
357
+ async loadSummary0(preset, modelParams){
168
358
 
169
359
  const { columns, rows, values } = preset.summary
170
360
 
@@ -240,28 +430,38 @@ let ListPage1 = {
240
430
  columnValues.forEach((obj) => {
241
431
  const columnValue = obj.dataValues['cols']
242
432
 
433
+ let columnLabel = (columnValue ?? '').toString()
434
+ const baseColumn = this.columns[colKey]
435
+ switch(baseColumn.type){
436
+
437
+ case 'enum':
438
+ const enumValue = baseColumn.typeParams.filter((_) => _.value === columnValue).pop()
439
+ if(enumValue) columnLabel = enumValue.text
440
+ break
441
+ }
442
+
243
443
  switch(value.aggregrate){
244
444
  case 'count':
245
445
  const fn = columnValue === null ?
246
446
  Sequelize.literal(`${colKey} is null`) :
247
447
  Sequelize.literal(`${colKey} = '${columnValue}'`)
248
448
  attributes.push([Sequelize.fn("SUM", Sequelize.fn("IF", fn, 1, 0)), colKey + "-" + columnValue])
249
- summaryColumns.push({ key:colKey + "-" + columnValue, label:(columnValue ?? '').toString(), visible:true, aggregrate:"count" })
449
+ summaryColumns.push({ key:colKey + "-" + columnValue, label:columnLabel, visible:true, aggregrate:"count" })
250
450
  break
251
451
 
252
452
  case 'min':
253
453
  attributes.push([Sequelize.fn("MIN", colKey), colKey + "-" + columnValue])
254
- summaryColumns.push({ key:colKey + "-" + columnValue, label:(columnValue ?? '').toString(), visible:true, aggregrate:"count" })
454
+ summaryColumns.push({ key:colKey + "-" + columnValue, label:columnLabel, visible:true, aggregrate:"count" })
255
455
  break
256
456
 
257
457
  case 'max':
258
458
  attributes.push([Sequelize.fn("MAX", colKey), colKey + "-" + columnValue])
259
- summaryColumns.push({ key:colKey + "-" + columnValue, label:(columnValue ?? '').toString(), visible:true, aggregrate:"count" })
459
+ summaryColumns.push({ key:colKey + "-" + columnValue, label:columnLabel, visible:true, aggregrate:"count" })
260
460
  break
261
461
 
262
462
  case 'avg':
263
463
  attributes.push([Sequelize.fn("AVG", colKey), colKey + "-" + columnValue])
264
- summaryColumns.push({ key:colKey + "-" + columnValue, label:(columnValue ?? '').toString(), visible:true, aggregrate:"count" })
464
+ summaryColumns.push({ key:colKey + "-" + columnValue, label:columnLabel, visible:true, aggregrate:"count" })
265
465
  break
266
466
  }
267
467
  })
@@ -380,6 +580,14 @@ let ListPage1 = {
380
580
  }
381
581
  break
382
582
 
583
+ case 'weekAgo':
584
+ whereValue = {
585
+ ...whereValue,
586
+ [Op.gte]: dayjs().add(-1, 'week').format('YYYY-MM-DD 00:00:00'),
587
+ [Op.lt]: dayjs().format('YYYY-MM-DD 23:59:59'),
588
+ }
589
+ break
590
+
383
591
  case 'thisMonth':
384
592
  whereValue = {
385
593
  ...whereValue,
@@ -388,6 +596,14 @@ let ListPage1 = {
388
596
  }
389
597
  break
390
598
 
599
+ case 'monthAgo':
600
+ whereValue = {
601
+ ...whereValue,
602
+ [Op.gte]: dayjs().add(-1, 'month').format('YYYY-MM-DD 00:00:00'),
603
+ [Op.lt]: dayjs().format('YYYY-MM-DD 23:59:59'),
604
+ }
605
+ break
606
+
391
607
  case 'lastMonth':
392
608
  whereValue = {
393
609
  [Op.gte]: dayjs().add(-1, 'month').format('YYYY-MM-01 00:00:00'),