@ramathibodi/nuxt-commons 4.0.11 → 4.0.13

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.
Files changed (52) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/dialog/ImportProgress.d.vue.ts +35 -0
  3. package/dist/runtime/components/dialog/ImportProgress.vue +53 -0
  4. package/dist/runtime/components/dialog/ImportProgress.vue.d.ts +35 -0
  5. package/dist/runtime/components/document/TemplateBuilder.d.vue.ts +2 -2
  6. package/dist/runtime/components/document/TemplateBuilder.vue +113 -8
  7. package/dist/runtime/components/document/TemplateBuilder.vue.d.ts +2 -2
  8. package/dist/runtime/components/form/ActionPad.vue +1 -0
  9. package/dist/runtime/components/form/Birthdate.d.vue.ts +3 -3
  10. package/dist/runtime/components/form/Birthdate.vue.d.ts +3 -3
  11. package/dist/runtime/components/form/Date.vue +11 -6
  12. package/dist/runtime/components/form/Dialog.d.vue.ts +1 -5
  13. package/dist/runtime/components/form/Dialog.vue +1 -0
  14. package/dist/runtime/components/form/Dialog.vue.d.ts +1 -5
  15. package/dist/runtime/components/form/EditPad.vue +1 -0
  16. package/dist/runtime/components/form/Pad.d.vue.ts +24 -0
  17. package/dist/runtime/components/form/Pad.vue +11 -6
  18. package/dist/runtime/components/form/Pad.vue.d.ts +24 -0
  19. package/dist/runtime/components/form/Time.vue +10 -5
  20. package/dist/runtime/components/form/images/Edit.d.vue.ts +1 -3
  21. package/dist/runtime/components/form/images/Edit.vue.d.ts +1 -3
  22. package/dist/runtime/components/model/AutoRefreshChip.d.vue.ts +16 -0
  23. package/dist/runtime/components/model/AutoRefreshChip.vue +34 -0
  24. package/dist/runtime/components/model/AutoRefreshChip.vue.d.ts +16 -0
  25. package/dist/runtime/components/model/Pad.vue +2 -1
  26. package/dist/runtime/components/model/Table.d.vue.ts +158 -61
  27. package/dist/runtime/components/model/Table.vue +129 -7
  28. package/dist/runtime/components/model/Table.vue.d.ts +158 -61
  29. package/dist/runtime/components/model/iterator.d.vue.ts +198 -78
  30. package/dist/runtime/components/model/iterator.vue +140 -9
  31. package/dist/runtime/components/model/iterator.vue.d.ts +198 -78
  32. package/dist/runtime/composables/apiModel.d.ts +22 -3
  33. package/dist/runtime/composables/apiModel.js +27 -19
  34. package/dist/runtime/composables/autoRefresh.d.ts +42 -0
  35. package/dist/runtime/composables/autoRefresh.js +57 -0
  36. package/dist/runtime/composables/document/template.d.ts +61 -0
  37. package/dist/runtime/composables/document/template.js +60 -1
  38. package/dist/runtime/composables/document/validateTemplate.d.ts +62 -0
  39. package/dist/runtime/composables/document/validateTemplate.js +378 -0
  40. package/dist/runtime/composables/graphqlModel.d.ts +22 -3
  41. package/dist/runtime/composables/graphqlModel.js +27 -19
  42. package/dist/runtime/composables/graphqlModelOperation.d.ts +1 -0
  43. package/dist/runtime/composables/importProgress.d.ts +34 -0
  44. package/dist/runtime/composables/importProgress.js +50 -0
  45. package/dist/runtime/composables/modelAutoRefresh.d.ts +29 -0
  46. package/dist/runtime/composables/modelAutoRefresh.js +16 -0
  47. package/dist/runtime/composables/utils/validation.d.ts +4 -0
  48. package/dist/runtime/composables/utils/validation.js +2 -0
  49. package/dist/runtime/utils/virtualize.d.ts +15 -0
  50. package/dist/runtime/utils/virtualize.js +10 -0
  51. package/package.json +3 -2
  52. package/scripts/validate-document-template.mjs +158 -0
@@ -1,8 +1,10 @@
1
1
  <script setup>
2
- import { computed, nextTick, ref, useAttrs, useSlots, watch } from "vue";
2
+ import { computed, nextTick, ref, markRaw, useAttrs, useSlots, watch } from "vue";
3
+ import { useModelAutoRefresh } from "../../composables/modelAutoRefresh";
3
4
  import { VDataIterator } from "vuetify/components/VDataIterator";
4
5
  import { VDataTable } from "vuetify/components/VDataTable";
5
- import { omit } from "lodash-es";
6
+ import { omit, chunk } from "lodash-es";
7
+ import { shouldVirtualize, itemsPerRowForSpan } from "../../utils/virtualize";
6
8
  import { useGraphqlModel } from "../../composables/graphqlModel";
7
9
  import { useApiModel } from "../../composables/apiModel";
8
10
  import { usePerPagePreference } from "../../composables/perPagePreference";
@@ -39,6 +41,15 @@ const props = defineProps({
39
41
  api: { type: Boolean, required: false, default: false },
40
42
  perPageStorageKey: { type: String, required: false },
41
43
  perPageStorageEnabled: { type: Boolean, required: false, default: true },
44
+ autoRefresh: { type: [Number, Boolean], required: false, default: false },
45
+ autoRefreshDefault: { type: Number, required: false, default: 60 },
46
+ autoRefreshControl: { type: Boolean, required: false, default: true },
47
+ importConcurrency: { type: Number, required: false, default: 3 },
48
+ virtual: { type: Boolean, required: false, default: void 0 },
49
+ virtualThreshold: { type: Number, required: false, default: 500 },
50
+ virtualHeight: { type: [Number, String], required: false, default: "70vh" },
51
+ virtualItemHeight: { type: Number, required: false, default: 80 },
52
+ virtualItemsPerRow: { type: Number, required: false, default: void 0 },
42
53
  modelName: { type: String, required: true },
43
54
  modelKey: { type: String, required: false, default: "id" },
44
55
  modelBy: { type: Object, required: false, default: void 0 },
@@ -112,8 +123,24 @@ const {
112
123
  deleteItem,
113
124
  loadItems,
114
125
  reload,
115
- isLoading
126
+ isLoading,
127
+ importProgress
116
128
  } = props.api ? useApiModel(props) : useGraphqlModel(props);
129
+ const { autoRefresh, manualReload } = useModelAutoRefresh(props, {
130
+ reload,
131
+ isLoading,
132
+ isDialogOpen
133
+ });
134
+ const useVirtual = computed(() => shouldVirtualize(items.value.length, props.virtual, props.virtualThreshold));
135
+ const itemsPerRow = computed(() => {
136
+ if (props.virtualItemsPerRow && props.virtualItemsPerRow > 0) return props.virtualItemsPerRow;
137
+ const bp = display.name?.value;
138
+ const span = (bp === "xxl" && props.xxl !== false ? props.xxl : void 0) ?? (["xxl", "xl"].includes(bp) && props.xl !== false ? props.xl : void 0) ?? (["xxl", "xl", "lg"].includes(bp) && props.lg !== false ? props.lg : void 0) ?? (["xxl", "xl", "lg", "md"].includes(bp) && props.md !== false ? props.md : void 0) ?? (["xxl", "xl", "lg", "md", "sm"].includes(bp) && props.sm !== false ? props.sm : void 0) ?? props.cols;
139
+ return itemsPerRowForSpan(span);
140
+ });
141
+ function chunkRows(slotItems) {
142
+ return chunk([...slotItems ?? []], itemsPerRow.value);
143
+ }
117
144
  function openDialog(item) {
118
145
  currentItem.value = item;
119
146
  nextTick(() => {
@@ -158,7 +185,7 @@ watch(
158
185
  },
159
186
  { immediate: true }
160
187
  );
161
- const operation = ref({ openDialog, createItem, importItems, updateItem, deleteItem, reload, setSearch, canServerPageable, canServerSearch, canCreate, canUpdate, canDelete });
188
+ const operation = ref({ openDialog, createItem, importItems, updateItem, deleteItem, reload, setSearch, canServerPageable, canServerSearch, canCreate, canUpdate, canDelete, autoRefresh: markRaw(autoRefresh) });
162
189
  const computedInitialData = computed(() => {
163
190
  return Object.assign({}, props.initialData, props.modelBy);
164
191
  });
@@ -169,7 +196,7 @@ const computedSkeletonPerPage = computed(() => {
169
196
  watch(() => props.search, () => {
170
197
  search.value = props.search;
171
198
  }, { immediate: true });
172
- defineExpose({ reload, operation });
199
+ defineExpose({ reload, operation, autoRefresh, importProgress });
173
200
  </script>
174
201
 
175
202
  <template>
@@ -182,13 +209,14 @@ defineExpose({ reload, operation });
182
209
  :item-value="modelKey"
183
210
  :search="search"
184
211
  :loading="isLoading"
212
+ :transition="false"
185
213
  >
186
214
  <template #default="defaultProps" v-if="viewType.includes('iterator')">
187
215
  <slot
188
216
  v-bind="defaultProps"
189
217
  :operation="operation"
190
218
  >
191
- <v-container fluid>
219
+ <v-container fluid v-if="!useVirtual">
192
220
  <v-row>
193
221
  <v-col
194
222
  v-for="(item, index) in defaultProps.items"
@@ -208,6 +236,38 @@ defineExpose({ reload, operation });
208
236
  </v-col>
209
237
  </v-row>
210
238
  </v-container>
239
+ <v-virtual-scroll
240
+ v-else
241
+ :items="chunkRows(defaultProps.items)"
242
+ :item-height="props.virtualItemHeight"
243
+ :height="props.virtualHeight"
244
+ >
245
+ <template #default="{ item: rowItems }">
246
+ <!-- pt-0 pb-6: reproduce the grid's 24px row gap as bottom padding so the
247
+ measured virtual-row height includes it and VVirtualScroll spaces rows
248
+ the same as the non-virtual <v-row gap="24"> grid. -->
249
+ <v-container fluid class="pt-0 pb-6">
250
+ <v-row>
251
+ <v-col
252
+ v-for="(item, index) in rowItems"
253
+ :key="index"
254
+ :cols="cols"
255
+ :sm="sm"
256
+ :md="md"
257
+ :lg="lg"
258
+ :xl="xl"
259
+ :xxl="xxl"
260
+ >
261
+ <slot
262
+ name="item"
263
+ :item="item"
264
+ :operation="operation"
265
+ />
266
+ </v-col>
267
+ </v-row>
268
+ </v-container>
269
+ </template>
270
+ </v-virtual-scroll>
211
271
  </slot>
212
272
  </template>
213
273
  <template #loader="loaderProps" v-if="viewType.includes('iterator')">
@@ -256,16 +316,26 @@ defineExpose({ reload, operation });
256
316
  <VToolbarTitle class="pl-3">
257
317
  <slot
258
318
  name="title"
259
- :reload="reload"
319
+ :reload="manualReload"
260
320
  >
261
321
  {{ title }}
262
322
  <v-icon
263
323
  size="small"
264
- @click="reload"
324
+ @click="manualReload"
265
325
  >
266
326
  mdi mdi-refresh
267
327
  </v-icon>
268
328
  </slot>
329
+ <slot
330
+ name="autoRefreshControl"
331
+ v-bind="autoRefresh"
332
+ >
333
+ <ModelAutoRefreshChip
334
+ v-if="props.autoRefreshControl"
335
+ :control="autoRefresh"
336
+ :color="toolbarColor"
337
+ />
338
+ </slot>
269
339
  </VToolbarTitle>
270
340
  </v-col>
271
341
  <v-col cols="5">
@@ -320,7 +390,7 @@ defineExpose({ reload, operation });
320
390
  </slot>
321
391
  <template v-if="viewType.includes('table')">
322
392
  <v-data-table-server
323
- v-if="canServerPageable"
393
+ v-if="canServerPageable && !useVirtual"
324
394
  v-bind="plainAttrs"
325
395
  color="primary"
326
396
  :items="items"
@@ -362,6 +432,49 @@ defineExpose({ reload, operation });
362
432
  />
363
433
  </template>
364
434
  </v-data-table-server>
435
+ <v-data-table-virtual
436
+ v-else-if="useVirtual"
437
+ v-bind="plainAttrs"
438
+ color="primary"
439
+ :items="items"
440
+ :item-value="props.modelKey"
441
+ :search="search"
442
+ :loading="isLoading"
443
+ :height="props.virtualHeight"
444
+ fixed-header
445
+ >
446
+ <!-- @ts-ignore -->
447
+ <template
448
+ v-for="(_, name, index) in tableSlots"
449
+ :key="index"
450
+ #[name]="slotData"
451
+ >
452
+ <slot
453
+ :name="name"
454
+ v-bind="slotData || {}"
455
+ :operation="operation"
456
+ />
457
+ </template>
458
+ <template
459
+ v-if="!$slots['item.action']"
460
+ #item.action="{ item }"
461
+ >
462
+ <v-btn
463
+ v-if="canUpdate"
464
+ variant="flat"
465
+ density="compact"
466
+ icon="mdi mdi-note-edit"
467
+ @click="openDialog(item)"
468
+ />
469
+ <v-btn
470
+ v-if="canDelete"
471
+ variant="flat"
472
+ density="compact"
473
+ icon="mdi mdi-delete"
474
+ @click="deleteItem(item)"
475
+ />
476
+ </template>
477
+ </v-data-table-virtual>
365
478
  <v-data-table
366
479
  v-else
367
480
  v-bind="plainAttrs"
@@ -467,5 +580,23 @@ defineExpose({ reload, operation });
467
580
  />
468
581
  </template>
469
582
  </FormDialog>
583
+ <slot
584
+ name="importProgress"
585
+ :is-importing="importProgress.isImporting.value"
586
+ :total="importProgress.total.value"
587
+ :processed="importProgress.processed.value"
588
+ :succeeded="importProgress.succeeded.value"
589
+ :failed="importProgress.failed.value"
590
+ :percent="importProgress.percent.value"
591
+ >
592
+ <DialogImportProgress
593
+ :model-value="importProgress.isImporting.value"
594
+ :total="importProgress.total.value"
595
+ :processed="importProgress.processed.value"
596
+ :succeeded="importProgress.succeeded.value"
597
+ :failed="importProgress.failed.value"
598
+ :percent="importProgress.percent.value"
599
+ />
600
+ </slot>
470
601
  </v-card>
471
602
  </template>