@mixd-id/web-scaffold 0.1.230406250 → 0.1.230406252

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.230406250",
4
+ "version": "0.1.230406252",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -13,17 +13,34 @@
13
13
  </h4>
14
14
  </div>
15
15
 
16
- <Bar v-if="preset.chart.type === 'bar'" class="w-full"
17
- id="my-chart-id"
18
- :options="chartOptions"
19
- :data="chartData"
20
- />
21
-
22
- <Line v-if="preset.chart.type === 'line'" class="w-full"
23
- id="my-chart-id"
24
- :options="chartOptions"
25
- :data="chartData"
26
- />
16
+ <div class="flex-1 flex flex-col">
17
+
18
+ <Bar v-if="preset.chart.type === 'bar'"
19
+ class="w-full"
20
+ :options="chartOptions"
21
+ :data="chartData" />
22
+
23
+ <Line v-else-if="preset.chart.type === 'line'"
24
+ class="w-full"
25
+ :options="chartOptions"
26
+ :data="chartData" />
27
+
28
+ <Doughnut v-else-if="preset.chart.type === 'doughnut'"
29
+ class="aspect-square"
30
+ :options="chartOptions"
31
+ :data="chartData" />
32
+
33
+ <Pie v-else-if="preset.chart.type === 'pie'"
34
+ class="aspect-square"
35
+ :options="chartOptions"
36
+ :data="chartData" />
37
+
38
+ <Gmaps v-else-if="preset.chart.type === 'maps'"
39
+ :data="chartData"
40
+ :config="chartOptions"
41
+ class="flex-1" />
42
+
43
+ </div>
27
44
 
28
45
  <PresetSelector ref="presetSelector" :config="config" @select="load" type="chart" />
29
46
 
@@ -38,7 +55,7 @@
38
55
 
39
56
  <script>
40
57
 
41
- import { Bar, Line } from 'vue-chartjs'
58
+ import { Bar, Line, Doughnut, Pie } from 'vue-chartjs'
42
59
  import Chart from 'chart.js/auto'
43
60
  import PresetSelector from "../widgets/PresetSelector.vue";
44
61
  import throttle from "lodash/throttle";
@@ -46,7 +63,7 @@ import dayjs from "dayjs";
46
63
 
47
64
  export default{
48
65
 
49
- components: {Bar, Line, PresetSelector},
66
+ components: {Bar, Line, Doughnut, Pie, PresetSelector},
50
67
 
51
68
  emits: [ 'open-preset' ],
52
69
 
@@ -103,93 +120,234 @@ export default{
103
120
 
104
121
  chartData(){
105
122
 
106
- const { type, xAxis = [], yAxis = [] } = this.preset.chart ?? {}
107
-
123
+ const { type } = this.preset.chart ?? {}
124
+ const { xAxis = [], yAxis = [] } = this.preset.chart[type] ?? {}
108
125
  const items = this.data.items ?? []
126
+ let labels = []
127
+ let datasets = []
128
+
129
+ if(items.length > 0){
130
+ switch(type){
131
+
132
+ case 'doughnut':
133
+ case 'pie':
134
+ if(yAxis.length > 0){
135
+ for(let i = 0 ; i < items.length ; i++){
136
+ const item = items[i]
137
+
138
+ const data = []
139
+ for(let key in item){
140
+ if(key.startsWith(yAxis[0].key)){
141
+ const value = key.split(':').pop()
142
+ if(i === 0) labels.push(value)
143
+ }
144
+ data.push(item[key])
145
+ }
146
+
147
+ let label = []
148
+ for(let xAxe of xAxis){
149
+ if(!xAxe.key) continue
150
+
151
+ switch(this.columns[xAxe.key].type){
152
+ case 'enum':
153
+ label.push(this.columns[xAxe.key].typeParams.find(_ => _.value === item[xAxe.key])?.text ?? item[xAxe.key])
154
+ break
155
+
156
+ default:
157
+ label.push(item[xAxe.key])
158
+ break
159
+ }
160
+ }
161
+ label = label.join(' ')
162
+
163
+ datasets.push({
164
+ label,
165
+ backgroundColor: this.backgroundColors,
166
+ data
167
+ })
168
+ }
169
+ }
170
+ break
171
+
172
+ case 'maps':
173
+ datasets = items
174
+ break
175
+
176
+ case 'line':
177
+ case 'bar':
178
+
179
+ if(xAxis.length > 0){
180
+ if(yAxis.length < 1){
181
+ datasets.push({
182
+ label: 'count',
183
+ data: [],
184
+ borderColor: this.borderColors[datasets.length % this.borderColors.length],
185
+ backgroundColor: this.backgroundColors[datasets.length % this.backgroundColors.length],
186
+ })
187
+ }
188
+ else{
189
+ for(let yAxe of yAxis){
190
+
191
+ const item0 = items[0]
192
+ for(let key in item0){
193
+ if(key.startsWith(yAxe.key)) {
194
+ const value = key.split(':').pop()
195
+ let label = value
196
+
197
+ const columnKey = yAxe.key
198
+ const column = this.config.columns.find(column => column.key === columnKey)
199
+ switch (column.type) {
200
+ case 'enum':
201
+ label = column.typeParams.find(_ => `${_.value}` === `${value}`)?.text ?? label
202
+ break
203
+ }
204
+
205
+ datasets.push({
206
+ key,
207
+ label,
208
+ data: [],
209
+ borderColor: this.borderColors[datasets.length % this.borderColors.length],
210
+ backgroundColor: this.backgroundColors[datasets.length % this.backgroundColors.length],
211
+ })
212
+ }
213
+ }
214
+ }
215
+ }
109
216
 
110
- const datasets = []
111
- if((yAxis[0] ?? {}).aggregrate === 'count'){
112
- datasets.push({
113
- label: 'count',
114
- data: [],
115
- borderColor: this.borderColors[datasets.length % this.borderColors.length],
116
- backgroundColor: this.backgroundColors[datasets.length % this.backgroundColors.length],
117
- })
118
- }
119
- else{
120
- for(let key in items[0] ?? {}){
121
- if(key !== xAxis[0].key){
122
- datasets.push({
123
- label: key,
124
- data: [],
125
- borderColor: this.borderColors[datasets.length % this.borderColors.length],
126
- backgroundColor: this.backgroundColors[datasets.length % this.backgroundColors.length],
127
- })
128
- }
129
- }
130
- }
131
-
132
- const labels = []
133
- for(let item of this.data.items ?? []){
134
- labels.push(dayjs(item[xAxis[0].key]).format('DD MMM'))
135
-
136
- if((yAxis[0] ?? {}).aggregrate === 'count'){
137
- datasets[0].data.push(item['count'])
138
- }
139
- else{
140
- for(let i in datasets){
141
- datasets[i].data.push(item[datasets[i].label])
142
- }
217
+ for(let item of this.data.items ?? []){
218
+
219
+ const column = this.config.columns.find(column => column.key === xAxis[0].key)
220
+ if(!column) continue
221
+
222
+ switch(column.type){
223
+ case 'date':
224
+ switch(xAxis[0].aggregrate){
225
+
226
+ case 'date':
227
+ labels.push(dayjs(item[xAxis[0].key]).format('DD MMM'))
228
+ break
229
+
230
+ default:
231
+ labels.push(item[xAxis[0].key])
232
+ break
233
+ }
234
+ break
235
+
236
+ case 'enum':
237
+ labels.push(column.typeParams.find(_ => _.value === item[xAxis[0].key])?.text ?? item[xAxis[0].key])
238
+ break
239
+
240
+ default:
241
+ labels.push(item[xAxis[0].key])
242
+ break
243
+ }
244
+
245
+ if(yAxis.length < 1){
246
+ datasets[0].data.push(item['count'])
247
+ }
248
+ else{
249
+ for(let i in datasets){
250
+ datasets[i].data.push(item[datasets[i].key])
251
+ }
252
+ }
253
+ }
254
+ }
255
+ break
143
256
  }
144
257
  }
145
258
 
146
259
  return {
147
260
  labels,
148
- datasets
261
+ datasets,
149
262
  }
150
263
  },
151
264
 
152
265
  chartOptions(){
153
266
  if(typeof window === 'undefined') return
154
267
 
155
- var style = getComputedStyle(document.body)
156
- var gridColor = style.getPropertyValue('--text-100')
157
- var gridColor2 = style.getPropertyValue('--text-200')
268
+ const { type } = this.chart
269
+ const opt = this.chartOpt
158
270
 
159
- return {
160
- responsive: true,
161
- maintainAspectRatio: false,
162
- animation: false,
163
- plugins: {
164
- legend: {
165
- display: this.preset.chart.showLegend ?? false, // Disable the legend
166
- },
167
- },
168
- scales: {
169
- x: {
170
- //display: false, // Disable x-axis labels
171
- grid: {
172
- display: true,
173
- color: function(context){
174
- return `rgb(${gridColor2})`
175
- }
271
+ switch(type){
272
+
273
+ case 'doughnut':
274
+ case 'pie':
275
+ return {
276
+ responsive: true,
277
+ maintainAspectRatio: false,
278
+ plugins: {
279
+ legend: {
280
+ display: opt.showLegend ?? false, // Disable the legend
281
+ },
176
282
  },
177
- stacked: this.preset.chart.type === 'bar' && this.preset.chart.stack
178
- },
179
- y: {
180
- beginAtZero: true, // Adjust y-axis as needed
181
- grid: {
182
- display: true,
183
- color: function(context){
184
- return `rgb(${gridColor})`
185
- }
283
+ }
284
+
285
+ case 'maps':
286
+ return {
287
+ apiKey: 'AIzaSyBmzMlmrR5St-njtN--64y_oLTa9FDLYfQ',
288
+ mapColumn: opt.mapColumn,
289
+ zoom: 4,
290
+ center: [ -1.861824, 118.444392 ]
291
+ }
292
+
293
+ default:
294
+ var style = getComputedStyle(document.body)
295
+ var gridColor = style.getPropertyValue('--text-100')
296
+ var gridColor2 = style.getPropertyValue('--text-200')
297
+
298
+ return {
299
+ responsive: true,
300
+ maintainAspectRatio: false,
301
+ animation: true,
302
+ plugins: {
303
+ legend: {
304
+ display: opt.showLegend ?? false, // Disable the legend
305
+ },
186
306
  },
187
- stacked: this.preset.chart.type === 'bar' && this.preset.chart.stack
188
- },
189
- },
307
+ scales: {
308
+ x: {
309
+ //display: false, // Disable x-axis labels
310
+ grid: {
311
+ display: true,
312
+ color: function(context){
313
+ return `rgb(${gridColor2})`
314
+ }
315
+ },
316
+ stacked: this.preset.chart.type === 'bar' && opt.stack
317
+ },
318
+ y: {
319
+ beginAtZero: true, // Adjust y-axis as needed
320
+ grid: {
321
+ display: true,
322
+ color: function(context){
323
+ return `rgb(${gridColor})`
324
+ }
325
+ },
326
+ stacked: this.preset.chart.type === 'bar' && opt.stack
327
+ },
328
+ },
329
+ }
190
330
  }
191
331
  },
192
332
 
333
+ chart(){
334
+ return this.preset.chart ?? {}
335
+ },
336
+
337
+ chartOpt(){
338
+ if(!this.preset.chart[this.preset.chart.type])
339
+ this.preset.chart[this.preset.chart.type] = {}
340
+
341
+ return this.preset.chart[this.preset.chart.type]
342
+ },
343
+
344
+ columns(){
345
+ return this.config.columns.reduce((acc, column) => {
346
+ acc[column.key] = column
347
+ return acc
348
+ }, {})
349
+ },
350
+
193
351
  preset(){
194
352
  return ((this.config ?? {}).presets ?? [])[(this.config ?? {}).presetIdx ?? 0] ?? {}
195
353
  },
@@ -200,7 +358,10 @@ export default{
200
358
 
201
359
  load(){
202
360
  this.socket.send(this.src, this.preset)
203
- .then(data => this.data = data)
361
+ .then(data => {
362
+ this.data = data
363
+ this.readyState = 1
364
+ })
204
365
  .catch(err => {
205
366
  this.readyState = -1
206
367
  this.error = err
@@ -230,7 +391,6 @@ export default{
230
391
  }, 1000, { leading:true }),
231
392
 
232
393
  onSignal(event, items){
233
- console.log('onSignal', event, items)
234
394
 
235
395
  const hasData = items.some(item => item._data)
236
396
  if(hasData){
@@ -318,7 +478,7 @@ export default{
318
478
 
319
479
  .comp{
320
480
  @apply flex flex-col p-2;
321
- @apply bg-base-500;
481
+ @apply backdrop-blur-lg;
322
482
  padding-bottom: 50px;
323
483
  }
324
484
 
@@ -9,7 +9,10 @@
9
9
  </div>
10
10
  </Transition>
11
11
  </div>
12
- <slot></slot>
12
+ <label v-if="!$slots.item" :class="$style.label">
13
+ <slot name="default"></slot>
14
+ </label>
15
+ <slot v-else name="item"></slot>
13
16
  </label>
14
17
  </div>
15
18
  </template>
@@ -181,4 +184,8 @@ export default {
181
184
  opacity: 0;
182
185
  }
183
186
 
187
+ .label{
188
+ @apply flex-1 text-ellipsis overflow-hidden whitespace-nowrap;
189
+ }
190
+
184
191
  </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :class="$style.comp">
3
- <div v-if="apiKey" ref="map" class="flex-1"></div>
3
+ <div v-if="config.apiKey" ref="map" class="flex-1"></div>
4
4
  <div v-else class="flex-1 flex items-center justify-center text-text-400">{{ $t('Google maps api required') }}</div>
5
5
  </div>
6
6
  </template>
@@ -12,9 +12,12 @@ import { Loader } from '@googlemaps/js-api-loader';
12
12
  export default{
13
13
 
14
14
  props: {
15
- data: Array,
16
- config: Object,
17
- apiKey: String
15
+ data: Object,
16
+
17
+ config: {
18
+ type: Object,
19
+ default: {}
20
+ },
18
21
  },
19
22
 
20
23
  data(){
@@ -30,13 +33,13 @@ export default{
30
33
  methods: {
31
34
 
32
35
  load(){
33
- if(!this.apiKey) return
36
+ if(!this.config.apiKey) return
34
37
 
35
- if(!Array.isArray(this.data) || this.data.length < 1)
38
+ if(!Array.isArray(this.data.datasets) || this.data.datasets.length < 1)
36
39
  return
37
40
 
38
41
  const loader = new Loader({
39
- apiKey: this.apiKey // "AIzaSyBmzMlmrR5St-njtN--64y_oLTa9FDLYfQ"
42
+ apiKey: this.config.apiKey // "AIzaSyBmzMlmrR5St-njtN--64y_oLTa9FDLYfQ"
40
43
  })
41
44
 
42
45
  loader.load()
@@ -51,7 +54,7 @@ export default{
51
54
 
52
55
  this.map = new Map(this.$refs.map, {
53
56
  center: center,
54
- zoom: this.config.zoom ?? 7,
57
+ zoom: this.config.zoom ?? 4,
55
58
  mapTypeId: 'roadmap',
56
59
  streetViewControl: false,
57
60
  keyboardShortcuts: false,
@@ -166,7 +169,7 @@ export default{
166
169
  {location: new google.maps.LatLng(37.785, -122.435), weight: 3}*/
167
170
  ];
168
171
 
169
- this.data.forEach((item) => {
172
+ this.datasets.forEach((item) => {
170
173
  if(item[0] && item[1] && item[2]){
171
174
  heatMapData.push({
172
175
  location: new google.maps.LatLng(item[0], item[1]),
@@ -206,6 +209,27 @@ export default{
206
209
 
207
210
  },
208
211
 
212
+ computed: {
213
+
214
+ datasets(){
215
+ if(!Array.isArray((this.data ?? {}).datasets)) return []
216
+
217
+ const grouped = this.data.datasets.reduce((acc, item) => {
218
+ if(!acc[item['deliveryCityCoord']]) acc[item['deliveryCityCoord']] = 0
219
+ acc[item['deliveryCityCoord']] += 1
220
+ return acc
221
+ }, {})
222
+
223
+ const datasets = []
224
+ for(let coord in grouped){
225
+ datasets.push([parseFloat(coord.split(',')[0]), parseFloat(coord.split(',')[1]), grouped[coord]])
226
+ }
227
+
228
+ return datasets
229
+ }
230
+
231
+ },
232
+
209
233
  watch: {
210
234
 
211
235
  data(){
@@ -221,7 +245,7 @@ export default{
221
245
  <style module>
222
246
 
223
247
  .comp{
224
- @apply flex-1 flex flex-col;
248
+ @apply flex flex-col;
225
249
  }
226
250
 
227
- </style>
251
+ </style>
@@ -4,7 +4,7 @@
4
4
  class="flex-1 flex flex-row">
5
5
 
6
6
  <div v-if="computedPresetMode === 'sidebar' && config.sidebarOpen"
7
- class="relative flex flex-col border-r-[1px] border-text-50 bg-base-400 dark:bg-base-300 backdrop-blur-lg"
7
+ class="relative flex flex-col border-r-[1px] border-text-50 backdrop-blur-lg"
8
8
  :style="sidebarWidth">
9
9
 
10
10
  <PresetBar :config="config"
@@ -22,7 +22,7 @@
22
22
  @mousedown="(e) => $util.dragResize(e, resize1)"></div>
23
23
  </div>
24
24
 
25
- <div class="flex-1 flex flex-col gap-3" :class="containerClass">
25
+ <div class="flex-1 flex flex-col gap-6" :class="containerClass">
26
26
 
27
27
  <slot name="head"
28
28
  :preset="preset"
@@ -44,11 +44,11 @@
44
44
 
45
45
  <div class="flex-1"></div>
46
46
 
47
- <slot name="toolbar"></slot>
47
+ <slot v-if="Boolean(toolbar)" name="toolbar"></slot>
48
48
  </div>
49
49
 
50
50
  <div class="flex flex-row gap-2 gap-1" v-if="Boolean(toolbar)">
51
- <Textbox class="flex-1 bg-base-500 md:w-[240px]" placeholder="Search..." clearable="1"
51
+ <Textbox class="flex-1 backdrop-blur-lg md:w-[240px]" placeholder="Search..." clearable="1"
52
52
  v-model="preset.search"
53
53
  @clear="delete preset.search; load()"
54
54
  @keyup.enter="load">
@@ -85,7 +85,7 @@
85
85
 
86
86
  <VirtualTable v-if="presetView === 'table'"
87
87
  :columns="columns"
88
- class="flex-1 bg-base-500 dark:bg-base-400 rounded-lg"
88
+ class="flex-1 rounded-lg backdrop-blur-lg"
89
89
  :items="data.items"
90
90
  @scroll-end="loadNext">
91
91
 
@@ -106,7 +106,7 @@
106
106
  :column="computedGridColumn"
107
107
  class="flex-1"
108
108
  @scroll-end="loadNext"
109
- :container-class="gridContainerClass"
109
+ :container-class="`${gridContainerClass}`"
110
110
  :config="config">
111
111
  <template #item="{ item }">
112
112
  <slot name="gridItem" :item="item">
@@ -190,18 +190,31 @@ export default{
190
190
  // Handle non-aggregrated pivot values
191
191
  if((this.preset.pivot ?? {}).enabled && data.items.length > 0){
192
192
 
193
- const tableColumns = groupBy(this.preset.columns ?? this.config.columns, 'key')
193
+ const tableColumns = (this.preset.columns ?? this.config.columns).reduce((cur, obj) => {
194
+ cur[obj.key] = obj
195
+ return cur
196
+ }, {})
194
197
 
195
198
  const columns = []
196
199
  for(let key in data.items[0]){
197
200
  if(key.startsWith('_')){
198
201
  const [ k1, k2 ] = key.substring(1).split('-')
199
202
 
203
+ let label = k2.replace(/_/gi, ' ')
204
+ const column = tableColumns[k1]
205
+ if(column){
206
+ switch(column.type){
207
+ case 'enum':
208
+ label = (column.typeParams ?? []).find(_ => `${_.value}` === `${k2}`)?.text ?? label
209
+ break
210
+ }
211
+ }
212
+
200
213
  if(!tableColumns[key]){
201
214
  columns.push({
202
215
  key,
203
- label: k2.replace(/_/gi, ' '),
204
- label2: ((tableColumns[k1][0].label ?? '') + ': ' + k2.replace(/_/gi, ' ')).trim(),
216
+ label,
217
+ label2: (((tableColumns[k1] ?? {}).label ?? '') + ': ' + label).trim(),
205
218
  type: 'number',
206
219
  })
207
220
  }
@@ -257,7 +270,7 @@ export default{
257
270
  else{
258
271
  return new Promise((resolve) => {
259
272
  this.savePreset()
260
- //this.$router.replace({ name:this.$route.name })
273
+ this.$router.replace({ name:this.$route.name })
261
274
  resolve()
262
275
  })
263
276
  }
@@ -461,7 +474,7 @@ export default{
461
474
  return {
462
475
  readyState: 0,
463
476
  data: {
464
- itemsPerPage: 15,
477
+ itemsPerPage: 16,
465
478
  },
466
479
  observer: null,
467
480
  compPrefix: '',
@@ -305,7 +305,7 @@ export default{
305
305
 
306
306
  .modal{
307
307
  @apply fixed;
308
- @apply bg-base-400;
308
+ @apply bg-base-400 dark:bg-base-300;
309
309
  @apply border-[1px] border-text-50 z-20 flex max-h-[90vh];
310
310
  @apply rounded-xl overflow-hidden transition-all;
311
311
  }