lkt-item-crud 1.3.0 → 2.0.1

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.
@@ -1,133 +1,39 @@
1
1
  <script setup lang="ts">
2
- import { computed, nextTick, onMounted, ref, useSlots, watch } from 'vue';
2
+ import { computed, nextTick, onMounted, ref, SetupContext, useSlots, watch } from 'vue';
3
3
  import { httpCall, HTTPResponse } from 'lkt-http-client';
4
4
  import { DataState } from 'lkt-data-state';
5
5
  import { debug } from '../functions/debug';
6
- import { LktObject } from 'lkt-ts-interfaces';
7
- import { ModalCallbackConfig } from 'lkt-vue-kernel';
8
- import { runModalCallback } from 'lkt-modal';
6
+ import {
7
+ getDefaultValues,
8
+ ItemCrud,
9
+ ItemCrudButtonNavPosition,
10
+ ItemCrudConfig,
11
+ ItemCrudMode,
12
+ ItemCrudView,
13
+ LktObject,
14
+ TablePermission,
15
+ } from 'lkt-vue-kernel';
16
+ import { closeModal } from 'lkt-modal';
9
17
  import { __ } from 'lkt-i18n';
10
- import { Settings } from '../settings/Settings';
11
18
  import ButtonNav from '../components/ButtonNav.vue';
12
- import { ButtonNavPosition } from '../enums/ButtonNavPosition';
13
- import { ButtonNavVisibility } from '../enums/ButtonNavVisibility';
14
19
 
15
- const props = withDefaults(defineProps<{
16
- modelValue: LktObject
17
- title: string
18
- editModeText: string
19
- saveText: string
20
- saveIcon: string
21
- dropText: string
22
- dropIcon: string
23
- hiddenSave: boolean
24
- hiddenDrop: boolean
25
- hiddenButtons: boolean
26
- readResource: string
27
- createResource: string
28
- updateResource: string
29
- dropResource: string
30
- readData: LktObject
31
- createData: LktObject
32
- updateData: LktObject
33
- dropData: LktObject
34
- isCreate: boolean
35
- createConfirm: string
36
- updateConfirm: string
37
- dropConfirm: string
38
- createConfirmData: LktObject
39
- updateConfirmData: LktObject
40
- dropConfirmData: LktObject
41
- createDisabled: boolean
42
- updateDisabled: boolean
43
- dropDisabled: boolean
44
- saveValidator: Function
45
- beforeEmitUpdate: Function | undefined
46
- onCreate: Function | undefined
47
- onUpdate: Function | undefined
48
- insideModal: boolean
49
- hideSwitchEdition: boolean
50
- dataStateConfig: LktObject
51
- onCreateModalCallbacks: ModalCallbackConfig[]
52
- onUpdateModalCallbacks: ModalCallbackConfig[]
53
- onDropModalCallbacks: ModalCallbackConfig[]
54
- editing: boolean
55
- buttonNavPosition?: ButtonNavPosition
56
- buttonNavVisibility?: ButtonNavVisibility
57
20
 
58
- // Modal props
59
- size: string
60
- preTitle: string
61
- showClose: boolean
62
- disabledClose: boolean
63
- disabledVeilClick: boolean
64
- modalName: string
65
- modalKey: string
66
- zIndex: number
67
- editedCloseConfirm: string
68
- editedCloseConfirmKey: string | number
69
- beforeClose: Function | undefined
21
+ const props = withDefaults(defineProps<ItemCrudConfig>(), getDefaultValues(ItemCrud));
70
22
 
71
- }>(), {
72
- modelValue: () => ({}),
73
- title: '',
74
- editModeText: 'Edition Mode',
75
- saveText: 'Save',
76
- dropText: 'Delete',
77
- saveIcon: () => Settings.defaultSaveIcon,
78
- dropIcon: () => Settings.defaultDropIcon,
79
- hiddenSave: false,
80
- hiddenDrop: false,
81
- hiddenButtons: false,
82
- readResource: '',
83
- createResource: '',
84
- updateResource: '',
85
- dropResource: '',
86
- readData: () => ({}),
87
- createData: () => ({}),
88
- updateData: () => ({}),
89
- dropData: () => ({}),
90
- isCreate: false,
91
- createConfirm: '',
92
- updateConfirm: '',
93
- dropConfirm: '',
94
- createConfirmData: () => ({}),
95
- updateConfirmData: () => ({}),
96
- dropConfirmData: () => ({}),
97
- createDisabled: false,
98
- updateDisabled: false,
99
- dropDisabled: false,
100
- saveValidator: () => true,
101
- beforeEmitUpdate: undefined,
102
- onCreate: undefined,
103
- onUpdate: undefined,
104
- insideModal: false,
105
- hideSwitchEdition: false,
106
- dataStateConfig: () => ({}),
107
- onCreateModalCallbacks: () => [],
108
- onUpdateModalCallbacks: () => [],
109
- onDropModalCallbacks: () => [],
110
- editing: false,
111
- buttonNavPosition: ButtonNavPosition.Top,
112
- buttonNavVisibility: ButtonNavVisibility.Changed,
23
+ const slots: SetupContext['slots'] = useSlots();
113
24
 
114
- // Modal props
115
- size: '',
116
- preTitle: '',
117
- showClose: true,
118
- disabledClose: false,
119
- disabledVeilClick: false,
120
- modalName: '',
121
- modalKey: '_',
122
- zIndex: 500,
123
- editedCloseConfirm: '',
124
- editedCloseConfirmKey: '_',
125
- beforeClose: undefined,
126
- });
127
-
128
- const slots = useSlots();
129
-
130
- const emit = defineEmits(['update:modelValue', 'update:isCreate', 'update:editing', 'read', 'create', 'update', 'drop', 'before-save', 'perms', 'error', 'modified-data']);
25
+ const emit = defineEmits([
26
+ 'update:modelValue',
27
+ 'update:editing',
28
+ 'read',
29
+ 'create',
30
+ 'update',
31
+ 'drop',
32
+ 'before-save',
33
+ 'perms',
34
+ 'error',
35
+ 'modified-data',
36
+ ]);
131
37
 
132
38
  let basePerms: string[] = [];
133
39
 
@@ -138,50 +44,23 @@
138
44
  httpSuccessRead = ref(false),
139
45
  showStoreMessage = ref(false),
140
46
  httpStatus = ref(200),
141
- saveButton = ref(null),
142
- dropButton = ref(null),
143
47
  dataState = ref(new DataState(item.value, props.dataStateConfig)),
48
+ dataChanged = ref(false),
144
49
  readDataState = ref(new DataState(props.readData)),
145
- createMode = ref(props.isCreate),
50
+ createMode = ref(props.mode === ItemCrudMode.Create),
146
51
  itemBeingEdited = ref(false),
147
- itemCreated = ref(false);
148
-
149
- const buttonNav = ref(null);
150
-
151
- const saveConfirm = computed(() => {
152
- return createMode.value
153
- ? props.createConfirm
154
- : props.updateConfirm;
155
- }),
156
- confirmData = computed(() => {
157
- return createMode.value
158
- ? props.createConfirmData
159
- : props.updateConfirmData;
160
- }),
161
- saveResource = computed(() => {
162
- return createMode.value
163
- ? props.createResource
164
- : props.updateResource;
165
- }),
166
- saveData = computed(() => {
167
- if (createMode.value) {
168
- return { ...props.createData, ...JSON.parse(JSON.stringify(item.value)) };
169
- }
170
- return { ...props.updateData, ...JSON.parse(JSON.stringify(item.value)) };
171
- }),
172
- saveDisabled = computed(() => {
173
- return createMode.value
174
- ? props.createDisabled
175
- : props.updateDisabled;
176
- }),
177
- canUpdate = computed(() => !createMode.value && Array.isArray(perms.value) && perms.value.includes('update')),
178
- canDrop = computed(() => !createMode.value && Array.isArray(perms.value) && perms.value.includes('drop'));
52
+ itemCreated = ref(false),
53
+ buttonNav = ref(null),
54
+ canUpdate = computed(() => !createMode.value && Array.isArray(perms.value) && perms.value.includes(TablePermission.Update)),
55
+ canDrop = computed(() => !createMode.value && Array.isArray(perms.value) && perms.value.includes(TablePermission.Drop)),
56
+ canSwitchEditMode = computed(() => !createMode.value && Array.isArray(perms.value) && perms.value.includes(TablePermission.SwitchEditMode));
179
57
 
180
58
  const fetchItem = async () => {
181
59
  debug('fetchItem');
182
60
  isLoading.value = true;
183
61
  httpStatus.value = -1;
184
62
  showStoreMessage.value = false;
63
+
185
64
  try {
186
65
  const r = await httpCall(props.readResource, props.readData);
187
66
  debug('fetchItem -> response', r);
@@ -197,8 +76,10 @@
197
76
  item.value = r.data;
198
77
  perms.value = r.perms;
199
78
  dataState.value.increment(item.value).turnStoredIntoOriginal();
79
+ dataChanged.value = dataState.value.changed();
200
80
  readDataState.value.turnStoredIntoOriginal();
201
81
  emit('read', r);
82
+
202
83
  } catch (e) {
203
84
  isLoading.value = false;
204
85
  httpSuccessRead.value = false;
@@ -226,25 +107,14 @@
226
107
  emit('update:modelValue', item.value);
227
108
  debug('item updated -> update dataState');
228
109
  dataState.value.increment(v);
110
+ dataChanged.value = dataState.value.changed();
229
111
  nextTick(() => itemBeingEdited.value = false);
230
112
  }, { deep: true });
231
113
 
232
114
  watch(perms, () => emit('perms', perms.value));
233
-
234
- const ableToSave = computed(() => {
235
- if (saveDisabled.value) return false;
236
- if (!createMode.value && !canUpdate.value) return false;
237
-
238
- if (typeof props.saveValidator === 'function' && !props.saveValidator(item.value)) return false;
239
-
240
- return dataState.value.changed();
241
- });
242
-
243
- const ableToDrop = computed(() => {
244
- return !props.dropDisabled && canDrop.value;
115
+ watch(dataChanged, (v) => {
116
+ emit('modified-data', v);
245
117
  });
246
- watch(ableToSave, (v) => emit('modified-data', v));
247
- watch(createMode, (v) => emit('update:isCreate', v));
248
118
 
249
119
  watch(() => props.readData, v => {
250
120
  readDataState.value.increment(v);
@@ -268,90 +138,68 @@
268
138
  editMode.value = true;
269
139
  isLoading.value = false;
270
140
  dataState.value.increment(item.value).turnStoredIntoOriginal();
141
+ dataChanged.value = dataState.value.changed();
271
142
  }
272
- })
143
+ });
273
144
 
274
- const onDrop = ($event: PointerEvent, r: HTTPResponse) => {
275
- isLoading.value = false;
276
- httpStatus.value = r.httpStatus;
277
- if (!r.success) {
278
- showStoreMessage.value = true;
279
- emit('error', r.httpStatus);
280
- return;
281
- }
282
- showStoreMessage.value = true;
283
- if (props.onDropModalCallbacks.length > 0) {
284
- debug('onDrop -> has onDropModalCallbacks');
285
- props.onDropModalCallbacks.forEach(cb => {
286
- runModalCallback(cb);
287
- });
288
- }
289
- emit('drop', r);
290
- },
291
- onSave = ($event: PointerEvent, r: HTTPResponse) => {
292
- debug('onSave -> received response:', r);
293
- emit('before-save');
294
- if (saveResource.value) {
145
+ const ensureValidResourceSave = (r: HTTPResponse, resource?: string) => {
146
+ if (resource) {
295
147
  isLoading.value = false;
296
148
  if (typeof r !== 'undefined') {
297
149
  httpStatus.value = r.httpStatus;
298
150
  if (!r.success) {
299
151
  showStoreMessage.value = true;
300
152
  emit('error', r.httpStatus);
301
- return;
153
+ return false;
302
154
  }
303
155
  }
304
156
  showStoreMessage.value = true;
305
157
  }
306
- let emits: 'create' | 'update' = createMode.value ? 'create' : 'update';
307
- if (!createMode.value) {
308
- debug('onSave -> turn stored data into original');
309
- dataState.value.turnStoredIntoOriginal();
310
- }
311
-
312
-
313
- if (emits === 'create') {
314
- itemCreated.value = true;
315
- dataState.value.increment(item.value).turnStoredIntoOriginal();
316
- if (typeof props.onCreate === 'function') {
317
- debug('onSave -> trigger onCreate callback');
318
- props.onCreate(r);
319
- if (props.onCreateModalCallbacks.length > 0) {
320
- debug('onSave -> has onCreateModalCallbacks');
321
- props.onCreateModalCallbacks.forEach(cb => {
322
- runModalCallback(cb);
323
- });
324
- }
325
- }
326
- } else {
327
- if (typeof props.onUpdate === 'function') {
328
- debug('onSave -> trigger onUpdate callback');
329
- props.onUpdate(r);
330
- if (props.onUpdateModalCallbacks.length > 0) {
331
- debug('onSave -> has onUpdateModalCallbacks');
332
- props.onUpdateModalCallbacks.forEach(cb => {
333
- runModalCallback(cb);
334
- });
335
- }
336
- }
337
- }
338
-
339
- if (!props.insideModal && r.autoReloadId) {
340
- debug('onSave -> autoReloadId detected: ', r.autoReloadId);
158
+ return true;
159
+ },
160
+ doAutoReloadId = (r: HTTPResponse) => {
161
+ if (!computedInsideModal.value && r.autoReloadId) {
162
+ debug('doAutoReloadId -> autoReloadId detected: ', r.autoReloadId);
341
163
  props.readData['id'] = r.autoReloadId;
342
- debug('onSave -> turning off create mode');
164
+ debug('doAutoReloadId -> turning off create mode');
343
165
  createMode.value = false;
344
166
  fetchItem();
345
167
  }
346
- emit(emits, r);
168
+ },
169
+ onCreate = ($event: PointerEvent, r: HTTPResponse) => {
170
+ debug('onCreate');
171
+ if (!ensureValidResourceSave(r, props.createButton.resource)) return;
172
+ itemCreated.value = true;
173
+ debug('onCreate -> turn stored data into original');
174
+ dataState.value.increment(item.value).turnStoredIntoOriginal();
175
+ doAutoReloadId(r);
176
+ emit('create', r);
177
+ },
178
+ onUpdate = ($event: PointerEvent, r: HTTPResponse) => {
179
+ debug('onUpdate');
180
+ if (!ensureValidResourceSave(r, props.updateButton.resource)) return;
181
+ debug('onUpdate -> turn stored data into original');
182
+ dataState.value.turnStoredIntoOriginal();
183
+ doAutoReloadId(r);
184
+ emit('update', r);
185
+ },
186
+ onDrop = ($event: PointerEvent, r: HTTPResponse) => {
187
+ debug('onDrop');
188
+ if (!ensureValidResourceSave(r, props.dropButton.resource)) return;
189
+ emit('drop', r);
190
+ if (props.view === ItemCrudView.Modal) {
191
+ debug('onDrop -> close modal');
192
+ //@ts-ignore
193
+ closeModal(props.modalConfig.modalName, props.modalConfig.modalKey);
194
+ }
347
195
  },
348
196
  doSave = () => {
349
197
  // @ts-ignore
350
- if (buttonNav.value) saveButton.value.doSave();
198
+ if (buttonNav.value) buttonNav.value.doSave();
351
199
  },
352
200
  doDrop = () => {
353
201
  // @ts-ignore
354
- if (buttonNav.value) dropButton.value.doDrop();
202
+ if (buttonNav.value) buttonNav.value.doDrop();
355
203
  };
356
204
 
357
205
  defineExpose({
@@ -363,57 +211,20 @@
363
211
 
364
212
 
365
213
  const closeConfirm = computed(() => {
366
- return dataState.value.changed() ? props.editedCloseConfirm : '';
214
+ return dataState.value.changed() ? props.modalConfig?.closeConfirm : '';
367
215
  });
368
216
 
369
217
  const crudBeforeClose = (modalData: LktObject) => {
370
- if (typeof props.beforeClose === 'function') {
371
- return props.beforeClose({
218
+ if (typeof props.modalConfig?.beforeClose === 'function') {
219
+ //@ts-ignore
220
+ return props.modalConfig.beforeClose({
372
221
  ...modalData,
373
222
  itemCreated: itemCreated.value,
374
223
  });
375
224
  }
376
225
  };
377
226
 
378
- const showDropButton = computed(() => {
379
- if (!canUpdate.value && canDrop.value) return true;
380
-
381
- return !props.hiddenDrop
382
- && !isLoading.value
383
- && editMode.value
384
- && httpSuccessRead.value;
385
- }),
386
- showSaveButton = computed(() => {
387
-
388
- if (dataState.value.changed()) return true;
389
- if (isLoading.value) return false;
390
-
391
- if (createMode.value) return true;
392
-
393
- if (props.buttonNavVisibility === ButtonNavVisibility.Always) {
394
- return ableToSave.value;
395
- }
396
-
397
- return !props.hiddenSave
398
- && editMode.value
399
- && httpSuccessRead.value;
400
- }),
401
- showSwitchButton = computed(() => {
402
- if (props.hideSwitchEdition) return false;
403
- if (!canUpdate.value && !canDrop.value) return false;
404
- if (!canUpdate.value && canDrop.value) return false;
405
-
406
- return !isLoading.value
407
- && !createMode.value
408
- && httpSuccessRead.value
409
- && !(props.dropDisabled && props.updateDisabled);
410
- }),
411
- showButtons = computed(() => {
412
- if (props.buttonNavVisibility === ButtonNavVisibility.Always && (ableToSave.value || ableToDrop.value)) return true;
413
- if (slots['prev-buttons-ever']) return true;
414
- return !props.hiddenButtons && (showSaveButton.value || showDropButton.value || showSwitchButton.value);
415
- }),
416
- computedTitle = computed(() => {
227
+ const computedTitle = computed(() => {
417
228
  if (props.title.startsWith('__:')) {
418
229
  return String(__(props.title.substring(3)));
419
230
  }
@@ -424,27 +235,25 @@
424
235
 
425
236
  return computedTitle.value.length > 0 || !!slots['post-title'];
426
237
  }),
238
+ computedInsideModal = computed(() => {
239
+ return props.view === ItemCrudView.Modal;
240
+ }),
427
241
  computedContainerTag = computed(() => {
428
- if (props.insideModal) return 'lkt-modal';
242
+ if (computedInsideModal.value) return 'lkt-modal';
429
243
  return 'section';
430
244
  }),
431
245
  computedContainerAttrs = computed(() => {
432
246
  if (computedContainerTag.value === 'lkt-modal') {
433
-
434
247
  return {
435
- 'modal-name': props.modalName,
436
- 'modal-key': props.modalKey,
437
- 'z-index': props.zIndex,
438
- 'pre-title': props.preTitle,
439
- 'show-close': props.showClose,
440
- 'before-close': crudBeforeClose,
441
- 'disabled-close': props.disabledClose,
442
- 'disabled-veil-click': props.disabledVeilClick,
443
- 'close-confirm': closeConfirm.value,
444
- 'close-confirm-key': props.editedCloseConfirmKey,
445
- title: props.title,
446
- size: props.size,
447
- item: item.value,
248
+ ...{
249
+ title: props.title,
250
+ item: item.value,
251
+ },
252
+ ...props.modalConfig,
253
+ ...{
254
+ 'before-close': crudBeforeClose,
255
+ 'close-confirm': closeConfirm.value,
256
+ },
448
257
  };
449
258
  }
450
259
  return {};
@@ -457,44 +266,36 @@
457
266
  v-bind="computedContainerAttrs"
458
267
  >
459
268
  <article class="lkt-item-crud">
460
- <header class="lkt-item-crud_header" v-if="!insideModal && displayHeader">
269
+ <header class="lkt-item-crud_header" v-if="!computedInsideModal && displayHeader">
461
270
  <div class="lkt-item-crud_header-slot" v-if="slots['pre-title']">
462
- <slot name="pre-title" :item="item" :loading="isLoading"/>
271
+ <slot name="pre-title" :item="item" :loading="isLoading" />
463
272
  </div>
464
273
  <h1 class="lkt-item-crud_header-title" v-if="computedTitle.length > 0">{{ computedTitle }}</h1>
465
274
  <div class="lkt-item-crud_header-slot" v-if="slots['post-title']">
466
- <slot name="post-title" :item="item" :loading="isLoading"/>
275
+ <slot name="post-title" :item="item" :loading="isLoading" />
467
276
  </div>
468
277
  </header>
469
278
 
470
279
  <button-nav
471
280
  ref="buttonNav"
472
- v-if="showButtons && buttonNavPosition === 'top'"
281
+ v-if="buttonNavPosition === ItemCrudButtonNavPosition.Top"
473
282
  v-model:loading="isLoading"
474
283
  v-model:editing="editMode"
475
284
  :item="item"
476
- :create-mode="createMode"
285
+ :mode="mode"
286
+ :view="view"
287
+ :button-nav-visibility="buttonNavVisibility"
288
+ :create-button="createButton"
289
+ :update-button="updateButton"
290
+ :drop-button="dropButton"
291
+ :edit-mode-button="editModeButton"
292
+ :data-changed="dataChanged"
293
+ :http-success-read="httpSuccessRead"
477
294
  :can-update="canUpdate"
478
295
  :can-drop="canDrop"
479
- :show-switch-button="showSwitchButton"
480
- :show-save-button="showSaveButton"
481
- :show-drop-button="showDropButton"
482
- :able-to-save="ableToSave"
483
- :able-to-drop="ableToDrop"
484
- :save-confirm="saveConfirm"
485
- :drop-confirm="dropConfirm"
486
- :confirm-data="confirmData"
487
- :drop-confirm-data="dropConfirmData"
488
- :save-resource="saveResource"
489
- :drop-resource="dropResource"
490
- :save-data="saveData"
491
- :drop-data="dropData"
492
- :save-text="saveText"
493
- :drop-text="dropText"
494
- :save-icon="saveIcon"
495
- :drop-icon="dropIcon"
496
- :edit-mode-text="editModeText"
497
- @save="onSave"
296
+ :can-switch-edit-mode="canSwitchEditMode"
297
+ @create="onCreate"
298
+ @save="onUpdate"
498
299
  @drop="onDrop"
499
300
  >
500
301
  <template #prev-buttons-ever v-if="slots['prev-buttons-ever']">
@@ -509,46 +310,37 @@
509
310
  <div v-if="httpSuccessRead" class="lkt-grid-1">
510
311
  <lkt-http-info :code="httpStatus" v-if="showStoreMessage" quick
511
312
  :palette="httpStatus === 200 ? 'success' : 'danger'" can-close
512
- v-on:close="showStoreMessage = false"/>
313
+ v-on:close="showStoreMessage = false" />
513
314
  <slot name="item" :item="item" :loading="isLoading" :edit-mode="editMode"
514
315
  :is-create="createMode"
515
316
  :can-update="canUpdate"
516
317
  :can-drop="canDrop"
517
318
  :item-being-edited="itemBeingEdited"></slot>
518
319
  </div>
519
- <lkt-http-info :code="httpStatus" v-else/>
320
+ <lkt-http-info :code="httpStatus" v-else />
520
321
  </div>
521
322
  <lkt-loader v-if="isLoading" />
522
323
 
523
324
  <button-nav
524
325
  ref="buttonNav"
525
- v-if="buttonNavPosition === ButtonNavPosition.Bottom"
526
- v-show="showButtons"
326
+ v-if="buttonNavPosition === ItemCrudButtonNavPosition.Bottom"
527
327
  v-model:loading="isLoading"
528
328
  v-model:editing="editMode"
529
329
  :item="item"
530
- :create-mode="createMode"
330
+ :mode="mode"
331
+ :view="view"
332
+ :button-nav-visibility="buttonNavVisibility"
333
+ :create-button="createButton"
334
+ :update-button="updateButton"
335
+ :drop-button="dropButton"
336
+ :edit-mode-button="editModeButton"
337
+ :data-changed="dataChanged"
338
+ :http-success-read="httpSuccessRead"
531
339
  :can-update="canUpdate"
532
340
  :can-drop="canDrop"
533
- :show-switch-button="showSwitchButton"
534
- :show-save-button="showSaveButton"
535
- :show-drop-button="showDropButton"
536
- :able-to-save="ableToSave"
537
- :able-to-drop="ableToDrop"
538
- :save-confirm="saveConfirm"
539
- :drop-confirm="dropConfirm"
540
- :confirm-data="confirmData"
541
- :drop-confirm-data="dropConfirmData"
542
- :save-resource="saveResource"
543
- :drop-resource="dropResource"
544
- :save-data="saveData"
545
- :drop-data="dropData"
546
- :save-text="saveText"
547
- :drop-text="dropText"
548
- :save-icon="saveIcon"
549
- :drop-icon="dropIcon"
550
- :edit-mode-text="editModeText"
551
- @save="onSave"
341
+ :can-switch-edit-mode="canSwitchEditMode"
342
+ @create="onCreate"
343
+ @save="onUpdate"
552
344
  @drop="onDrop"
553
345
  >
554
346
  <template #prev-buttons-ever v-if="slots['prev-buttons-ever']">
File without changes