@mixd-id/web-scaffold 0.1.250801006 → 0.1.250801008
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/MultiDropdown.vue +15 -11
- package/src/components/VirtualTable.vue +2 -3
- package/src/utils/list.mjs +112 -54
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="$style.dropdown">
|
|
3
|
-
<div ref="btn" class="flex flex-row items-center w-[150px]"
|
|
3
|
+
<div ref="btn" class="flex-1 flex flex-row items-center w-[150px]"
|
|
4
4
|
:class="containerClass"
|
|
5
5
|
@click="open()">
|
|
6
6
|
<div class="flex-1 p-2 text-ellipsis-nowrap">
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
</button>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
|
-
<ContextMenu ref="contextMenu"
|
|
15
|
+
<ContextMenu ref="contextMenu" class="mt-2">
|
|
16
16
|
<div class="flex flex-col min-w-[200px]">
|
|
17
|
-
<div class="p-2">
|
|
17
|
+
<div class="p-2" v-if="viewedItems.length > 10">
|
|
18
18
|
<Textbox v-model="search" :clearable="true" @clear="search = ''">
|
|
19
19
|
<template #start>
|
|
20
20
|
<div class="pl-2">
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
</template>
|
|
24
24
|
</Textbox>
|
|
25
25
|
</div>
|
|
26
|
-
<div v-for="item in viewedItems" class="p-2">
|
|
26
|
+
<div v-for="item in viewedItems" class="p-2" @click.stop>
|
|
27
27
|
<Checkbox :value="item[valueKey]" v-model="selectedItems">
|
|
28
28
|
{{ item[textKey] }}
|
|
29
29
|
</Checkbox>
|
|
@@ -40,7 +40,12 @@ export default{
|
|
|
40
40
|
props: {
|
|
41
41
|
containerClass: String,
|
|
42
42
|
|
|
43
|
-
modelValue:
|
|
43
|
+
modelValue: {
|
|
44
|
+
type: Array,
|
|
45
|
+
validator(value){
|
|
46
|
+
return Array.isArray(value)
|
|
47
|
+
}
|
|
48
|
+
},
|
|
44
49
|
|
|
45
50
|
items: Array,
|
|
46
51
|
|
|
@@ -58,15 +63,15 @@ export default{
|
|
|
58
63
|
computed: {
|
|
59
64
|
|
|
60
65
|
selectedText(){
|
|
61
|
-
if(this.modelValue.length > 0)
|
|
66
|
+
if((this.modelValue ?? []).length > 0)
|
|
62
67
|
return this.modelValue.map(_ => _[this.textKey] ?? _[this.valueKey]).join(', ')
|
|
63
68
|
return this.$t('(Not Selected)')
|
|
64
69
|
},
|
|
65
70
|
|
|
66
71
|
viewedItems(){
|
|
67
72
|
if(this.search !== '')
|
|
68
|
-
return this.items.filter(_ => `${_[this.textKey]}`.toLowerCase().indexOf(this.search.toLowerCase()) >= 0)
|
|
69
|
-
return this.items
|
|
73
|
+
return (this.items ?? []).filter(_ => `${_[this.textKey]}`.toLowerCase().indexOf(this.search.toLowerCase()) >= 0)
|
|
74
|
+
return this.items ?? []
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
},
|
|
@@ -81,7 +86,7 @@ export default{
|
|
|
81
86
|
methods: {
|
|
82
87
|
|
|
83
88
|
open(){
|
|
84
|
-
this.selectedItems = this.modelValue.map(_ => _[this.valueKey])
|
|
89
|
+
this.selectedItems = (this.modelValue ?? []).map(_ => _[this.valueKey])
|
|
85
90
|
this.$refs.contextMenu.open(this.$refs.btn)
|
|
86
91
|
}
|
|
87
92
|
|
|
@@ -92,8 +97,7 @@ export default{
|
|
|
92
97
|
selectedItems: {
|
|
93
98
|
deep: true,
|
|
94
99
|
handler(_items){
|
|
95
|
-
this.$emit('update:modelValue',
|
|
96
|
-
this.items.filter(_ => _items.includes(_[this.valueKey]))
|
|
100
|
+
this.$emit('update:modelValue', (this.items ?? []).filter(_ => _items.includes(_[this.valueKey]))
|
|
97
101
|
)
|
|
98
102
|
}
|
|
99
103
|
}
|
|
@@ -207,7 +207,7 @@ const _DEFAULT_COLUMN_WIDTH = '100px'
|
|
|
207
207
|
|
|
208
208
|
export default{
|
|
209
209
|
|
|
210
|
-
inject: [ 'emitRoot'
|
|
210
|
+
inject: [ 'emitRoot' ],
|
|
211
211
|
|
|
212
212
|
emits: [ 'dragover', 'freeze', 'unfreeze', 'scroll-end', 'item-click' ],
|
|
213
213
|
|
|
@@ -685,8 +685,7 @@ export default{
|
|
|
685
685
|
|
|
686
686
|
return [
|
|
687
687
|
this.$style.tdDiv,
|
|
688
|
-
this.$style['align-' + align]
|
|
689
|
-
this.listStyle ? this.listStyle[appearanceClass] : ''
|
|
688
|
+
this.$style['align-' + align]
|
|
690
689
|
]
|
|
691
690
|
.join(' ')
|
|
692
691
|
},
|
package/src/utils/list.mjs
CHANGED
|
@@ -366,34 +366,57 @@ const getValue = (filter, opt) => {
|
|
|
366
366
|
return whereObj
|
|
367
367
|
}
|
|
368
368
|
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
369
|
+
const getColumnTypeFromModelAttribute = (attribute, opt) => {
|
|
370
|
+
const { DataTypes } = opt?.Sequelize ?? Sequelize
|
|
371
|
+
|
|
372
|
+
switch(attribute.type.key){
|
|
373
|
+
case DataTypes.BOOLEAN.key:
|
|
374
|
+
return 'boolean'
|
|
375
|
+
|
|
376
|
+
case DataTypes.INTEGER.key:
|
|
377
|
+
case DataTypes.FLOAT.key:
|
|
378
|
+
case DataTypes.DOUBLE.key:
|
|
379
|
+
case DataTypes.DECIMAL.key:
|
|
380
|
+
return 'number'
|
|
381
|
+
|
|
382
|
+
case DataTypes.DATE.key:
|
|
383
|
+
case DataTypes.DATEONLY.key:
|
|
384
|
+
return 'date'
|
|
385
|
+
|
|
386
|
+
default:
|
|
387
|
+
return 'string'
|
|
375
388
|
}
|
|
389
|
+
}
|
|
376
390
|
|
|
391
|
+
const filtersToSequelizeWhere = async(filters, opt) => {
|
|
377
392
|
let whereArr = []
|
|
378
393
|
let replacements = []
|
|
379
394
|
const { literal, Op } = opt.Sequelize ?? Sequelize
|
|
395
|
+
const { columns = [] } = opt?.config ?? {}
|
|
396
|
+
const modelAttributes = opt.model.getAttributes()
|
|
397
|
+
const tableName = opt.model.getTableName()
|
|
398
|
+
|
|
399
|
+
if(columns.length < 1){
|
|
400
|
+
for(let key in modelAttributes){
|
|
401
|
+
columns.push({
|
|
402
|
+
key,
|
|
403
|
+
fieldName: modelAttributes[key]?.fieldName || key,
|
|
404
|
+
type: getColumnTypeFromModelAttribute(modelAttributes[key], opt)
|
|
405
|
+
})
|
|
406
|
+
}
|
|
407
|
+
}
|
|
380
408
|
|
|
381
|
-
const
|
|
409
|
+
const keyColumns = (columns ?? []).reduce((res, cur) => {
|
|
410
|
+
res[cur.key] = cur
|
|
411
|
+
cur.fieldName = modelAttributes[cur.key]?.fieldName || cur.key
|
|
412
|
+
return res
|
|
413
|
+
}, {})
|
|
382
414
|
|
|
383
|
-
|
|
384
|
-
let { key, operator, value, fn:filterFn } = filter
|
|
385
|
-
const
|
|
386
|
-
const type = ((keyColumns[key] ?? [])[0] ?? {}).type
|
|
415
|
+
const getValue = (filter) => {
|
|
416
|
+
let { key, operator, value, fn:filterFn, fieldName } = filter
|
|
417
|
+
const type = (keyColumns[key] ?? {}).type ?? 'string'
|
|
387
418
|
|
|
388
419
|
let whereObj = {}
|
|
389
|
-
let Model, field
|
|
390
|
-
if(opt.model){
|
|
391
|
-
const modelAttributes = opt.model.getAttributes()
|
|
392
|
-
if(modelAttributes[key]){
|
|
393
|
-
Model = opt.model
|
|
394
|
-
field = modelAttributes[key].field
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
420
|
|
|
398
421
|
switch(type){
|
|
399
422
|
|
|
@@ -539,7 +562,7 @@ const filtersToSequelizeWhere = async(filters, opt) => {
|
|
|
539
562
|
switch(filterFn) {
|
|
540
563
|
|
|
541
564
|
case 'format_hour':
|
|
542
|
-
whereObj = literal(`DATE_FORMAT(${
|
|
565
|
+
whereObj = literal(`DATE_FORMAT(${tableName}.${fieldName}, "%H") < "${filter.value}"`)
|
|
543
566
|
break
|
|
544
567
|
|
|
545
568
|
default:
|
|
@@ -557,7 +580,7 @@ const filtersToSequelizeWhere = async(filters, opt) => {
|
|
|
557
580
|
switch(filterFn) {
|
|
558
581
|
|
|
559
582
|
case 'format_hour':
|
|
560
|
-
whereObj = literal(`DATE_FORMAT(${
|
|
583
|
+
whereObj = literal(`DATE_FORMAT(${tableName}.${fieldName}, "%H") <= "${filter.value}"`)
|
|
561
584
|
break
|
|
562
585
|
|
|
563
586
|
default:
|
|
@@ -575,19 +598,19 @@ const filtersToSequelizeWhere = async(filters, opt) => {
|
|
|
575
598
|
switch(filterFn) {
|
|
576
599
|
|
|
577
600
|
case 'format_date':
|
|
578
|
-
whereObj = literal(`DATE_FORMAT(${
|
|
601
|
+
whereObj = literal(`DATE_FORMAT(${tableName}.${fieldName}, "%Y-%m-%d") = "${filter.value}"`)
|
|
579
602
|
break
|
|
580
603
|
|
|
581
604
|
case 'format_hour':
|
|
582
|
-
whereObj = literal(`DATE_FORMAT(${
|
|
605
|
+
whereObj = literal(`DATE_FORMAT(${tableName}.${fieldName}, "%H") = "${filter.value}"`)
|
|
583
606
|
break
|
|
584
607
|
|
|
585
608
|
case 'format_month':
|
|
586
|
-
whereObj = literal(`DATE_FORMAT(${
|
|
609
|
+
whereObj = literal(`DATE_FORMAT(${tableName}.${fieldName}, "%m") = "${filter.value.split('-')[1]}"`)
|
|
587
610
|
break
|
|
588
611
|
|
|
589
612
|
case 'format_year':
|
|
590
|
-
whereObj = literal(`DATE_FORMAT(${
|
|
613
|
+
whereObj = literal(`DATE_FORMAT(${tableName}.${fieldName}, "%Y") = "${filter.value}"`)
|
|
591
614
|
break
|
|
592
615
|
|
|
593
616
|
default:
|
|
@@ -606,7 +629,7 @@ const filtersToSequelizeWhere = async(filters, opt) => {
|
|
|
606
629
|
switch(filterFn) {
|
|
607
630
|
|
|
608
631
|
case 'format_hour':
|
|
609
|
-
whereObj = literal(`DATE_FORMAT(${
|
|
632
|
+
whereObj = literal(`DATE_FORMAT(${tableName}.${fieldName}, "%H") > "${filter.value}"`)
|
|
610
633
|
break
|
|
611
634
|
|
|
612
635
|
default:
|
|
@@ -624,7 +647,7 @@ const filtersToSequelizeWhere = async(filters, opt) => {
|
|
|
624
647
|
switch(filterFn) {
|
|
625
648
|
|
|
626
649
|
case 'format_hour':
|
|
627
|
-
whereObj = literal(`DATE_FORMAT(${
|
|
650
|
+
whereObj = literal(`DATE_FORMAT(${tableName}.${fieldName}, "%H") >= "${filter.value}"`)
|
|
628
651
|
break
|
|
629
652
|
|
|
630
653
|
default:
|
|
@@ -736,41 +759,74 @@ const filtersToSequelizeWhere = async(filters, opt) => {
|
|
|
736
759
|
return whereObj
|
|
737
760
|
}
|
|
738
761
|
|
|
739
|
-
|
|
740
|
-
|
|
762
|
+
if(Array.isArray(filters)){
|
|
763
|
+
for(let filter of filters) {
|
|
764
|
+
if (filter.enabled === false) continue
|
|
741
765
|
|
|
742
|
-
|
|
766
|
+
const { key, value, modifier = 'and' } = filter
|
|
743
767
|
|
|
744
|
-
|
|
768
|
+
if(!keyColumns[key]) continue
|
|
745
769
|
|
|
746
|
-
|
|
770
|
+
if(Array.isArray(value)){
|
|
747
771
|
|
|
748
|
-
|
|
772
|
+
const modifierValue = []
|
|
749
773
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
774
|
+
for(let _value of value){
|
|
775
|
+
modifierValue.push(getValue({
|
|
776
|
+
..._value,
|
|
777
|
+
key
|
|
778
|
+
}, opt))
|
|
779
|
+
}
|
|
756
780
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
781
|
+
switch(modifier){
|
|
782
|
+
case 'or':
|
|
783
|
+
whereArr.push({
|
|
784
|
+
[Op.or]: modifierValue
|
|
785
|
+
})
|
|
786
|
+
break
|
|
763
787
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
788
|
+
default:
|
|
789
|
+
whereArr.push({
|
|
790
|
+
[Op.and]: modifierValue
|
|
791
|
+
})
|
|
792
|
+
break
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
else{
|
|
796
|
+
whereArr.push(getValue(filter, opt))
|
|
769
797
|
}
|
|
770
798
|
}
|
|
771
|
-
|
|
772
|
-
|
|
799
|
+
}
|
|
800
|
+
else if(filters && typeof filters === 'object'){
|
|
801
|
+
|
|
802
|
+
for(let key in filters){
|
|
803
|
+
if(!keyColumns[key]) continue
|
|
804
|
+
|
|
805
|
+
const value = filters[key]
|
|
806
|
+
|
|
807
|
+
if(Array.isArray(value)){
|
|
808
|
+
const modifierValue = []
|
|
809
|
+
|
|
810
|
+
for(let _value of value){
|
|
811
|
+
modifierValue.push(getValue({
|
|
812
|
+
..._value,
|
|
813
|
+
key
|
|
814
|
+
}, opt))
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
whereArr.push({
|
|
818
|
+
[Op.and]: modifierValue
|
|
819
|
+
})
|
|
820
|
+
}
|
|
821
|
+
else{
|
|
822
|
+
whereArr.push(getValue({
|
|
823
|
+
key,
|
|
824
|
+
operator: '=',
|
|
825
|
+
value
|
|
826
|
+
}, opt))
|
|
827
|
+
}
|
|
773
828
|
}
|
|
829
|
+
|
|
774
830
|
}
|
|
775
831
|
|
|
776
832
|
return {
|
|
@@ -1305,7 +1361,8 @@ const presetToSequelizeList = async(preset, opt = {}) => {
|
|
|
1305
1361
|
replacements: initialReplacements,
|
|
1306
1362
|
include,
|
|
1307
1363
|
order:initialOrder,
|
|
1308
|
-
logging = false
|
|
1364
|
+
logging = false,
|
|
1365
|
+
debug = false
|
|
1309
1366
|
} = opt
|
|
1310
1367
|
|
|
1311
1368
|
if(!model) return {}
|
|
@@ -1349,7 +1406,8 @@ const presetToSequelizeList = async(preset, opt = {}) => {
|
|
|
1349
1406
|
const { where:filterWhere, replacements:filterReplacements } = await filtersToSequelizeWhere(filters, {
|
|
1350
1407
|
config,
|
|
1351
1408
|
model,
|
|
1352
|
-
Sequelize: opt.Sequelize
|
|
1409
|
+
Sequelize: opt.Sequelize,
|
|
1410
|
+
debug
|
|
1353
1411
|
})
|
|
1354
1412
|
|
|
1355
1413
|
let searchWhere = {}, searchReplacements = []
|