@mixd-id/web-scaffold 0.1.230406001 → 0.1.230406002

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.230406001",
4
+ "version": "0.1.230406002",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -33,7 +33,7 @@
33
33
  :class="[ selectedIndex === ((item && item.id) ? item.id : visibleStartIndex + index) ? $style.trSelected : '', item._highlight ? $style.highlight : '' ].join(' ')">
34
34
  <td v-for="column in visibleColumns">
35
35
  <slot v-if="$slots[column.key]" :name="column.key" :column="column" :item="item" :index="visibleStartIndex + index"></slot>
36
- <div v-else :class="columnClass(column)" v-html="formatColumn(item[column.key ?? ''] ?? '', column)"></div>
36
+ <div v-else :class="columnClass(column)" v-html="formatColumn(item, column)"></div>
37
37
  </td>
38
38
  <td :class="$style.spacer"></td>
39
39
  </tr>
@@ -47,7 +47,7 @@
47
47
  <tr>
48
48
  <td v-for="column in columns" :style="thStyle(column)">
49
49
  <slot v-if="$slots[column.key]" :name="column.key" :column="column" :item="items[0]"></slot>
50
- <div v-else :class="columnClass(column)" v-html="formatColumn(items[0][column.key ?? ''] ?? '', column)"></div>
50
+ <div v-else :class="columnClass(column)" v-html="formatColumn(items[0] ?? {}, column)"></div>
51
51
  </td>
52
52
  <td :class="$style.spacer"></td>
53
53
  </tr>
@@ -312,7 +312,24 @@ export default{
312
312
  ]
313
313
  },
314
314
 
315
- formatColumn(value, column){
315
+ formatColumn(item, column){
316
+
317
+ let value
318
+ if(column.key.indexOf('.') > -1){
319
+ const columnKeys = column.key.split('.')
320
+ const columnAs = columnKeys[0]
321
+ const columnKey = columnKeys[1]
322
+
323
+ let columnValue = [];
324
+ (item[columnAs] ?? []).forEach((item) => {
325
+ columnValue.push(item[columnKey])
326
+ })
327
+
328
+ value = columnValue.join(',')
329
+ }
330
+ else{
331
+ value = item[column.key ?? ''] ?? ''
332
+ }
316
333
 
317
334
  if(this.appearances[column.key] && this.appearances[column.key].length){
318
335
  const formatted = this.appearances[column.key].filter((appearance) => {
@@ -438,6 +438,11 @@ let ListPage1 = {
438
438
  attributeIncludes = this.getAttributeIncludes(preset)
439
439
  }
440
440
 
441
+ let includes
442
+ if(this.getModelIncludes){
443
+ includes = this.getModelIncludes(preset)
444
+ }
445
+
441
446
  let attributes = { id:1, updatedAt:1 }
442
447
  if(preset.columns){
443
448
  let modelAttributes = this.model.getAttributes();
@@ -464,7 +469,7 @@ let ListPage1 = {
464
469
  attributes = Object.keys(attributes)
465
470
 
466
471
  if(preset.filters){
467
- const { where:presetWhere } = this.getPresetFilterParams(preset)
472
+ const { where:presetWhere } = this.getPresetFilterParams(preset, includes)
468
473
  where = {
469
474
  ...where,
470
475
  ...presetWhere
@@ -472,7 +477,7 @@ let ListPage1 = {
472
477
  }
473
478
 
474
479
  if(preset.sorts){
475
- const { order:presetOrder } = this.getPresetSortParams(preset)
480
+ const { order:presetOrder } = this.getPresetSortParams(preset, includes)
476
481
  if(presetOrder){
477
482
  order = presetOrder
478
483
  }
@@ -505,7 +510,7 @@ let ListPage1 = {
505
510
  order,
506
511
  limit: itemsPerPage + 1,
507
512
  replacements,
508
- include: this.getModelIncludes ? this.getModelIncludes(preset) : undefined,
513
+ include: includes,
509
514
  logging: (sql, queryObject, p) => {
510
515
  derivedSql = sql
511
516
  }
@@ -1033,7 +1038,7 @@ let ListPage1 = {
1033
1038
 
1034
1039
 
1035
1040
 
1036
- getPresetFilterParams(preset){
1041
+ getPresetFilterParams(preset, includes){
1037
1042
 
1038
1043
  let where = {}
1039
1044
  let replacements = []
@@ -1047,264 +1052,346 @@ let ListPage1 = {
1047
1052
  if(!filter.enabled) return
1048
1053
 
1049
1054
  const key = filter.key
1050
- const type = filter.type
1051
- const operand = filter.operand === 'or' ? 'or' : 'and'
1052
- const items = filter.filters ?? []
1053
-
1054
- let whereValue = []
1055
- switch(type){
1056
1055
 
1057
- case 'date':
1058
- items.forEach((item) => {
1059
- if(!('operator' in item) || (item.operator === 'between' && !('value' in item))) return
1060
-
1061
- const operator = item.operator
1062
- const value = item.value
1056
+ const whereValue = this.getWhereValue(filter)
1057
+ const operand = filter.operand === 'or' ? 'or' : 'and'
1063
1058
 
1064
- switch(operator){
1059
+ // Nested filter attribute
1060
+ if(key.indexOf('.') > -1){
1065
1061
 
1066
- case 'today':
1067
- whereValue = {
1068
- ...whereValue,
1069
- [Op.eq]: dayjs().format('YYYY-MM-DD'),
1062
+ const inclKeys = key.split('.')
1063
+ if(inclKeys.length !== 2){
1064
+ console.warn('Filter key not handled', key)
1065
+ }
1066
+ else{
1067
+ const inclAs = inclKeys[0]
1068
+ const inclKey = inclKeys[1]
1069
+ const inclIndex = (includes ?? []).findIndex((_) => _.as === inclAs)
1070
+ if(inclIndex > -1){
1071
+
1072
+ let includeWhere = includes[inclIndex].where ?? {}
1073
+
1074
+ switch(operand){
1075
+
1076
+ case 'or':
1077
+ includeWhere = {
1078
+ ...includeWhere,
1079
+ [inclKey]: {
1080
+ [Op.or]: whereValue
1081
+ }
1070
1082
  }
1071
1083
  break
1072
1084
 
1073
- case 'thisWeek':
1074
- whereValue = {
1075
- ...whereValue,
1076
- [Op.gte]: dayjs().startOf('week').format('YYYY-MM-DD 00:00:00'),
1077
- [Op.lt]: dayjs().endOf('week').format('YYYY-MM-DD 23:59:59'),
1085
+ default:
1086
+ includeWhere = {
1087
+ ...where,
1088
+ [inclKey]: {
1089
+ [Op.and]: whereValue
1090
+ }
1078
1091
  }
1079
1092
  break
1093
+ }
1080
1094
 
1081
- case 'weekAgo':
1082
- whereValue = {
1083
- ...whereValue,
1084
- [Op.gte]: dayjs().add(-1, 'week').format('YYYY-MM-DD 00:00:00'),
1085
- [Op.lt]: dayjs().format('YYYY-MM-DD 23:59:59'),
1086
- }
1087
- break
1095
+ includes[inclIndex].where = includeWhere
1096
+ }
1097
+ else{
1098
+ console.warn('Unsupported filter key', key)
1099
+ }
1100
+ }
1101
+ }
1088
1102
 
1089
- case 'thisMonth':
1090
- whereValue = {
1091
- ...whereValue,
1092
- [Op.gte]: dayjs().format('YYYY-MM-01 00:00:00'),
1093
- [Op.lt]: dayjs().endOf('month').format('YYYY-MM-DD 23:59:59'),
1094
- }
1095
- break
1103
+ // Unnested filter attribute
1104
+ else{
1105
+ switch(operand){
1096
1106
 
1097
- case 'monthAgo':
1098
- whereValue = {
1099
- ...whereValue,
1100
- [Op.gte]: dayjs().add(-1, 'month').format('YYYY-MM-DD 00:00:00'),
1101
- [Op.lt]: dayjs().format('YYYY-MM-DD 23:59:59'),
1102
- }
1103
- break
1107
+ case 'or':
1108
+ where = {
1109
+ ...where,
1110
+ [key]: {
1111
+ [Op.or]: whereValue
1112
+ }
1113
+ }
1114
+ break
1104
1115
 
1105
- case 'lastMonth':
1106
- whereValue = {
1107
- [Op.gte]: dayjs().add(-1, 'month').format('YYYY-MM-01 00:00:00'),
1108
- [Op.lte]: dayjs().add(-1, 'month').endOf('month').format('YYYY-MM-DD 23:59:59'),
1109
- }
1110
- break
1116
+ default:
1117
+ where = {
1118
+ ...where,
1119
+ [key]: {
1120
+ [Op.and]: whereValue
1121
+ }
1122
+ }
1123
+ break
1124
+ }
1125
+ }
1126
+ })
1127
+ }
1111
1128
 
1112
- case 'thisYear':
1113
- whereValue = {
1114
- ...whereValue,
1115
- [Op.gte]: dayjs().startOf('year').format('YYYY-MM-DD 00:00:00'),
1116
- [Op.lt]: dayjs().endOf('year').format('YYYY-MM-DD 23:59:59'),
1117
- }
1118
- break
1129
+ //console.log(util.inspect(where, false, null, true /* enable colors */))
1119
1130
 
1120
- case 'lastYear':
1121
- whereValue = {
1122
- ...whereValue,
1123
- [Op.gte]: dayjs().add(-1, 'year').startOf('year').format('YYYY-MM-DD 00:00:00'),
1124
- [Op.lt]: dayjs().add(-1, 'year').endOf('year').format('YYYY-MM-DD 23:59:59'),
1125
- }
1126
- break
1131
+ /*console.log(util.inspect(preset.filters, false, null, true /!* enable colors *!/))
1132
+ console.log(where)
1133
+ console.log(replacements)*/
1127
1134
 
1128
- case 'between':
1129
- whereValue = {
1130
- ...whereValue,
1131
- [Op.gte]: dayjs(value[0]).format('YYYY-MM-DD 00:00:00'),
1132
- [Op.lt]: dayjs(value[1]).format('YYYY-MM-DD 23:59:59'),
1133
- }
1134
- break
1135
- }
1136
- })
1137
- break
1135
+ return {
1136
+ where,
1137
+ replacements
1138
+ }
1139
+ },
1138
1140
 
1139
- case 'enum':
1140
- items.forEach((item) => {
1141
- if(!('value' in item)) return
1141
+ getWhereValue(filter){
1142
1142
 
1143
- const value = item.value ?? []
1144
- whereValue = {
1145
- ...whereValue,
1146
- [Op.in]: value
1147
- }
1148
- })
1149
- break
1143
+ let whereValue = []
1144
+ const type = filter.type
1145
+ const items = filter.filters ?? []
1146
+ switch(type){
1150
1147
 
1151
- case 'number':
1152
- case 'currency':
1153
- items.forEach((item) => {
1154
- if(!('operator' in item) || !('value' in item)) return
1148
+ case 'date':
1149
+ items.forEach((item) => {
1150
+ if(!('operator' in item) || (item.operator === 'between' && !('value' in item))) return
1155
1151
 
1156
- const operator = item.operator
1157
- const value = item.value
1152
+ const operator = item.operator
1153
+ const value = item.value
1158
1154
 
1159
- switch(operator){
1155
+ switch(operator){
1160
1156
 
1161
- case '>':
1162
- whereValue = {
1163
- ...whereValue,
1164
- [Op.gt]: parseFloat(value)
1165
- }
1166
- break
1157
+ case 'today':
1158
+ whereValue = {
1159
+ ...whereValue,
1160
+ [Op.eq]: dayjs().format('YYYY-MM-DD'),
1161
+ }
1162
+ break
1167
1163
 
1168
- case '>=':
1169
- whereValue = {
1170
- ...whereValue,
1171
- [Op.gte]: parseFloat(value)
1172
- }
1173
- break
1164
+ case 'thisWeek':
1165
+ whereValue = {
1166
+ ...whereValue,
1167
+ [Op.gte]: dayjs().startOf('week').format('YYYY-MM-DD 00:00:00'),
1168
+ [Op.lt]: dayjs().endOf('week').format('YYYY-MM-DD 23:59:59'),
1169
+ }
1170
+ break
1174
1171
 
1175
- case '=':
1176
- whereValue = {
1177
- ...whereValue,
1178
- [Op.eq]: parseFloat(value)
1179
- }
1180
- break
1172
+ case 'weekAgo':
1173
+ whereValue = {
1174
+ ...whereValue,
1175
+ [Op.gte]: dayjs().add(-1, 'week').format('YYYY-MM-DD 00:00:00'),
1176
+ [Op.lt]: dayjs().format('YYYY-MM-DD 23:59:59'),
1177
+ }
1178
+ break
1181
1179
 
1182
- case '<':
1183
- whereValue = {
1184
- ...whereValue,
1185
- [Op.lt]: parseFloat(value)
1186
- }
1187
- break
1180
+ case 'thisMonth':
1181
+ whereValue = {
1182
+ ...whereValue,
1183
+ [Op.gte]: dayjs().format('YYYY-MM-01 00:00:00'),
1184
+ [Op.lt]: dayjs().endOf('month').format('YYYY-MM-DD 23:59:59'),
1185
+ }
1186
+ break
1188
1187
 
1189
- case '<=':
1190
- whereValue = {
1191
- ...whereValue,
1192
- [Op.lte]: parseFloat(value)
1193
- }
1194
- break
1188
+ case 'monthAgo':
1189
+ whereValue = {
1190
+ ...whereValue,
1191
+ [Op.gte]: dayjs().add(-1, 'month').format('YYYY-MM-DD 00:00:00'),
1192
+ [Op.lt]: dayjs().format('YYYY-MM-DD 23:59:59'),
1195
1193
  }
1196
- })
1197
- break
1194
+ break
1198
1195
 
1199
- default:
1200
- items.forEach((item) => {
1201
- if(!('operator' in item) ||
1202
- ([ 'startsWith', 'endsWith', 'contains', '=' ].includes(item.operator) && !'value' in item))
1203
- return
1196
+ case 'lastMonth':
1197
+ whereValue = {
1198
+ [Op.gte]: dayjs().add(-1, 'month').format('YYYY-MM-01 00:00:00'),
1199
+ [Op.lte]: dayjs().add(-1, 'month').endOf('month').format('YYYY-MM-DD 23:59:59'),
1200
+ }
1201
+ break
1204
1202
 
1205
- const operator = item.operator
1206
- const value = item.value
1203
+ case 'thisYear':
1204
+ whereValue = {
1205
+ ...whereValue,
1206
+ [Op.gte]: dayjs().startOf('year').format('YYYY-MM-DD 00:00:00'),
1207
+ [Op.lt]: dayjs().endOf('year').format('YYYY-MM-DD 23:59:59'),
1208
+ }
1209
+ break
1207
1210
 
1208
- switch(operator){
1211
+ case 'lastYear':
1212
+ whereValue = {
1213
+ ...whereValue,
1214
+ [Op.gte]: dayjs().add(-1, 'year').startOf('year').format('YYYY-MM-DD 00:00:00'),
1215
+ [Op.lt]: dayjs().add(-1, 'year').endOf('year').format('YYYY-MM-DD 23:59:59'),
1216
+ }
1217
+ break
1209
1218
 
1210
- case 'startsWith':
1211
- whereValue.push({
1212
- [Op.like]: `${value}%`
1213
- })
1214
- break
1219
+ case 'between':
1220
+ whereValue = {
1221
+ ...whereValue,
1222
+ [Op.gte]: dayjs(value[0]).format('YYYY-MM-DD 00:00:00'),
1223
+ [Op.lt]: dayjs(value[1]).format('YYYY-MM-DD 23:59:59'),
1224
+ }
1225
+ break
1226
+ }
1227
+ })
1228
+ break
1215
1229
 
1216
- case 'endsWith':
1217
- whereValue.push({
1218
- [Op.like]: `%${value}`
1219
- })
1220
- break
1230
+ case 'enum':
1231
+ items.forEach((item) => {
1232
+ if(!('value' in item)) return
1221
1233
 
1222
- case 'contains':
1223
- whereValue.push({
1224
- [Op.like]: `%${value}%`
1225
- })
1226
- break
1234
+ const value = item.value ?? []
1235
+ whereValue = {
1236
+ ...whereValue,
1237
+ [Op.in]: value
1238
+ }
1239
+ })
1240
+ break
1227
1241
 
1228
- case '=':
1229
- whereValue.push({
1230
- [Op.eq]: value
1231
- })
1232
- break
1242
+ case 'number':
1243
+ case 'currency':
1244
+ items.forEach((item) => {
1245
+ if(!('operator' in item) || !('value' in item)) return
1233
1246
 
1234
- case 'empty':
1235
- whereValue.push({
1236
- [Op.or]: [
1237
- { [Op.eq]: null },
1238
- { [Op.eq]: '' },
1239
- ]
1240
- })
1241
- break
1247
+ const operator = item.operator
1248
+ const value = item.value
1242
1249
 
1243
- case 'notEmpty':
1244
- whereValue.push({
1245
- [Op.and]: [
1246
- { [Op.ne]: null },
1247
- { [Op.ne]: '' },
1248
- ]
1249
- })
1250
- break
1250
+ switch(operator){
1251
1251
 
1252
- case 'length':
1253
- break
1252
+ case '>':
1253
+ whereValue = {
1254
+ ...whereValue,
1255
+ [Op.gt]: parseFloat(value)
1256
+ }
1257
+ break
1254
1258
 
1255
- case 'regex':
1256
- whereValue.push({
1257
- [Op.regexp]: value
1258
- })
1259
- break
1259
+ case '>=':
1260
+ whereValue = {
1261
+ ...whereValue,
1262
+ [Op.gte]: parseFloat(value)
1260
1263
  }
1261
- })
1262
- break
1263
- }
1264
+ break
1264
1265
 
1265
- switch(operand){
1266
+ case '=':
1267
+ whereValue = {
1268
+ ...whereValue,
1269
+ [Op.eq]: parseFloat(value)
1270
+ }
1271
+ break
1266
1272
 
1267
- case 'or':
1268
- where = {
1269
- ...where,
1270
- [key]: {
1271
- [Op.or]: whereValue
1273
+ case '<':
1274
+ whereValue = {
1275
+ ...whereValue,
1276
+ [Op.lt]: parseFloat(value)
1272
1277
  }
1273
- }
1274
- break
1278
+ break
1275
1279
 
1276
- default:
1277
- where = {
1278
- ...where,
1279
- [key]: {
1280
- [Op.and]: whereValue
1280
+ case '<=':
1281
+ whereValue = {
1282
+ ...whereValue,
1283
+ [Op.lte]: parseFloat(value)
1281
1284
  }
1282
- }
1283
- break
1284
- }
1285
- })
1286
- }
1285
+ break
1286
+ }
1287
+ })
1288
+ break
1287
1289
 
1288
- //console.log(util.inspect(where, false, null, true /* enable colors */))
1290
+ default:
1291
+ items.forEach((item) => {
1292
+ if(!('operator' in item) ||
1293
+ ([ 'startsWith', 'endsWith', 'contains', '=' ].includes(item.operator) && !'value' in item))
1294
+ return
1289
1295
 
1290
- /*console.log(util.inspect(preset.filters, false, null, true /!* enable colors *!/))
1291
- console.log(where)
1292
- console.log(replacements)*/
1296
+ const operator = item.operator
1297
+ const value = item.value
1293
1298
 
1294
- return {
1295
- where,
1296
- replacements
1299
+ switch(operator){
1300
+
1301
+ case 'startsWith':
1302
+ whereValue.push({
1303
+ [Op.like]: `${value}%`
1304
+ })
1305
+ break
1306
+
1307
+ case 'endsWith':
1308
+ whereValue.push({
1309
+ [Op.like]: `%${value}`
1310
+ })
1311
+ break
1312
+
1313
+ case 'contains':
1314
+ whereValue.push({
1315
+ [Op.like]: `%${value}%`
1316
+ })
1317
+ break
1318
+
1319
+ case '=':
1320
+ whereValue.push({
1321
+ [Op.eq]: value
1322
+ })
1323
+ break
1324
+
1325
+ case 'empty':
1326
+ whereValue.push({
1327
+ [Op.or]: [
1328
+ { [Op.eq]: null },
1329
+ { [Op.eq]: '' },
1330
+ ]
1331
+ })
1332
+ break
1333
+
1334
+ case 'notEmpty':
1335
+ whereValue.push({
1336
+ [Op.and]: [
1337
+ { [Op.ne]: null },
1338
+ { [Op.ne]: '' },
1339
+ ]
1340
+ })
1341
+ break
1342
+
1343
+ case 'length':
1344
+ break
1345
+
1346
+ case 'regex':
1347
+ whereValue.push({
1348
+ [Op.regexp]: value
1349
+ })
1350
+ break
1351
+ }
1352
+ })
1353
+ break
1297
1354
  }
1355
+
1356
+ return whereValue
1298
1357
  },
1299
1358
 
1300
- getPresetSortParams(preset){
1359
+ getPresetSortParams(preset, includes){
1301
1360
 
1302
1361
  if(preset.sorts && preset.sorts.length > 0){
1303
1362
  let order = []
1304
1363
  preset.sorts.forEach((sort) => {
1305
1364
  const key = sort.key
1306
1365
  const type = sort.type === 'desc' ? 'desc' : 'asc'
1307
- order.push([ key, type ])
1366
+ if(key.indexOf('.') > -1){
1367
+
1368
+ const inclKeys = key.split('.')
1369
+ if(inclKeys.length !== 2){
1370
+ console.warn('Filter key not handled', key)
1371
+ }
1372
+ else {
1373
+ const inclAs = inclKeys[0]
1374
+ const inclKey = inclKeys[1]
1375
+ const inclIndex = (includes ?? []).findIndex((_) => _.as === inclAs)
1376
+
1377
+ if(inclIndex > -1){
1378
+ order.push([
1379
+ {
1380
+ model: includes[inclIndex].model,
1381
+ as: inclAs
1382
+ },
1383
+ inclKey,
1384
+ type
1385
+ ])
1386
+ }
1387
+ else{
1388
+ console.warn('Unsupported sort key', key)
1389
+ }
1390
+ }
1391
+ }
1392
+ else{
1393
+ order.push([ key, type ])
1394
+ }
1308
1395
  })
1309
1396
  order.push([ 'id', 'desc' ])
1310
1397