@mixd-id/web-scaffold 0.1.230406133 → 0.1.230406134
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/ChartBar.vue +193 -0
- package/src/components/ListView.vue +6 -1
- package/src/components/ListViewBarSummary.vue +1 -0
- package/src/components/ListViewLiveBarSummary.vue +52 -0
- package/src/components/ListViewSettings.vue +4 -0
- package/src/components/Slider.vue +1 -1
- package/src/index.js +2 -0
- package/src/utils/listview.js +6 -0
- package/src/widgets/FeatureList.vue +6 -7
- package/src/widgets/FeatureListItem.vue +1 -1
- package/src/widgets/FeatureListSetting.vue +21 -0
package/package.json
CHANGED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="$style.comp">
|
|
3
|
+
<pre class="hidden whitespace-nowrap text-xs overflow-x-auto">{{ options }}</pre>
|
|
4
|
+
<Bar :class="$style.chart" :data="chartData" :options="chartOptions" />
|
|
5
|
+
</div>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<script>
|
|
9
|
+
|
|
10
|
+
import { Bar } from 'vue-chartjs';
|
|
11
|
+
import Chart from 'chart.js/auto'
|
|
12
|
+
import dayjs from "dayjs";
|
|
13
|
+
import groupBy from "lodash/groupBy";
|
|
14
|
+
|
|
15
|
+
export default{
|
|
16
|
+
|
|
17
|
+
name: 'BarChart',
|
|
18
|
+
|
|
19
|
+
components: { Bar },
|
|
20
|
+
|
|
21
|
+
props: {
|
|
22
|
+
|
|
23
|
+
items: Array,
|
|
24
|
+
|
|
25
|
+
options: Object,
|
|
26
|
+
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
methods: {
|
|
30
|
+
|
|
31
|
+
setInitialData(){
|
|
32
|
+
|
|
33
|
+
const items = []
|
|
34
|
+
const end = new Date();
|
|
35
|
+
const start = new Date(end);
|
|
36
|
+
start.setMinutes(end.getMinutes() - 2);
|
|
37
|
+
|
|
38
|
+
let currentTime = new Date(start);
|
|
39
|
+
while (currentTime <= end) {
|
|
40
|
+
|
|
41
|
+
const count = Math.round(Math.random() * 100)
|
|
42
|
+
for(let i = 0 ; i < count ; i++){
|
|
43
|
+
items.push({
|
|
44
|
+
createdAt: currentTime.toISOString()
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
currentTime.setSeconds(currentTime.getSeconds() + 1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.items = items
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
play(){
|
|
55
|
+
|
|
56
|
+
const arr = []
|
|
57
|
+
const end = new Date();
|
|
58
|
+
//end.setHours(16, 7, 0, 0)
|
|
59
|
+
const start = new Date(end);
|
|
60
|
+
start.setHours(end.getHours() - 2);
|
|
61
|
+
|
|
62
|
+
let currentTime = new Date(start);
|
|
63
|
+
while (currentTime <= end) {
|
|
64
|
+
arr.push(dayjs(currentTime).format('YYYYMMDDHHmm'))
|
|
65
|
+
currentTime.setMinutes(currentTime.getMinutes() + 1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.labels = arr
|
|
69
|
+
|
|
70
|
+
/*let count = Math.round(Math.random() * 100)
|
|
71
|
+
if(count < 10) count = 0
|
|
72
|
+
const newItems = []
|
|
73
|
+
for(let i = 0 ; i < count ; i++){
|
|
74
|
+
newItems.push({
|
|
75
|
+
createdAt: currentTime.toISOString()
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
this.items.push(...newItems)*/
|
|
79
|
+
|
|
80
|
+
/*window.setTimeout(() => {
|
|
81
|
+
this.play()
|
|
82
|
+
}, 1000)*/
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
data(){
|
|
88
|
+
return {
|
|
89
|
+
labels: [],
|
|
90
|
+
groupedData: {},
|
|
91
|
+
// items: []
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
mounted() {
|
|
96
|
+
|
|
97
|
+
//this.setInitialData()
|
|
98
|
+
|
|
99
|
+
this.play()
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
computed: {
|
|
103
|
+
|
|
104
|
+
columnKey(){
|
|
105
|
+
return this.options.bar.rows[0].key
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
interval(){
|
|
109
|
+
return this.options.bar.rows[0].format
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
groupedItems(){
|
|
113
|
+
console.log('#1', this.columnKey)
|
|
114
|
+
return groupBy(this.items, (item) => {
|
|
115
|
+
return dayjs(item[this.columnKey]).format('YYYYMMDDHHmm')
|
|
116
|
+
})
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
data(){
|
|
120
|
+
const arr = []
|
|
121
|
+
for(let i = 0 ; i < this.labels.length ; i++){
|
|
122
|
+
arr.push((this.groupedItems[this.labels[i]] ?? []).length)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/*if(Array.isArray(this.labels))
|
|
126
|
+
console.log(this.labels[0], this.labels[this.labels.length - 1], Object.keys(this.groupedItems), arr)*/
|
|
127
|
+
|
|
128
|
+
return arr
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
chartData() {
|
|
132
|
+
return {
|
|
133
|
+
labels: this.labels,
|
|
134
|
+
datasets: [ { data: this.data } ],
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
chartOptions() {
|
|
139
|
+
|
|
140
|
+
var style = getComputedStyle(document.body)
|
|
141
|
+
var gridColor = style.getPropertyValue('--text-50')
|
|
142
|
+
var gridColor2 = style.getPropertyValue('--text-200')
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
responsive: true,
|
|
146
|
+
maintainAspectRatio: false,
|
|
147
|
+
animation: false,
|
|
148
|
+
plugins: {
|
|
149
|
+
legend: {
|
|
150
|
+
display: false, // Disable the legend
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
scales: {
|
|
154
|
+
x: {
|
|
155
|
+
display: false, // Disable x-axis labels
|
|
156
|
+
grid: {
|
|
157
|
+
display: true,
|
|
158
|
+
color: function(context){
|
|
159
|
+
return `rgb(${gridColor2})`
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
y: {
|
|
164
|
+
beginAtZero: true, // Adjust y-axis as needed
|
|
165
|
+
grid: {
|
|
166
|
+
display: true,
|
|
167
|
+
color: function(context){
|
|
168
|
+
return `rgb(${gridColor})`
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
</script>
|
|
181
|
+
|
|
182
|
+
<style module>
|
|
183
|
+
|
|
184
|
+
.comp{
|
|
185
|
+
@apply flex-1;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.chart{
|
|
189
|
+
position: relative;
|
|
190
|
+
width: 100%;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
</style>
|
|
@@ -88,8 +88,9 @@
|
|
|
88
88
|
</Textbox>
|
|
89
89
|
</div>
|
|
90
90
|
|
|
91
|
-
<div v-if="presetSummary
|
|
91
|
+
<div v-if="presetSummary" class="h-[300px] flex" :class="presetSummary.mode === 'liveBar' ? 'max-h-[20vh]' : 'max-h-[30vh]'">
|
|
92
92
|
<Bar v-if="presetSummary.mode === 'bar'" :data="chartData" :options="chartOptions" class="flex-1 w-full p-2"/>
|
|
93
|
+
<ChartBar v-else-if="presetSummary.mode === 'liveBar'" :items="items" :options="presetSummary" class="flex-1"/>
|
|
93
94
|
<Line v-else-if="presetSummary.mode === 'line'" :data="chartData" :options="chartOptions" class="flex-1 w-full p-2"/>
|
|
94
95
|
<VirtualTable v-else-if="presetSummary.mode === 'table'" :items="summaryItems" :columns="summaryColumns" class="flex-1"></VirtualTable>
|
|
95
96
|
<Gmaps v-else-if="presetSummary.mode === 'map'" :data="summary.items" :config="presetSummary.map"
|
|
@@ -345,6 +346,8 @@ export default{
|
|
|
345
346
|
break
|
|
346
347
|
}
|
|
347
348
|
|
|
349
|
+
itemsPerPage = 300
|
|
350
|
+
|
|
348
351
|
this.socketEmit2(this.src, { columns:this.config.columns, preset:this.preset, itemsPerPage })
|
|
349
352
|
.then((res) => {
|
|
350
353
|
Object.assign(this.$data, res)
|
|
@@ -411,6 +414,7 @@ export default{
|
|
|
411
414
|
switch(event){
|
|
412
415
|
|
|
413
416
|
case 'create':
|
|
417
|
+
case 'bulk-create':
|
|
414
418
|
case 'update':
|
|
415
419
|
if(items[0] && Object.keys(items[0]).length <= 1 && Object.keys(items[0])[0] === 'uid'){
|
|
416
420
|
this.socketEmit2(this.src, {
|
|
@@ -596,6 +600,7 @@ export default{
|
|
|
596
600
|
},
|
|
597
601
|
|
|
598
602
|
chartOptions(){
|
|
603
|
+
if(!this.summary) return {}
|
|
599
604
|
|
|
600
605
|
var style = getComputedStyle(document.body)
|
|
601
606
|
var gridColor = style.getPropertyValue('--text-50')
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
</Dropdown>
|
|
11
11
|
<Dropdown v-model="summary.bar.rows[0].format" class="w-[100px]">
|
|
12
12
|
<option value="">{{ $t('Default') }}</option>
|
|
13
|
+
<option value="hour">{{ $t('Hour') }}</option>
|
|
13
14
|
<option value="date">{{ $t('Date') }}</option>
|
|
14
15
|
<option value="month">{{ $t('Month') }}</option>
|
|
15
16
|
<option value="quarter">{{ $t('Quarterly') }}</option>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="$style.comp">
|
|
3
|
+
|
|
4
|
+
<div class="p-3">
|
|
5
|
+
<label class="text-text-400 flex-1">{{ $t('X-axis') }}</label>
|
|
6
|
+
<div class="flex flex-row mt-2 gap-2">
|
|
7
|
+
<Dropdown v-model="summary.bar.rows[0].key" class="flex-1">
|
|
8
|
+
<option value="" disabled selected>{{ $t('Add Column') }}</option>
|
|
9
|
+
<option v-for="column in columns" :value="column.key">{{ column.label ?? column.key }}</option>
|
|
10
|
+
</Dropdown>
|
|
11
|
+
<Dropdown v-model="summary.bar.rows[0].format" class="w-[100px]">
|
|
12
|
+
<option value="">{{ $t('Default') }}</option>
|
|
13
|
+
<option value="second">{{ $t('Second') }}</option>
|
|
14
|
+
<option value="minute">{{ $t('Minute') }}</option>
|
|
15
|
+
<option value="hour">{{ $t('Hour') }}</option>
|
|
16
|
+
<option value="date">{{ $t('Date') }}</option>
|
|
17
|
+
<option value="month">{{ $t('Month') }}</option>
|
|
18
|
+
<option value="quarter">{{ $t('Quarterly') }}</option>
|
|
19
|
+
<option value="year">{{ $t('Year') }}</option>
|
|
20
|
+
</Dropdown>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
|
|
29
|
+
export default{
|
|
30
|
+
|
|
31
|
+
props: {
|
|
32
|
+
|
|
33
|
+
columns: Array,
|
|
34
|
+
|
|
35
|
+
summary: {
|
|
36
|
+
type: Object,
|
|
37
|
+
required: true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<style module>
|
|
47
|
+
|
|
48
|
+
.comp{
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
</style>
|
|
@@ -210,6 +210,7 @@
|
|
|
210
210
|
<Dropdown v-model="openedPresetSummary.mode" class="flex-1">
|
|
211
211
|
<option value="table">{{ $t('Table') }}</option>
|
|
212
212
|
<option value="bar">{{ $t('Bar Chart') }}</option>
|
|
213
|
+
<option value="liveBar">{{ $t('Live Bar Chart') }}</option>
|
|
213
214
|
<option value="line">{{ $t('Line Chart') }}</option>
|
|
214
215
|
<option value="map">{{ $t('Maps') }}</option>
|
|
215
216
|
</Dropdown>
|
|
@@ -225,6 +226,9 @@
|
|
|
225
226
|
<ListViewBarSummary v-else-if="openedPresetSummary.mode === 'bar'"
|
|
226
227
|
:summary="openedPresetSummary" :columns="filterableColumns" />
|
|
227
228
|
|
|
229
|
+
<ListViewLiveBarSummary v-else-if="openedPresetSummary.mode === 'liveBar'"
|
|
230
|
+
:summary="openedPresetSummary" :columns="filterableColumns" />
|
|
231
|
+
|
|
228
232
|
<ListViewLineSummary v-else-if="openedPresetSummary.mode === 'line'"
|
|
229
233
|
:summary="openedPresetSummary" :columns="filterableColumns" />
|
|
230
234
|
|
|
@@ -280,7 +280,7 @@ export default{
|
|
|
280
280
|
|
|
281
281
|
.slider>div:nth-child(3),
|
|
282
282
|
.slider>div:nth-child(4){
|
|
283
|
-
@apply absolute w-[2.
|
|
283
|
+
@apply absolute w-[2.3rem] h-[2.3rem] rounded-full bg-white shadow-sm border-[1px] border-text-200;
|
|
284
284
|
@apply flex;
|
|
285
285
|
top: 50%;
|
|
286
286
|
transform: translate3d(0, -50%, 0);
|
package/src/index.js
CHANGED
|
@@ -337,6 +337,7 @@ export default{
|
|
|
337
337
|
app.component('Block', defineAsyncComponent(() => import("./components/Block.vue")))
|
|
338
338
|
app.component('Button', defineAsyncComponent(() => import("./components/Button.vue")))
|
|
339
339
|
app.component('Box', defineAsyncComponent(() => import("./components/Box.vue")))
|
|
340
|
+
app.component('ChartBar', defineAsyncComponent(() => import("./components/ChartBar.vue")))
|
|
340
341
|
app.component('ColorPicker', defineAsyncComponent(() => import("./components/ColorPicker.vue")))
|
|
341
342
|
app.component('SearchButton', defineAsyncComponent(() => import("./components/SearchButton.vue")))
|
|
342
343
|
app.component('ChatTyping', defineAsyncComponent(() => import("./components/ChatTyping.vue")))
|
|
@@ -367,6 +368,7 @@ export default{
|
|
|
367
368
|
app.component('ListView', defineAsyncComponent(() => import("./components/ListView.vue")))
|
|
368
369
|
app.component('ListViewSettings', defineAsyncComponent(() => import("./components/ListViewSettings.vue")))
|
|
369
370
|
app.component('ListViewBarSummary', defineAsyncComponent(() => import("./components/ListViewBarSummary.vue")))
|
|
371
|
+
app.component('ListViewLiveBarSummary', defineAsyncComponent(() => import("./components/ListViewLiveBarSummary.vue")))
|
|
370
372
|
app.component('ListViewTableSummary', defineAsyncComponent(() => import("./components/ListViewTableSummary.vue")))
|
|
371
373
|
app.component('ListViewLineSummary', defineAsyncComponent(() => import("./components/ListViewLineSummary.vue")))
|
|
372
374
|
app.component('ListViewMapSummary', defineAsyncComponent(() => import("./components/ListViewMapSummary.vue")))
|
package/src/utils/listview.js
CHANGED
|
@@ -423,6 +423,12 @@ let ListView = {
|
|
|
423
423
|
const rowKey = row.key
|
|
424
424
|
const rowLabel = this.columns.find((_) => _.key === row.key).label
|
|
425
425
|
switch(row.format){
|
|
426
|
+
case 'minute':
|
|
427
|
+
attributes.push(`DATE_FORMAT(${rowKey}, '%Y-%m-%d %H:%i:00') as dfDate`)
|
|
428
|
+
group.push(`DATE_FORMAT(${rowKey}, '%Y-%m-%d %H:%i:00')`)
|
|
429
|
+
summaryColumns.push({ key:"dfDate", label:rowLabel, width:"200px", visible:true, type:"date", format:"HH:mm" })
|
|
430
|
+
break
|
|
431
|
+
|
|
426
432
|
case 'date':
|
|
427
433
|
attributes.push(`DATE_FORMAT(${rowKey}, '%Y-%m-%d') as dfDate`)
|
|
428
434
|
group.push(`DATE_FORMAT(${rowKey}, '%Y-%m-%d')`)
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="$style.comp" v-if="Array.isArray(items) && items.length > 0">
|
|
3
|
-
<pre></pre>
|
|
4
3
|
<div v-if="id" :id="id" :class="$style.anchor"></div>
|
|
5
4
|
<h3>{{ title ?? '' }}</h3>
|
|
6
5
|
<p v-if="description" class="mt-2 text-lg">{{ description }}</p>
|
|
7
6
|
<div :class="computedContainerClass">
|
|
8
7
|
<div v-for="item in items" class="flex gap-4" :class="computedItemClass">
|
|
9
8
|
<div>
|
|
10
|
-
<Image :src="imageUrl(item.imageUrl)" class="
|
|
9
|
+
<Image :src="imageUrl(item.imageUrl)" :class="`object-contain ${item.sizeClass}`" />
|
|
11
10
|
</div>
|
|
12
|
-
<div class="flex-1 flex flex-col gap-1">
|
|
13
|
-
<h5>{{ item.title
|
|
14
|
-
<p>{{ item.description
|
|
11
|
+
<div class="flex-1 flex flex-col gap-1" v-if="item.title || item.description">
|
|
12
|
+
<h5 v-if="item.title">{{ item.title }}</h5>
|
|
13
|
+
<p v-if="item.description">{{ item.description }}</p>
|
|
15
14
|
</div>
|
|
16
15
|
</div>
|
|
17
16
|
</div>
|
|
@@ -36,7 +35,7 @@ export default{
|
|
|
36
35
|
type: Array,
|
|
37
36
|
default: [ 2, 4 ]
|
|
38
37
|
},
|
|
39
|
-
variant: Array
|
|
38
|
+
variant: Array,
|
|
40
39
|
|
|
41
40
|
},
|
|
42
41
|
|
|
@@ -82,7 +81,7 @@ export default{
|
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
.container{
|
|
85
|
-
@apply grid gap-6 mt-
|
|
84
|
+
@apply grid gap-6 mt-4;
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
.item{
|
|
@@ -139,6 +139,27 @@
|
|
|
139
139
|
<Textarea v-model="context.image.description" rows="3" placeholder="Description" />
|
|
140
140
|
</div>
|
|
141
141
|
|
|
142
|
+
<div class="flex flex-col gap-1">
|
|
143
|
+
<label class="flex-1 text-text-400">Size</label>
|
|
144
|
+
<Dropdown v-model="context.image.sizeClass" class="w-[100px]">
|
|
145
|
+
<option value="">Unset</option>
|
|
146
|
+
<option value="w-1">1</option>
|
|
147
|
+
<option value="w-2">2</option>
|
|
148
|
+
<option value="w-3">3</option>
|
|
149
|
+
<option value="w-4">4</option>
|
|
150
|
+
<option value="w-5">5</option>
|
|
151
|
+
<option value="w-6">6</option>
|
|
152
|
+
<option value="w-8">8</option>
|
|
153
|
+
<option value="w-12">12</option>
|
|
154
|
+
<option value="w-16">16</option>
|
|
155
|
+
<option value="w-20">20</option>
|
|
156
|
+
<option value="w-28">28</option>
|
|
157
|
+
<option value="w-32">32</option>
|
|
158
|
+
<option value="w-36">36</option>
|
|
159
|
+
<option value="w-48">48</option>
|
|
160
|
+
</Dropdown>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
142
163
|
</div>
|
|
143
164
|
</template>
|
|
144
165
|
</Modal>
|