vue-laravel-crud 2.0.0 → 2.0.4

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,656 +1,696 @@
1
- <script>
2
- import CrudHeader from "./components/CrudHeader.vue";
3
- import CrudTable from "./components/CrudTable.vue";
4
- import CrudCards from "./components/CrudCards.vue";
5
- import CrudKanban from "./components/CrudKanban.vue";
6
- import CrudCustom from "./components/CrudCustom.vue";
7
- import CrudModals from "./components/CrudModals.vue";
8
- import CrudPagination from "./components/CrudPagination.vue";
9
-
10
- // Import mixins
11
- import crudData from "./mixins/crudData.js";
12
- import crudApi from "./mixins/crudApi.js";
13
- import crudFilters from "./mixins/crudFilters.js";
14
- import crudValidation from "./mixins/crudValidation.js";
15
- import crudHelpers from "./mixins/crudHelpers.js";
16
-
17
- export default /*#__PURE__*/ {
18
- name: "VueLaravelCrud",
19
- components: {
20
- CrudHeader,
21
- CrudTable,
22
- CrudCards,
23
- CrudKanban,
24
- CrudCustom,
25
- CrudModals,
26
- CrudPagination
27
- },
28
- mixins: [
29
- crudData,
30
- crudApi,
31
- crudFilters,
32
- crudValidation,
33
- crudHelpers
34
- ],
35
- provide() {
36
- return {
37
- // Props
38
- modelName: this.modelName,
39
- title: this.title,
40
- model: this.model,
41
- models: this.models,
42
- ajax: this.ajax,
43
- useVuexORM: this.useVuexORM,
44
- vuexInitRelations: this.vuexInitRelations,
45
- vuexLocalforage: this.vuexLocalforage,
46
- columns: this.columns,
47
- filter: this.filter,
48
- enableFilters: this.enableFilters,
49
- infiniteScroll: this.infiniteScroll,
50
- sortable: this.sortable,
51
- orderable: this.orderable,
52
- validate: this.validate,
53
- orderProp: this.orderProp,
54
- createMultipart: this.createMultipart,
55
- apiUrl: this.apiUrl,
56
- search: this.search,
57
- hideModalAfterSave: this.hideModalAfterSave,
58
- hideModalAfterCreate: this.hideModalAfterCreate,
59
- hideModalAfterUpdate: this.hideModalAfterUpdate,
60
- refreshAfterSave: this.refreshAfterSave,
61
- showPaginator: this.showPaginator,
62
- showCreateBtn: this.showCreateBtn,
63
- showSearch: this.showSearch,
64
- showPrincipalSortBtn: this.showPrincipalSortBtn,
65
- showHeader: this.showHeader,
66
- showTitle: this.showTitle,
67
- limit: this.limit,
68
- displayMode: this.displayMode,
69
- displayModeToggler: this.displayModeToggler,
70
- colXs: this.colXs,
71
- colSm: this.colSm,
72
- colMd: this.colMd,
73
- colLg: this.colLg,
74
- colXl: this.colXl,
75
- selectHover: this.selectHover,
76
- selectClick: this.selectClick,
77
- cardClass: this.cardClass,
78
- listContainerClass: this.listContainerClass,
79
- listItemClass: this.listItemClass,
80
- cardHideFooter: this.cardHideFooter,
81
- messageRemoveConfirm: this.messageRemoveConfirm,
82
- messageRemoveBulkConfirm: this.messageRemoveBulkConfirm,
83
- messageRemove: this.messageRemove,
84
- messageNew: this.messageNew,
85
- messageImport: this.messageImport,
86
- messageExport: this.messageExport,
87
- messageEmptyResults: this.messageEmptyResults,
88
- messageNoMore: this.messageNoMore,
89
- messageLoading: this.messageLoading,
90
- messageSave: this.messageSave,
91
- messageDefaultValidationError: this.messageDefaultValidationError,
92
- searchPlaceholder: this.searchPlaceholder,
93
- tableContainerClass: this.tableContainerClass,
94
- tableClass: this.tableClass,
95
- grouped: this.grouped,
96
- groupedAttribute: this.groupedAttribute,
97
- groupedLabelPre: this.groupedLabelPre,
98
- groupedLabelAfter: this.groupedLabelAfter,
99
- groupedSplit: this.groupedSplit,
100
- draggableGroup: this.draggableGroup,
101
- draggableOptions: this.draggableOptions,
102
- masonryEnabled: this.masonryEnabled,
103
- masonrySort: this.masonrySort,
104
- masonryColumns: this.masonryColumns,
105
- principalSortColumn: this.principalSortColumn,
106
- bulkDelete: this.bulkDelete,
107
- showImport: this.showImport,
108
- showExport: this.showExport,
109
- markDirty: this.markDirty,
110
-
111
- // Data from mixins
112
- crudUuid: this.crudUuid,
113
- moment: this.moment,
114
- loading: this.loading,
115
- firstLoad: this.firstLoad,
116
- item: this.item,
117
- items: this.items,
118
- selectedItems: this.selectedItems,
119
- pagination: this.pagination,
120
- displaySearch: this.displaySearch,
121
- itemDefault: this.itemDefault,
122
- filters: this.filters,
123
- filtersVisible: this.filtersVisible,
124
- filterSidebarOpen: this.filterSidebarOpen,
125
- internalFilters: this.internalFilters,
126
- forceRecomputeCounter: this.forceRecomputeCounter,
127
- displayModes: this.displayModes,
128
- infiniteScrollKey: this.infiniteScrollKey,
129
- optionsLoaded: this.optionsLoaded,
130
- isMobile: this.isMobile,
131
- refreshing: this.refreshing,
132
- fetchError: this.fetchError,
133
- principalSort: this.principalSort,
134
- exportFormat: this.exportFormat,
135
-
136
- // Computed from mixins
137
- itemValue: this.itemValue,
138
- isSplitGroups: this.isSplitGroups,
139
- itemsList: this.itemsList,
140
- paginationIndexStart: this.paginationIndexStart,
141
- paginationIndexEnd: this.paginationIndexEnd,
142
- finalFilters: this.finalFilters,
143
- sortFilter: this.sortFilter,
144
- groupFilter: this.groupFilter,
145
- internalFilter: this.internalFilter,
146
- internalFilterByProp: this.internalFilterByProp,
147
- columnOptions: this.columnOptions,
148
-
149
- // Methods from mixins
150
- handleResize: this.handleResize,
151
- rearrangeArray: this.rearrangeArray,
152
- clearItems: this.clearItems,
153
- updateData: this.updateData,
154
- externalUpdate: this.externalUpdate,
155
- makePagination: this.makePagination,
156
- fetchItemsVuex: this.fetchItemsVuex,
157
- fetchItemsLocal: this.fetchItemsLocal,
158
- fetchItems: this.fetchItems,
159
- groupItems: this.groupItems,
160
- saveItemVuex: this.saveItemVuex,
161
- saveItemLocal: this.saveItemLocal,
162
- saveItem: this.saveItem,
163
- deleteItem: this.deleteItem,
164
- deleteItemLocal: this.deleteItemLocal,
165
- deleteItemVuex: this.deleteItemVuex,
166
- deleteItemBulk: this.deleteItemBulk,
167
- deleteItemBulkLocal: this.deleteItemBulkLocal,
168
- deleteItemBulkVuex: this.deleteItemBulkVuex,
169
- saveSort: this.saveSort,
170
- exportItems: this.exportItems,
171
- importItems: this.importItems,
172
- refresh: this.refresh,
173
- onPaginationChange: this.onPaginationChange,
174
- infiniteHandler: this.infiniteHandler,
175
- setupFilters: this.setupFilters,
176
- toggleSortFilter: this.toggleSortFilter,
177
- toggleFilters: this.toggleFilters,
178
- resetFilters: this.resetFilters,
179
- isColumnHasFilter: this.isColumnHasFilter,
180
- setFilter: this.setFilter,
181
- onChangeFilter: this.onChangeFilter,
182
- togglePrincipalSort: this.togglePrincipalSort,
183
- loadOptions: this.loadOptions,
184
- getArrayValue: this.getArrayValue,
185
- getStateValue: this.getStateValue,
186
- onRowHover: this.onRowHover,
187
- onRowClick: this.onRowClick,
188
- onSort: this.onSort,
189
- onCheckSelect: this.onCheckSelect,
190
- toggleAll: this.toggleAll,
191
- unSelectItem: this.unSelectItem,
192
- selectItem: this.selectItem,
193
- getSelectedItems: this.getSelectedItems,
194
- onSelect: this.onSelect,
195
- showItem: this.showItem,
196
- createItem: this.createItem,
197
- updateItem: this.updateItem,
198
- removeItem: this.removeItem,
199
- confirmBulkDelete: this.confirmBulkDelete,
200
- toggleDisplayMode: this.toggleDisplayMode,
201
- showExportModal: this.showExportModal,
202
- showImportModal: this.showImportModal,
203
- onDraggableAdded: this.onDraggableAdded,
204
- onDraggableChange: this.onDraggableChange,
205
- onDragEnd: this.onDragEnd,
206
- toastError: this.toastError,
207
- toastSuccess: this.toastSuccess,
208
- downloadBlobResponse: this.downloadBlobResponse
209
- };
210
- },
211
- props: {
212
- modelName: String,
213
-
214
- title: String,
215
- model: {
216
- type: Object | Function,
217
- default() {
218
- return { id: 0 };
219
- },
220
- },
221
- models: {
222
- type: Array,
223
- default: () => [],
224
- },
225
- ajax: {
226
- type: Boolean,
227
- default: true,
228
- },
229
- useVuexORM: {
230
- type: Boolean,
231
- default: false,
232
- },
233
- vuexInitRelations: {
234
- type: Boolean | Array,
235
- default: true,
236
- },
237
- vuexLocalforage: {
238
- type: Boolean,
239
- default: false,
240
- },
241
-
242
- columns: {
243
- type: Array,
244
-
245
- default() {
246
- return [{ label: "Id", prop: "id", type: "number" }];
247
- },
248
- },
249
- filter: {
250
- type: Array,
251
- default: () => [],
252
- },
253
- enableFilters: {
254
- type: Boolean,
255
- default: false,
256
- },
257
-
258
- infiniteScroll: {
259
- type: Boolean,
260
- default: false,
261
- },
262
- sortable: {
263
- type: Boolean,
264
- default: false,
265
- },
266
- orderable: {
267
- type: Boolean,
268
- default: false,
269
- },
270
- validate: {
271
- type: Boolean,
272
- default: false,
273
- },
274
- orderProp: {
275
- type: String,
276
- default: "order",
277
- },
278
- createMultipart: {
279
- type: Boolean,
280
- default: false,
281
- },
282
- apiUrl: {
283
- type: String,
284
- default: "/api",
285
- },
286
- search: {
287
- type: String,
288
- default: "",
289
- },
290
- hideModalAfterSave: {
291
- type: Boolean,
292
- default: true,
293
- },
294
- hideModalAfterCreate: {
295
- type: Boolean,
296
- default: false,
297
- },
298
- hideModalAfterUpdate: {
299
- type: Boolean,
300
- default: false,
301
- },
302
- refreshAfterSave: {
303
- type: Boolean,
304
- default: true,
305
- },
306
- showPaginator: {
307
- type: Boolean,
308
- default: true,
309
- },
310
- showCreateBtn: {
311
- type: Boolean,
312
- default: true,
313
- },
314
- showSearch: {
315
- type: Boolean,
316
- default: true,
317
- },
318
- showPrincipalSortBtn: {
319
- type: Boolean,
320
- default: false,
321
- },
322
-
323
- showHeader: {
324
- type: Boolean,
325
- default: true,
326
- },
327
- showTitle: {
328
- type: Boolean,
329
- default: true,
330
- },
331
- limit: {
332
- type: Number,
333
- default: 20,
334
- },
335
- displayMode: {
336
- type: Number,
337
- default: 1,
338
- },
339
- displayModeToggler: {
340
- type: Boolean,
341
- default: false,
342
- },
343
-
344
- colXs: {
345
- default: 12,
346
- type: Number,
347
- },
348
- colSm: {
349
- default: 12,
350
- type: Number,
351
- },
352
- colMd: {
353
- default: 6,
354
- type: Number,
355
- },
356
- colLg: {
357
- default: 4,
358
- type: Number,
359
- },
360
- colXl: {
361
- default: 4,
362
- type: Number,
363
- },
364
-
365
- selectHover: {
366
- type: Boolean,
367
- default: false,
368
- },
369
- selectClick: {
370
- type: Boolean,
371
- default: false,
372
- },
373
-
374
- cardClass: {
375
- type: String,
376
- default: "",
377
- },
378
-
379
- listContainerClass: {
380
- type: String,
381
- default: "",
382
- },
383
-
384
- listItemClass: {
385
- type: String,
386
- default: "",
387
- },
388
-
389
- cardHideFooter: {
390
- type: Boolean,
391
- default: false,
392
- },
393
-
394
- messageRemoveConfirm: {
395
- type: String,
396
- default: "¿Esta seguro de borrar este elemento?",
397
- },
398
- messageRemoveBulkConfirm: {
399
- type: String,
400
- default: "¿Esta seguro de borrar los elementos seleccionados?",
401
- },
402
- messageRemove: {
403
- type: String,
404
- default: "BORRAR",
405
- },
406
- messageNew: {
407
- type: String,
408
- default: "Nuevo",
409
- },
410
- messageImport: {
411
- type: String,
412
- default: "Importar",
413
- },
414
- messageExport: {
415
- type: String,
416
- default: "Exportar",
417
- },
418
- messageEmptyResults: {
419
- type: String,
420
- default: "No se han encontrado resultados",
421
- },
422
- messageNoMore: {
423
- type: String,
424
- default: "No hay más elementos para mostrar.",
425
- },
426
- messageLoading: {
427
- type: String,
428
- default: "Cargando...",
429
- },
430
- messageSave: {
431
- type: String,
432
- default: "Guardar",
433
- },
434
- messageDefaultValidationError: {
435
- type: String,
436
- default: "Por favor controle el formulario, contiene errores.",
437
- },
438
- searchPlaceholder: {
439
- type: String,
440
- default: "Buscar...",
441
- },
442
-
443
- tableContainerClass: {
444
- type: String,
445
- default: "",
446
- },
447
- tableClass: {
448
- type: String,
449
- default: "",
450
- },
451
- grouped: {
452
- type: Boolean,
453
- default: false,
454
- },
455
- groupedAttribute: {
456
- type: String,
457
- default: "name",
458
- },
459
- groupedLabelPre: {
460
- type: String,
461
- default: "",
462
- },
463
- groupedLabelAfter: {
464
- type: String,
465
- default: "",
466
- },
467
- groupedSplit: {
468
- type: Boolean,
469
- default: false,
470
- },
471
- draggableGroup: {
472
- type: String,
473
- default: "people",
474
- },
475
-
476
- draggableOptions: {
477
- type: Object,
478
- default: function () {
479
- return { clone: false };
480
- }
481
-
482
- },
483
- masonryEnabled: {
484
- type: Boolean,
485
- default: false,
486
- },
487
-
488
- masonrySort: {
489
- type: Boolean,
490
- default: false,
491
- },
492
- masonryColumns: {
493
- type: Number,
494
- default: 3,
495
- },
496
-
497
- principalSortColumn: {
498
- type: String,
499
- default: "id",
500
- },
501
-
502
- bulkDelete: {
503
- type: Boolean,
504
- default: false,
505
- },
506
-
507
- showImport: {
508
- type: Boolean,
509
- default: false,
510
- },
511
-
512
- showExport: {
513
- type: Boolean,
514
- default: false,
515
- },
516
- markDirty: {
517
- type: Boolean,
518
- default: true,
519
- }
520
- },
521
-
522
- };
523
- </script>
524
-
525
- <template>
526
- <div class="crud">
527
- <CrudHeader />
528
-
529
- <CrudTable />
530
- <CrudCards />
531
- <CrudKanban />
532
- <CrudCustom />
533
-
534
- <b-overlay :show="loading" rounded="sm"></b-overlay>
535
-
536
- <CrudPagination />
537
- <CrudModals />
538
- </div>
539
- </template>
540
-
541
- <style lang="scss" scoped>
542
- tr td:last-child,
543
- tr td:first-child {
544
- width: 1%;
545
- white-space: nowrap;
546
- }
547
-
548
- .crud-pagination {
549
- display: flex;
550
- align-items: center;
551
- width: 100%;
552
- justify-content: center;
553
- margin-top: 1rem;
554
- }
555
-
556
- .crud-header {
557
- display: flex;
558
- justify-content: space-between;
559
- max-height: 3rem;
560
-
561
- .crud-title {
562
- margin: 0;
563
- }
564
-
565
- .crud-search {
566
- max-width: 15rem;
567
-
568
- .btn {
569
- border-top-left-radius: 0;
570
- border-bottom-left-radius: 0;
571
- border-top-right-radius: 0.375rem;
572
- border-bottom-right-radius: 0.375rem;
573
-
574
- &.open {
575
- border-top-right-radius: 0;
576
- border-bottom-right-radius: 0;
577
- }
578
- }
579
- }
580
-
581
- .table-options {
582
- margin-bottom: 1rem;
583
- display: flex;
584
- align-items: center;
585
- justify-content: flex-end;
586
- }
587
- }
588
-
589
- .custom-control {
590
- position: relative;
591
- }
592
-
593
-
594
- @media (min-width: 992px) {
595
- .table {
596
- table-layout: auto;
597
-
598
- tbody {
599
- td {
600
- overflow: scroll;
601
- -ms-overflow-style: none;
602
- /* IE and Edge */
603
- scrollbar-width: none;
604
- /* Firefox */
605
- }
606
-
607
- td::-webkit-scrollbar {
608
- display: none;
609
- }
610
- }
611
- }
612
- }
613
-
614
-
615
- .kanban-board {
616
- display: flex;
617
- gap: 1rem;
618
- overflow-x: auto;
619
- padding: 1rem;
620
- }
621
-
622
- .kanban-column {
623
- background: #f4f5f7;
624
- border-radius: 8px;
625
- width: 300px;
626
- display: flex;
627
- flex-direction: column;
628
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
629
- }
630
-
631
- .kanban-column-header {
632
- font-weight: bold;
633
- padding: 0.5rem;
634
- background: #dfe1e6;
635
- border-radius: 8px 8px 0 0;
636
- text-align: center;
637
- }
638
-
639
- .kanban-column-body {
640
- padding: 0.5rem;
641
- min-height: 100px;
642
- background: #ffffff;
643
- border-radius: 0 0 8px 8px;
644
- display: flex;
645
- flex-direction: column;
646
- gap: 0.5rem;
647
- }
648
-
649
- .kanban-card {
650
- background: #ffffff;
651
- border-radius: 4px;
652
- padding: 1rem;
653
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
654
- cursor: grab;
655
- }
1
+ <script>
2
+ import CrudHeader from "./components/CrudHeader.vue";
3
+ import CrudTable from "./components/CrudTable.vue";
4
+ import CrudCards from "./components/CrudCards.vue";
5
+ import CrudKanban from "./components/CrudKanban.vue";
6
+ import CrudCustom from "./components/CrudCustom.vue";
7
+ import CrudModals from "./components/CrudModals.vue";
8
+ import CrudPagination from "./components/CrudPagination.vue";
9
+
10
+ // Import mixins
11
+ import crudData from "./mixins/crudData.js";
12
+ import crudApi from "./mixins/crudApi.js";
13
+ import crudFilters from "./mixins/crudFilters.js";
14
+ import crudValidation from "./mixins/crudValidation.js";
15
+ import crudHelpers from "./mixins/crudHelpers.js";
16
+
17
+ export default /*#__PURE__*/ {
18
+ name: "VueLaravelCrud",
19
+ components: {
20
+ CrudHeader,
21
+ CrudTable,
22
+ CrudCards,
23
+ CrudKanban,
24
+ CrudCustom,
25
+ CrudModals,
26
+ CrudPagination
27
+ },
28
+ mixins: [
29
+ crudData,
30
+ crudApi,
31
+ crudFilters,
32
+ crudValidation,
33
+ crudHelpers
34
+ ],
35
+ provide() {
36
+ return {
37
+ // Props
38
+ modelName: this.modelName,
39
+ title: this.title,
40
+ model: this.model,
41
+ models: this.models,
42
+ ajax: this.ajax,
43
+ useVuexORM: this.useVuexORM,
44
+ vuexInitRelations: this.vuexInitRelations,
45
+ vuexLocalforage: this.vuexLocalforage,
46
+ columns: this.columns,
47
+ filter: this.filter,
48
+ enableFilters: this.enableFilters,
49
+ infiniteScroll: this.infiniteScroll,
50
+ sortable: this.sortable,
51
+ orderable: this.orderable,
52
+ validate: this.validate,
53
+ orderProp: this.orderProp,
54
+ createMultipart: this.createMultipart,
55
+ apiUrl: this.apiUrl,
56
+ search: this.search,
57
+ hideModalAfterSave: this.hideModalAfterSave,
58
+ hideModalAfterCreate: this.hideModalAfterCreate,
59
+ hideModalAfterUpdate: this.hideModalAfterUpdate,
60
+ refreshAfterSave: this.refreshAfterSave,
61
+ showPaginator: this.showPaginator,
62
+ showCreateBtn: this.showCreateBtn,
63
+ showSearch: this.showSearch,
64
+ showPrincipalSortBtn: this.showPrincipalSortBtn,
65
+ showHeader: this.showHeader,
66
+ showTitle: this.showTitle,
67
+ limit: this.limit,
68
+ displayMode: this.displayMode,
69
+ displayModeToggler: this.displayModeToggler,
70
+ colXs: this.colXs,
71
+ colSm: this.colSm,
72
+ colMd: this.colMd,
73
+ colLg: this.colLg,
74
+ colXl: this.colXl,
75
+ selectHover: this.selectHover,
76
+ selectClick: this.selectClick,
77
+ cardClass: this.cardClass,
78
+ listContainerClass: this.listContainerClass,
79
+ listItemClass: this.listItemClass,
80
+ cardHideFooter: this.cardHideFooter,
81
+ messageRemoveConfirm: this.messageRemoveConfirm,
82
+ messageRemoveBulkConfirm: this.messageRemoveBulkConfirm,
83
+ messageRemove: this.messageRemove,
84
+ messageNew: this.messageNew,
85
+ messageImport: this.messageImport,
86
+ messageExport: this.messageExport,
87
+ messageEmptyResults: this.messageEmptyResults,
88
+ messageNoMore: this.messageNoMore,
89
+ messageLoading: this.messageLoading,
90
+ messageSave: this.messageSave,
91
+ messageDefaultValidationError: this.messageDefaultValidationError,
92
+ searchPlaceholder: this.searchPlaceholder,
93
+ tableContainerClass: this.tableContainerClass,
94
+ tableClass: this.tableClass,
95
+ grouped: this.grouped,
96
+ groupedAttribute: this.groupedAttribute,
97
+ groupedLabelPre: this.groupedLabelPre,
98
+ groupedLabelAfter: this.groupedLabelAfter,
99
+ groupedSplit: this.groupedSplit,
100
+ draggableGroup: this.draggableGroup,
101
+ draggableOptions: this.draggableOptions,
102
+ masonryEnabled: this.masonryEnabled,
103
+ masonrySort: this.masonrySort,
104
+ masonryColumns: this.masonryColumns,
105
+ principalSortColumn: this.principalSortColumn,
106
+ bulkDelete: this.bulkDelete,
107
+ showImport: this.showImport,
108
+ showExport: this.showExport,
109
+ fileImport: this.fileImport,
110
+ markDirty: this.markDirty,
111
+
112
+ // Data from mixins
113
+ crudUuid: this.crudUuid,
114
+ moment: this.moment,
115
+ loading: this.loading,
116
+ firstLoad: this.firstLoad,
117
+ item: this.item,
118
+ items: this.items,
119
+ selectedItems: this.selectedItems,
120
+ pagination: this.pagination,
121
+ displaySearch: this.displaySearch,
122
+ itemDefault: this.itemDefault,
123
+ filters: this.filters,
124
+ filtersVisible: this.filtersVisible,
125
+ filterSidebarOpen: this.filterSidebarOpen,
126
+ internalFilters: this.internalFilters,
127
+ forceRecomputeCounter: this.forceRecomputeCounter,
128
+ displayModes: this.displayModes,
129
+ infiniteScrollKey: this.infiniteScrollKey,
130
+ optionsLoaded: this.optionsLoaded,
131
+ isMobile: this.isMobile,
132
+ refreshing: this.refreshing,
133
+ fetchError: this.fetchError,
134
+ principalSort: this.principalSort,
135
+ exportFormat: this.exportFormat,
136
+
137
+ // Computed from mixins
138
+ itemValue: this.itemValue,
139
+ isSplitGroups: this.isSplitGroups,
140
+ itemsList: this.itemsList,
141
+ paginationIndexStart: this.paginationIndexStart,
142
+ paginationIndexEnd: this.paginationIndexEnd,
143
+ finalFilters: this.finalFilters,
144
+ sortFilter: this.sortFilter,
145
+ groupFilter: this.groupFilter,
146
+ internalFilter: this.internalFilter,
147
+ internalFilterByProp: this.internalFilterByProp,
148
+ columnOptions: this.columnOptions,
149
+ isAllSelected: this.isAllSelected,
150
+
151
+ // Methods from mixins
152
+ handleResize: this.handleResize,
153
+ rearrangeArray: this.rearrangeArray,
154
+ clearItems: this.clearItems,
155
+ updateData: this.updateData,
156
+ externalUpdate: this.externalUpdate,
157
+ makePagination: this.makePagination,
158
+ fetchItemsVuex: this.fetchItemsVuex,
159
+ fetchItemsLocal: this.fetchItemsLocal,
160
+ fetchItems: this.fetchItems,
161
+ groupItems: this.groupItems,
162
+ saveItemVuex: this.saveItemVuex,
163
+ saveItemLocal: this.saveItemLocal,
164
+ saveItem: this.saveItem,
165
+ deleteItem: this.deleteItem,
166
+ deleteItemLocal: this.deleteItemLocal,
167
+ deleteItemVuex: this.deleteItemVuex,
168
+ deleteItemBulk: this.deleteItemBulk,
169
+ deleteItemBulkLocal: this.deleteItemBulkLocal,
170
+ deleteItemBulkVuex: this.deleteItemBulkVuex,
171
+ saveSort: this.saveSort,
172
+ exportItems: this.exportItems,
173
+ importItems: this.importItems,
174
+ refresh: this.refresh,
175
+ onPaginationChange: this.onPaginationChange,
176
+ onPerPageChange: this.onPerPageChange,
177
+ infiniteHandler: this.infiniteHandler,
178
+ setupFilters: this.setupFilters,
179
+ toggleSortFilter: this.toggleSortFilter,
180
+ toggleFilters: this.toggleFilters,
181
+ resetFilters: this.resetFilters,
182
+ isColumnHasFilter: this.isColumnHasFilter,
183
+ setFilter: this.setFilter,
184
+ onChangeFilter: this.onChangeFilter,
185
+ togglePrincipalSort: this.togglePrincipalSort,
186
+ loadOptions: this.loadOptions,
187
+ getArrayValue: this.getArrayValue,
188
+ getStateValue: this.getStateValue,
189
+ onRowHover: this.onRowHover,
190
+ onRowClick: this.onRowClick,
191
+ onSort: this.onSort,
192
+ onCheckSelect: this.onCheckSelect,
193
+ toggleAll: this.toggleAll,
194
+ unSelectItem: this.unSelectItem,
195
+ selectItem: this.selectItem,
196
+ getSelectedItems: this.getSelectedItems,
197
+ clearSelection: this.clearSelection,
198
+ onSelect: this.onSelect,
199
+ showItem: this.showItem,
200
+ createItem: this.createItem,
201
+ updateItem: this.updateItem,
202
+ removeItem: this.removeItem,
203
+ confirmBulkDelete: this.confirmBulkDelete,
204
+ toggleDisplayMode: this.toggleDisplayMode,
205
+ showExportModal: this.showExportModal,
206
+ showImportModal: this.showImportModal,
207
+ onDraggableAdded: this.onDraggableAdded,
208
+ onDraggableChange: this.onDraggableChange,
209
+ onDragEnd: this.onDragEnd,
210
+ toastError: this.toastError,
211
+ toastSuccess: this.toastSuccess,
212
+ downloadBlobResponse: this.downloadBlobResponse
213
+ };
214
+ },
215
+ props: {
216
+ modelName: String,
217
+
218
+ title: String,
219
+ model: {
220
+ type: Object | Function,
221
+ default() {
222
+ return { id: 0 };
223
+ },
224
+ },
225
+ models: {
226
+ type: Array,
227
+ default: () => [],
228
+ },
229
+ ajax: {
230
+ type: Boolean,
231
+ default: true,
232
+ },
233
+ useVuexORM: {
234
+ type: Boolean,
235
+ default: false,
236
+ },
237
+ vuexInitRelations: {
238
+ type: Boolean | Array,
239
+ default: true,
240
+ },
241
+ vuexLocalforage: {
242
+ type: Boolean,
243
+ default: false,
244
+ },
245
+
246
+ columns: {
247
+ type: Array,
248
+
249
+ default() {
250
+ return [{ label: "Id", prop: "id", type: "number" }];
251
+ },
252
+ },
253
+ filter: {
254
+ type: Array,
255
+ default: () => [],
256
+ },
257
+ enableFilters: {
258
+ type: Boolean,
259
+ default: false,
260
+ },
261
+
262
+ infiniteScroll: {
263
+ type: Boolean,
264
+ default: false,
265
+ },
266
+ sortable: {
267
+ type: Boolean,
268
+ default: false,
269
+ },
270
+ orderable: {
271
+ type: Boolean,
272
+ default: false,
273
+ },
274
+ validate: {
275
+ type: Boolean,
276
+ default: false,
277
+ },
278
+ orderProp: {
279
+ type: String,
280
+ default: "order",
281
+ },
282
+ createMultipart: {
283
+ type: Boolean,
284
+ default: false,
285
+ },
286
+ apiUrl: {
287
+ type: String,
288
+ default: "/api",
289
+ },
290
+ search: {
291
+ type: String,
292
+ default: "",
293
+ },
294
+ hideModalAfterSave: {
295
+ type: Boolean,
296
+ default: true,
297
+ },
298
+ hideModalAfterCreate: {
299
+ type: Boolean,
300
+ default: false,
301
+ },
302
+ hideModalAfterUpdate: {
303
+ type: Boolean,
304
+ default: false,
305
+ },
306
+ refreshAfterSave: {
307
+ type: Boolean,
308
+ default: true,
309
+ },
310
+ showPaginator: {
311
+ type: Boolean,
312
+ default: true,
313
+ },
314
+ showCreateBtn: {
315
+ type: Boolean,
316
+ default: true,
317
+ },
318
+ showSearch: {
319
+ type: Boolean,
320
+ default: true,
321
+ },
322
+ showPrincipalSortBtn: {
323
+ type: Boolean,
324
+ default: false,
325
+ },
326
+
327
+ showHeader: {
328
+ type: Boolean,
329
+ default: true,
330
+ },
331
+ showTitle: {
332
+ type: Boolean,
333
+ default: true,
334
+ },
335
+ limit: {
336
+ type: Number,
337
+ default: 20,
338
+ },
339
+ displayMode: {
340
+ type: Number,
341
+ default: 1,
342
+ },
343
+ displayModeToggler: {
344
+ type: Boolean,
345
+ default: false,
346
+ },
347
+
348
+ colXs: {
349
+ default: 12,
350
+ type: Number,
351
+ },
352
+ colSm: {
353
+ default: 12,
354
+ type: Number,
355
+ },
356
+ colMd: {
357
+ default: 6,
358
+ type: Number,
359
+ },
360
+ colLg: {
361
+ default: 4,
362
+ type: Number,
363
+ },
364
+ colXl: {
365
+ default: 4,
366
+ type: Number,
367
+ },
368
+
369
+ selectHover: {
370
+ type: Boolean,
371
+ default: false,
372
+ },
373
+ selectClick: {
374
+ type: Boolean,
375
+ default: false,
376
+ },
377
+
378
+ cardClass: {
379
+ type: String,
380
+ default: "",
381
+ },
382
+
383
+ listContainerClass: {
384
+ type: String,
385
+ default: "",
386
+ },
387
+
388
+ listItemClass: {
389
+ type: String,
390
+ default: "",
391
+ },
392
+
393
+ cardHideFooter: {
394
+ type: Boolean,
395
+ default: false,
396
+ },
397
+
398
+ messageRemoveConfirm: {
399
+ type: String,
400
+ default: "¿Esta seguro de borrar este elemento?",
401
+ },
402
+ messageRemoveBulkConfirm: {
403
+ type: String,
404
+ default: "¿Esta seguro de borrar los elementos seleccionados?",
405
+ },
406
+ messageRemove: {
407
+ type: String,
408
+ default: "BORRAR",
409
+ },
410
+ messageNew: {
411
+ type: String,
412
+ default: "Nuevo",
413
+ },
414
+ messageImport: {
415
+ type: String,
416
+ default: "Importar",
417
+ },
418
+ messageExport: {
419
+ type: String,
420
+ default: "Exportar",
421
+ },
422
+ messageEmptyResults: {
423
+ type: String,
424
+ default: "No se han encontrado resultados",
425
+ },
426
+ messageNoMore: {
427
+ type: String,
428
+ default: "No hay más elementos para mostrar.",
429
+ },
430
+ messageLoading: {
431
+ type: String,
432
+ default: "Cargando...",
433
+ },
434
+ messageSave: {
435
+ type: String,
436
+ default: "Guardar",
437
+ },
438
+ messageDefaultValidationError: {
439
+ type: String,
440
+ default: "Por favor controle el formulario, contiene errores.",
441
+ },
442
+ searchPlaceholder: {
443
+ type: String,
444
+ default: "Buscar...",
445
+ },
446
+
447
+ tableContainerClass: {
448
+ type: String,
449
+ default: "",
450
+ },
451
+ tableClass: {
452
+ type: String,
453
+ default: "",
454
+ },
455
+ grouped: {
456
+ type: Boolean,
457
+ default: false,
458
+ },
459
+ groupedAttribute: {
460
+ type: String,
461
+ default: "name",
462
+ },
463
+ groupedLabelPre: {
464
+ type: String,
465
+ default: "",
466
+ },
467
+ groupedLabelAfter: {
468
+ type: String,
469
+ default: "",
470
+ },
471
+ groupedSplit: {
472
+ type: Boolean,
473
+ default: false,
474
+ },
475
+ draggableGroup: {
476
+ type: String,
477
+ default: "people",
478
+ },
479
+
480
+ draggableOptions: {
481
+ type: Object,
482
+ default: function () {
483
+ return { clone: false };
484
+ }
485
+
486
+ },
487
+ masonryEnabled: {
488
+ type: Boolean,
489
+ default: false,
490
+ },
491
+
492
+ masonrySort: {
493
+ type: Boolean,
494
+ default: false,
495
+ },
496
+ masonryColumns: {
497
+ type: Number,
498
+ default: 3,
499
+ },
500
+
501
+ principalSortColumn: {
502
+ type: String,
503
+ default: "id",
504
+ },
505
+
506
+ bulkDelete: {
507
+ type: Boolean,
508
+ default: false,
509
+ },
510
+
511
+ showImport: {
512
+ type: Boolean,
513
+ default: false,
514
+ },
515
+
516
+ showExport: {
517
+ type: Boolean,
518
+ default: false,
519
+ },
520
+ markDirty: {
521
+ type: Boolean,
522
+ default: true,
523
+ }
524
+ },
525
+
526
+ };
527
+ </script>
528
+
529
+ <template>
530
+ <div class="crud">
531
+ <CrudHeader />
532
+
533
+ <CrudTable />
534
+ <CrudCards />
535
+ <CrudKanban />
536
+ <CrudCustom />
537
+
538
+ <b-overlay :show="loading" rounded="sm"></b-overlay>
539
+
540
+ <CrudPagination />
541
+ <CrudModals>
542
+ <template v-for="(slot, name) in $scopedSlots" v-slot:[name]="slotProps">
543
+ <slot :name="name" v-bind="slotProps" />
544
+ </template>
545
+ </CrudModals>
546
+ </div>
547
+ </template>
548
+
549
+ <style lang="scss" scoped>
550
+ tr td:last-child,
551
+ tr td:first-child {
552
+ width: 1%;
553
+ white-space: nowrap;
554
+ }
555
+
556
+ tbody tr.selected {
557
+ background-color: #e3f2fd !important;
558
+
559
+ td {
560
+ background-color: transparent !important;
561
+ }
562
+
563
+ &:hover {
564
+ background-color: #bbdefb !important;
565
+
566
+ td {
567
+ background-color: transparent !important;
568
+ }
569
+ }
570
+ }
571
+
572
+ .table-striped tbody tr.selected:nth-of-type(odd) {
573
+ background-color: #e3f2fd !important;
574
+
575
+ td {
576
+ background-color: transparent !important;
577
+ }
578
+ }
579
+
580
+ .table-striped tbody tr.selected:nth-of-type(even) {
581
+ background-color: #e3f2fd !important;
582
+
583
+ td {
584
+ background-color: transparent !important;
585
+ }
586
+ }
587
+
588
+ .crud-pagination {
589
+ display: flex;
590
+ align-items: center;
591
+ width: 100%;
592
+ justify-content: center;
593
+ margin-top: 1rem;
594
+ }
595
+
596
+ .crud-header {
597
+ display: flex;
598
+ justify-content: space-between;
599
+ max-height: 3rem;
600
+
601
+ .crud-title {
602
+ margin: 0;
603
+ }
604
+
605
+ .crud-search {
606
+ max-width: 15rem;
607
+
608
+ .btn {
609
+ border-top-left-radius: 0;
610
+ border-bottom-left-radius: 0;
611
+ border-top-right-radius: 0.375rem;
612
+ border-bottom-right-radius: 0.375rem;
613
+
614
+ &.open {
615
+ border-top-right-radius: 0;
616
+ border-bottom-right-radius: 0;
617
+ }
618
+ }
619
+ }
620
+
621
+ .table-options {
622
+ margin-bottom: 1rem;
623
+ display: flex;
624
+ align-items: center;
625
+ justify-content: flex-end;
626
+ }
627
+ }
628
+
629
+ .custom-control {
630
+ position: relative;
631
+ }
632
+
633
+
634
+ @media (min-width: 992px) {
635
+ .table {
636
+ table-layout: auto;
637
+
638
+ tbody {
639
+ td {
640
+ overflow: scroll;
641
+ -ms-overflow-style: none;
642
+ /* IE and Edge */
643
+ scrollbar-width: none;
644
+ /* Firefox */
645
+ }
646
+
647
+ td::-webkit-scrollbar {
648
+ display: none;
649
+ }
650
+ }
651
+ }
652
+ }
653
+
654
+
655
+ .kanban-board {
656
+ display: flex;
657
+ gap: 1rem;
658
+ overflow-x: auto;
659
+ padding: 1rem;
660
+ }
661
+
662
+ .kanban-column {
663
+ background: #f4f5f7;
664
+ border-radius: 8px;
665
+ width: 300px;
666
+ display: flex;
667
+ flex-direction: column;
668
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
669
+ }
670
+
671
+ .kanban-column-header {
672
+ font-weight: bold;
673
+ padding: 0.5rem;
674
+ background: #dfe1e6;
675
+ border-radius: 8px 8px 0 0;
676
+ text-align: center;
677
+ }
678
+
679
+ .kanban-column-body {
680
+ padding: 0.5rem;
681
+ min-height: 100px;
682
+ background: #ffffff;
683
+ border-radius: 0 0 8px 8px;
684
+ display: flex;
685
+ flex-direction: column;
686
+ gap: 0.5rem;
687
+ }
688
+
689
+ .kanban-card {
690
+ background: #ffffff;
691
+ border-radius: 4px;
692
+ padding: 1rem;
693
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
694
+ cursor: grab;
695
+ }
656
696
  </style>