@mixd-id/web-scaffold 0.1.230406251 → 0.1.230406253

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.230406251",
4
+ "version": "0.1.230406253",
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,105 +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 ?? []
109
-
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
-
123
- let label = key
124
-
125
- const columnKey = yAxis[0].key
126
- const column = this.preset.columns.find(column => column.key === columnKey)
127
- switch(column.type){
128
- case 'enum':
129
- label = column.typeParams.find(_ => `${_.value}` === `${key}`)?.text ?? label
130
- break
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
+ }
131
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
+ }
132
216
 
133
- datasets.push({
134
- key,
135
- label,
136
- data: [],
137
- borderColor: this.borderColors[datasets.length % this.borderColors.length],
138
- backgroundColor: this.backgroundColors[datasets.length % this.backgroundColors.length],
139
- })
140
- }
141
- }
142
- }
143
-
144
- const labels = []
145
- for(let item of this.data.items ?? []){
146
- labels.push(dayjs(item[xAxis[0].key]).format('DD MMM'))
147
-
148
- if((yAxis[0] ?? {}).aggregrate === 'count'){
149
- datasets[0].data.push(item['count'])
150
- }
151
- else{
152
- for(let i in datasets){
153
- datasets[i].data.push(item[datasets[i].key])
154
- }
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
155
256
  }
156
257
  }
157
258
 
158
259
  return {
159
260
  labels,
160
- datasets
261
+ datasets,
161
262
  }
162
263
  },
163
264
 
164
265
  chartOptions(){
165
266
  if(typeof window === 'undefined') return
166
267
 
167
- var style = getComputedStyle(document.body)
168
- var gridColor = style.getPropertyValue('--text-100')
169
- var gridColor2 = style.getPropertyValue('--text-200')
268
+ const { type } = this.chart
269
+ const opt = this.chartOpt
170
270
 
171
- return {
172
- responsive: true,
173
- maintainAspectRatio: false,
174
- animation: false,
175
- plugins: {
176
- legend: {
177
- display: this.preset.chart.showLegend ?? false, // Disable the legend
178
- },
179
- },
180
- scales: {
181
- x: {
182
- //display: false, // Disable x-axis labels
183
- grid: {
184
- display: true,
185
- color: function(context){
186
- return `rgb(${gridColor2})`
187
- }
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
+ },
188
282
  },
189
- stacked: this.preset.chart.type === 'bar' && this.preset.chart.stack
190
- },
191
- y: {
192
- beginAtZero: true, // Adjust y-axis as needed
193
- grid: {
194
- display: true,
195
- color: function(context){
196
- return `rgb(${gridColor})`
197
- }
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
+ },
198
306
  },
199
- stacked: this.preset.chart.type === 'bar' && this.preset.chart.stack
200
- },
201
- },
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
+ }
202
330
  }
203
331
  },
204
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
+
205
351
  preset(){
206
352
  return ((this.config ?? {}).presets ?? [])[(this.config ?? {}).presetIdx ?? 0] ?? {}
207
353
  },
@@ -212,7 +358,10 @@ export default{
212
358
 
213
359
  load(){
214
360
  this.socket.send(this.src, this.preset)
215
- .then(data => this.data = data)
361
+ .then(data => {
362
+ this.data = data
363
+ this.readyState = 1
364
+ })
216
365
  .catch(err => {
217
366
  this.readyState = -1
218
367
  this.error = err
@@ -329,7 +478,7 @@ export default{
329
478
 
330
479
  .comp{
331
480
  @apply flex flex-col p-2;
332
- @apply bg-base-500;
481
+ @apply backdrop-blur-lg;
333
482
  padding-bottom: 50px;
334
483
  }
335
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>
@@ -302,7 +302,7 @@ export default {
302
302
 
303
303
  .contextMenu{
304
304
  @apply fixed z-20 bg-base-400 min-w-[150px] overflow-y-auto rounded-xl;
305
- @apply border-[2px] border-border-50 shadow-2xl whitespace-nowrap;
305
+ @apply border-[2px] border-text-50 shadow-2xl whitespace-nowrap;
306
306
  transition: all 150ms cubic-bezier(0.25, 1, 0.5, 1);
307
307
  opacity: 0;
308
308
  }
@@ -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
  }