lkt-table 1.4.3 → 2.0.2

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.
@@ -3,9 +3,13 @@ import {defaultTableSorter, getColumnByKey, getDefaultSortColumn} from "../funct
3
3
  import LktTableRow from "../components/LktTableRow.vue";
4
4
  import {computed, nextTick, onMounted, ref, useSlots, watch} from "vue";
5
5
  import {
6
+ ButtonType,
6
7
  Column,
8
+ ensureButtonConfig,
9
+ extractI18nValue,
7
10
  getDefaultValues,
8
11
  LktObject,
12
+ LktSettings,
9
13
  SortDirection,
10
14
  Table,
11
15
  TableConfig,
@@ -19,7 +23,6 @@ import {HTTPResponse} from "lkt-http-client";
19
23
  import CreateButton from "../components/CreateButton.vue";
20
24
  import Sortable from 'sortablejs';
21
25
  import TableHeader from "../components/TableHeader.vue";
22
- import {__} from "lkt-i18n";
23
26
  import {time} from "lkt-date-tools";
24
27
  import {Settings} from "../settings/Settings";
25
28
 
@@ -47,25 +50,29 @@ const hiddenColumnsStack: LktObject = {};
47
50
 
48
51
  const Sorter = ref(typeof props.sorter === 'function' ? props.sorter : defaultTableSorter),
49
52
  SortBy = ref(getDefaultSortColumn(props.columns)),
50
- SortingDirection = ref(<SortDirection>SortDirection.Asc),
53
+ SortingDirection = ref(SortDirection.Asc),
51
54
  Items = ref(props.modelValue),
52
55
  Hidden = ref(hiddenColumnsStack),
53
- tableBody = ref(<HTMLElement|null>null),
56
+ tableBody = ref(<HTMLElement | null>null),
54
57
  Columns = ref(props.columns);
55
58
 
56
- const Page = ref(props.page),
59
+ const Page = ref(props.paginator?.modelValue),
57
60
  isLoading = ref(props.loading),
58
61
  firstLoadReady = ref(false),
59
62
  permissions = ref(props.perms),
60
- paginator = ref(null),
63
+ paginatorRef = ref(null),
61
64
  element = ref(null),
65
+ saveButtonRef = ref(null),
62
66
  sortableObject = ref({}),
63
- dataState = ref(new DataState({items: Items.value}, props.dataStateConfig)),
67
+ dataState = ref(<DataState>new DataState({items: Items.value}, props.dataStateConfig)),
64
68
  editModeEnabled = ref(props.editMode),
65
69
  updateTimeStamp = ref(0),
66
- sortableContainer = ref(<HTMLElement|null>null)
70
+ sortableContainer = ref(<HTMLElement | null>null)
67
71
  ;
68
72
 
73
+ const safeSaveButton = ref(ensureButtonConfig(props.saveButton, LktSettings.defaultSaveButton));
74
+ const safeCreateButton = ref(ensureButtonConfig(props.createButton, LktSettings.defaultCreateButton));
75
+
69
76
  const dataStateChanged = ref(false);
70
77
 
71
78
  watch(isLoading, v => emit('update:loading', v));
@@ -83,13 +90,14 @@ const onPerms = (r: string[]) => {
83
90
  dataState.value.store({items: Items.value}).turnStoredIntoOriginal();
84
91
  dataStateChanged.value = false;
85
92
  nextTick(() => {
93
+ saveIsDisabled.value; // Force calc call
86
94
  emit('read-response', r);
87
95
  })
88
96
  },
89
97
  onLoading = () => nextTick(() => isLoading.value = true),
90
98
  doRefresh = () => {
91
99
  //@ts-ignore
92
- paginator.value.doRefresh();
100
+ paginatorRef.value.doRefresh();
93
101
  };
94
102
 
95
103
 
@@ -142,7 +150,7 @@ const emptyColumns = computed(() => {
142
150
  showSaveButton = computed(() => {
143
151
  if (props.hiddenSave) return false;
144
152
  if (isLoading.value) return false;
145
- if (!props.saveResource) return false;
153
+ if (!(safeSaveButton.value?.resource || safeSaveButton.value.type)) return false;
146
154
  if (editModeEnabled.value && dataStateChanged.value) return true;
147
155
 
148
156
  return editModeEnabled.value;
@@ -152,10 +160,14 @@ const emptyColumns = computed(() => {
152
160
  if (props.switchEditionEnabled) return true;
153
161
  return showSaveButton.value || (editModeEnabled.value && hasCreatePerm.value);
154
162
  }),
155
- ableToSave = computed(() => {
156
- if (props.saveDisabled) return false;
157
- if (typeof props.saveValidator === 'function' && !props.saveValidator(Items.value)) return false;
158
- return dataStateChanged.value;
163
+ saveIsDisabled = computed(() => {
164
+ updateTimeStamp.value;
165
+ if (typeof safeSaveButton.value?.disabled === 'function') return safeSaveButton.value.disabled({
166
+ value: Items.value,
167
+ dataState: <DataState>dataState.value,
168
+ });
169
+ if (typeof safeSaveButton.value?.disabled === 'boolean') return safeSaveButton.value.disabled;
170
+ return !dataStateChanged.value;
159
171
  }),
160
172
  amountOfItems = computed(() => {
161
173
  return Items.value.length;
@@ -163,7 +175,7 @@ const emptyColumns = computed(() => {
163
175
  computedSaveResourceData = computed(() => {
164
176
  return {
165
177
  items: Items.value,
166
- ...props.saveResourceData
178
+ ...safeSaveButton.value?.resourceData
167
179
  }
168
180
  }),
169
181
  computedTitleTag = computed(() => {
@@ -175,22 +187,13 @@ const emptyColumns = computed(() => {
175
187
  return props.wrapContentTag;
176
188
  }),
177
189
  computedTitle = computed(() => {
178
- if (props.title.startsWith('__:')) {
179
- return __(props.title.substring(3));
180
- }
181
- return props.title;
182
- }),
183
- computedSaveText = computed(() => {
184
- if (props.saveText.startsWith('__:')) {
185
- return __(props.saveText.substring(3));
186
- }
187
- return props.saveText;
190
+ return extractI18nValue(props.title);
188
191
  }),
189
192
  computedEditModeText = computed(() => {
190
- if (props.editModeText.startsWith('__:')) {
191
- return __(props.editModeText.substring(3));
192
- }
193
- return props.editModeText;
193
+ return extractI18nValue(props.editModeText);
194
+ }),
195
+ computedDragModeEnabled = computed(() => {
196
+ return props.drag?.enabled;
194
197
  }),
195
198
  hasCreatePerm = computed(() => permissions.value.includes(TablePermission.Create)),
196
199
  hasReadPerm = computed(() => permissions.value.includes('read')),
@@ -248,13 +251,12 @@ const getItemByEvent = (e: any) => {
248
251
  },
249
252
  validDragChecker = (evt: any) => {
250
253
  let targetIndex = parseInt(evt?.originalEvent?.toElement?.closest('tr')?.dataset?.i);
251
- if (typeof props.disabledDrag === 'function' && props.disabledDrag(Items.value[targetIndex])) return false;
252
- if (typeof props.disabledDrag === 'boolean' && props.disabledDrag) return false;
253
- if (typeof props.checkValidDrag === 'function') return props.checkValidDrag(evt);
254
+ if (typeof props.drag?.isValid === 'function' && !props.drag?.isValid(Items.value[targetIndex])) return false;
255
+ if (typeof props.drag?.isValid === 'boolean' && !props.drag?.isValid) return false;
254
256
  return true;
255
257
  },
256
258
  isDraggable = (element: any) => {
257
- if (typeof props.draggableChecker === 'function') return props.draggableChecker(element);
259
+ if (typeof props.drag?.isDraggable === 'function') return props.drag?.isDraggable(element);
258
260
  return true;
259
261
  },
260
262
  onClickAddItem = () => {
@@ -280,15 +282,21 @@ const getItemByEvent = (e: any) => {
280
282
  onAppend = (data: LktObject) => {
281
283
  Items.value.push(data);
282
284
  },
283
- onButtonLoading = () => {
284
- isLoading.value = true;
285
- },
286
- onButtonLoaded = () => {
287
- isLoading.value = false;
288
- },
285
+ onButtonLoading = () => isLoading.value = true,
286
+ onButtonLoaded = () => isLoading.value = false,
289
287
  onSave = ($event: PointerEvent, r: HTTPResponse) => {
288
+ if (safeSaveButton.value?.type) {
289
+ if ([
290
+ ButtonType.Split,
291
+ ButtonType.SplitEver,
292
+ ButtonType.SplitLazy,
293
+ ].includes(safeSaveButton.value?.type)) {
294
+ return;
295
+ }
296
+ }
297
+
290
298
  emit('before-save');
291
- if (props.saveResource) {
299
+ if (safeSaveButton.value?.resource) {
292
300
  isLoading.value = false;
293
301
  if (!r.success) {
294
302
  emit('error', r.httpStatus);
@@ -394,14 +402,14 @@ onMounted(() => {
394
402
  }
395
403
  dataState.value.store({items: Items.value}).turnStoredIntoOriginal();
396
404
  dataStateChanged.value = false;
397
- if (props.sortable) {
405
+ if (props.drag?.enabled) {
398
406
  nextTick(() => {
399
407
  initSortable();
400
408
  })
401
409
  }
402
410
  })
403
411
 
404
- watch(() => props.sortable, (v) => {
412
+ watch(() => props.drag?.enabled, (v) => {
405
413
  if (v) {
406
414
  initSortable();
407
415
  } else {
@@ -426,6 +434,12 @@ defineExpose({
426
434
  getRowByIndex,
427
435
  doRefresh,
428
436
  getHtml: () => element.value,
437
+ turnStoredIntoOriginal: () => {
438
+ dataState.value.turnStoredIntoOriginal();
439
+ nextTick(()=> {
440
+ updateTimeStamp.value = time();
441
+ })
442
+ },
429
443
  });
430
444
 
431
445
  const hasEmptySlot = computed(() => {
@@ -433,6 +447,18 @@ const hasEmptySlot = computed(() => {
433
447
  }),
434
448
  emptySlot = computed(() => {
435
449
  return Settings.defaultEmptySlot;
450
+ }),
451
+ computedRenderDrag = computed(() => {
452
+ if (!props.drag || Object.keys(props.drag).length === 0) return false;
453
+ if (!props.drag.enabled) return false;
454
+ if (typeof props.drag.canRender === 'undefined') return true;
455
+ return props.drag.canRender;
456
+ }),
457
+ computedDisabledDrag = computed(() => {
458
+ if (!props.drag || Object.keys(props.drag).length === 0) return false;
459
+ if (!props.drag.enabled) return false;
460
+ if (typeof props.drag.isDisabled === 'undefined') return false;
461
+ return props.drag.isDisabled;
436
462
  });
437
463
 
438
464
  </script>
@@ -459,16 +485,11 @@ const hasEmptySlot = computed(() => {
459
485
  v-if="showEditionButtons">
460
486
  <lkt-button
461
487
  class="lkt-table--save-button"
462
- ref="saveButton"
488
+ ref="saveButtonRef"
463
489
  v-show="showSaveButton"
464
- :icon="Settings.defaultSaveIcon"
465
- :disabled="!ableToSave"
466
- :confirm-modal="saveConfirm"
467
- :confirm-data="confirmData"
468
- :resource="saveResource"
469
- :resource-data="computedSaveResourceData"
470
- :split="splitSave"
471
- :tooltip-engine="saveTooltipEngine"
490
+ v-bind="safeSaveButton"
491
+ :disabled="saveIsDisabled"
492
+ :modal-data="computedSaveResourceData"
472
493
  v-on:loading="onButtonLoading"
473
494
  v-on:loaded="onButtonLoaded"
474
495
  v-on:click="onSave">
@@ -476,8 +497,7 @@ const hasEmptySlot = computed(() => {
476
497
  name="button-save"
477
498
  :items="Items"
478
499
  :edit-mode="editMode"
479
- :can-update="!saveDisabled"></slot>
480
- <span v-else>{{ computedSaveText }}</span>
500
+ :can-update="!saveIsDisabled"/>
481
501
 
482
502
  <template v-slot:split="{doClose, doRootClick}">
483
503
  <slot name="button-save-split"
@@ -485,18 +505,14 @@ const hasEmptySlot = computed(() => {
485
505
  :do-root-click="doRootClick"
486
506
  :data-state="dataState"
487
507
  :on-button-loading="onButtonLoading"
488
- :on-button-loaded="onButtonLoaded" />
508
+ :on-button-loaded="onButtonLoaded"/>
489
509
  </template>
490
510
  </lkt-button>
491
511
 
492
512
  <create-button
493
513
  v-if="computedDisplayCreateButton && Items.length >= requiredItemsForTopCreate"
514
+ :config="safeCreateButton"
494
515
  :disabled="!createEnabled || createDisabled"
495
- :text="createText"
496
- :icon="createIcon"
497
- :to="createRoute"
498
- :modal="modal"
499
- :modal-data="modalData"
500
516
  @click="onClickAddItem"
501
517
  @append="onAppend"
502
518
  />
@@ -522,11 +538,11 @@ const hasEmptySlot = computed(() => {
522
538
 
523
539
  <lkt-loader v-if="isLoading"/>
524
540
 
525
- <div v-show="!isLoading && Items.length > 0" class="lkt-table" :data-sortable="sortable">
541
+ <div v-show="!isLoading && Items.length > 0" class="lkt-table">
526
542
  <table v-if="type === TableType.Table">
527
543
  <thead>
528
544
  <tr>
529
- <th v-if="sortable && editModeEnabled" data-role="drag-indicator"/>
545
+ <th v-if="computedDragModeEnabled && editModeEnabled" data-role="drag-indicator"/>
530
546
  <th v-if="addNavigation && editModeEnabled"/>
531
547
  <th v-if="displayHiddenColumnsIndicator"/>
532
548
  <template v-for="column in visibleColumns">
@@ -554,94 +570,94 @@ const hasEmptySlot = computed(() => {
554
570
  ref="tableBody"
555
571
  :id="'lkt-table-body-' + uniqueId"
556
572
  >
557
- <lkt-table-row
558
- v-for="(item, i) in Items"
559
- v-model="Items[i]"
560
- v-show="canDisplayItem(Items[i], i)"
561
- :key="getRowKey(item, i)"
562
- :i="i"
563
- :display-hidden-columns-indicator="displayHiddenColumnsIndicator"
564
- :is-draggable="isDraggable(item)"
565
- :sortable="sortable"
566
- :visible-columns="visibleColumns"
567
- :empty-columns="emptyColumns"
568
- :add-navigation="addNavigation"
569
- :hidden-is-visible="isVisible(i)"
570
- :latest-row="i+1 === amountOfItems"
571
- :can-drop="hasDropPerm && editModeEnabled"
572
- :drop-confirm="dropConfirm"
573
- :drop-resource="dropResource"
574
- :drop-text="dropText"
575
- :drop-icon="dropIcon"
576
- :can-edit="hasEditPerm && hasUpdatePerm && editModeEnabled"
577
- :edit-text="editText"
578
- :edit-icon="editIcon"
579
- :edit-link="editLink"
580
- :edit-mode-enabled="editModeEnabled"
581
- :has-inline-edit-perm="hasInlineEditPerm"
582
- :row-display-type="rowDisplayType"
583
- :render-drag="renderDrag"
584
- :disabled-drag="disabledDrag"
585
- v-on:click="onClick"
586
- v-on:show="show"
587
- v-on:item-up="onItemUp"
588
- v-on:item-down="onItemDown"
589
- v-on:item-drop="onItemDrop"
590
- >
591
- <template v-if="slots[`item-${i}`]" v-slot:[`item-${i}`]="row">
592
- <slot
593
- :name="`item-${i}`"
594
- :[slotItemVar]="row.item"
595
- v-bind:index="i"
596
- />
597
- </template>
598
- <template v-else-if="slots.item" #item="row">
599
- <slot
600
- name="item"
601
- :[slotItemVar]="row.item"
602
- v-bind:index="i"
603
- />
604
- </template>
605
- <template
606
- v-for="column in colSlots"
607
- v-slot:[column]="row">
608
- <slot
609
- :name="column"
610
- :[slotItemVar]="row.item"
611
- :value="row.value"
612
- :column="row.column"
613
- />
614
- </template>
615
- </lkt-table-row>
616
- <lkt-hidden-row
617
- v-if="hiddenColumns.length > 0"
618
- v-model="Items[i]"
619
- v-for="(item, i) in Items"
620
- :key="getRowKey(item, i, true)"
621
- :i="i"
622
- :hidden-columns="hiddenColumns"
623
- :hidden-columns-col-span="hiddenColumnsColSpan"
624
- :is-draggable="isDraggable(item)"
625
- :sortable="sortable"
626
- :visible-columns="visibleColumns"
627
- :empty-columns="emptyColumns"
628
- :hidden-is-visible="isVisible(i)"
629
- :edit-mode-enabled="editModeEnabled"
630
- :has-inline-edit-perm="hasInlineEditPerm"
631
- v-on:click="onClick"
632
- v-on:show="show"
633
- >
634
- <template
635
- v-for="column in colSlots"
636
- v-slot:[column]="row">
637
- <slot
638
- :name="column"
639
- :[slotItemVar]="row.item"
640
- :value="row.value"
641
- :column="row.column"
642
- />
643
- </template>
644
- </lkt-hidden-row>
573
+ <lkt-table-row
574
+ v-for="(item, i) in Items"
575
+ v-model="Items[i]"
576
+ v-show="canDisplayItem(Items[i], i)"
577
+ :key="getRowKey(item, i)"
578
+ :i="i"
579
+ :display-hidden-columns-indicator="displayHiddenColumnsIndicator"
580
+ :is-draggable="isDraggable(item)"
581
+ :sortable="computedDragModeEnabled"
582
+ :visible-columns="visibleColumns"
583
+ :empty-columns="emptyColumns"
584
+ :add-navigation="addNavigation"
585
+ :hidden-is-visible="isVisible(i)"
586
+ :latest-row="i+1 === amountOfItems"
587
+ :can-drop="hasDropPerm && editModeEnabled"
588
+ :drop-confirm="dropConfirm"
589
+ :drop-resource="dropResource"
590
+ :drop-text="dropText"
591
+ :drop-icon="dropIcon"
592
+ :can-edit="hasEditPerm && hasUpdatePerm && editModeEnabled"
593
+ :edit-text="editText"
594
+ :edit-icon="editIcon"
595
+ :edit-link="editLink"
596
+ :edit-mode-enabled="editModeEnabled"
597
+ :has-inline-edit-perm="hasInlineEditPerm"
598
+ :row-display-type="rowDisplayType"
599
+ :render-drag="computedRenderDrag"
600
+ :disabled-drag="computedDisabledDrag"
601
+ v-on:click="onClick"
602
+ v-on:show="show"
603
+ v-on:item-up="onItemUp"
604
+ v-on:item-down="onItemDown"
605
+ v-on:item-drop="onItemDrop"
606
+ >
607
+ <template v-if="slots[`item-${i}`]" v-slot:[`item-${i}`]="row">
608
+ <slot
609
+ :name="`item-${i}`"
610
+ :[slotItemVar]="row.item"
611
+ v-bind:index="i"
612
+ />
613
+ </template>
614
+ <template v-else-if="slots.item" #item="row">
615
+ <slot
616
+ name="item"
617
+ :[slotItemVar]="row.item"
618
+ v-bind:index="i"
619
+ />
620
+ </template>
621
+ <template
622
+ v-for="column in colSlots"
623
+ v-slot:[column]="row">
624
+ <slot
625
+ :name="column"
626
+ :[slotItemVar]="row.item"
627
+ :value="row.value"
628
+ :column="row.column"
629
+ />
630
+ </template>
631
+ </lkt-table-row>
632
+ <lkt-hidden-row
633
+ v-if="hiddenColumns.length > 0"
634
+ v-model="Items[i]"
635
+ v-for="(item, i) in Items"
636
+ :key="getRowKey(item, i, true)"
637
+ :i="i"
638
+ :hidden-columns="hiddenColumns"
639
+ :hidden-columns-col-span="hiddenColumnsColSpan"
640
+ :is-draggable="isDraggable(item)"
641
+ :sortable="computedDragModeEnabled"
642
+ :visible-columns="visibleColumns"
643
+ :empty-columns="emptyColumns"
644
+ :hidden-is-visible="isVisible(i)"
645
+ :edit-mode-enabled="editModeEnabled"
646
+ :has-inline-edit-perm="hasInlineEditPerm"
647
+ v-on:click="onClick"
648
+ v-on:show="show"
649
+ >
650
+ <template
651
+ v-for="column in colSlots"
652
+ v-slot:[column]="row">
653
+ <slot
654
+ :name="column"
655
+ :[slotItemVar]="row.item"
656
+ :value="row.value"
657
+ :column="row.column"
658
+ />
659
+ </template>
660
+ </lkt-hidden-row>
645
661
  </tbody>
646
662
  </table>
647
663
 
@@ -672,7 +688,8 @@ const hasEmptySlot = computed(() => {
672
688
  </template>
673
689
  </div>
674
690
 
675
- <component :is="type" v-else-if="computedIsList" class="lkt-table-items-container" :class="itemsContainerClass">
691
+ <component :is="type" v-else-if="computedIsList" class="lkt-table-items-container"
692
+ :class="itemsContainerClass">
676
693
  <template
677
694
  v-for="(item, i) in Items">
678
695
  <li class="lkt-table-item" v-if="canDisplayItem(item, i)" :data-i="i">
@@ -708,12 +725,8 @@ const hasEmptySlot = computed(() => {
708
725
  class="lkt-table-page-buttons lkt-table-page-buttons-bottom">
709
726
  <create-button
710
727
  v-if="computedDisplayCreateButton && Items.length >= requiredItemsForBottomCreate"
728
+ :config="safeCreateButton"
711
729
  :disabled="!createEnabled || createDisabled"
712
- :text="createText"
713
- :icon="createIcon"
714
- :to="createRoute"
715
- :modal="modal"
716
- :modal-data="modalData"
717
730
  @click="onClickAddItem"
718
731
  @append="onAppend"
719
732
  />
@@ -721,7 +734,7 @@ const hasEmptySlot = computed(() => {
721
734
  </div>
722
735
 
723
736
  <lkt-paginator
724
- ref="paginator"
737
+ ref="paginatorRef"
725
738
  v-if="resource.length > 0"
726
739
  v-model="Page"
727
740
  :resource="resource"