vue-laravel-crud 2.0.6 → 2.0.7

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,200 +1,207 @@
1
- <template>
2
- <div>
3
- <!-- Infinite Loading -->
4
- <infinite-loading
5
- ref="infiniteLoading"
6
- @infinite="infiniteHandler"
7
- v-if="infiniteScroll"
8
- :forceUseInfiniteWrapper="true"
9
- :key="infiniteScrollKey"
10
- >
11
- <div slot="spinner">
12
- <div class="text-center">{{ messageLoading }}</div>
13
- </div>
14
- <div slot="no-more">
15
- <div class="text-center" v-if="!loading">{{ messageNoMore }}</div>
16
- </div>
17
- <div slot="no-results">
18
- <div class="text-center" v-if="!loading">{{ items.length == 0 ? messageEmptyResults : messageNoMore }}</div>
19
- </div>
20
- </infinite-loading>
21
-
22
- <!-- Paginador -->
23
- <div class="paginator-container" v-if="!infiniteScroll">
24
- <div class="paginator-data">
25
- <span class="paginator-badge">
26
- <span class="paginator-label">Filas:</span>
27
- <span class="paginator-value">{{ pagination.total }}</span>
28
- </span>
29
- <b-dropdown
30
- variant="outline-secondary"
31
- size="sm"
32
- class="paginator-dropdown"
33
- :text="`xPág: ${pagination.per_page}`"
34
- >
35
- <b-dropdown-item
36
- v-for="option in perPageOptions"
37
- :key="option"
38
- @click="onPerPageChange(option)"
39
- :active="pagination.per_page === option"
40
- >
41
- {{ option }}
42
- </b-dropdown-item>
43
- </b-dropdown>
44
- <b-dropdown
45
- v-if="selectedItemsCount > 0"
46
- variant="outline-secondary"
47
- size="sm"
48
- class="paginator-dropdown paginator-badge-dropdown"
49
- :text="`Seleccionados: ${selectedItemsCount}`"
50
- >
51
- <b-dropdown-item @click="clearSelection">
52
- <b-icon-x-circle class="mr-1"></b-icon-x-circle>
53
- Limpiar selección
54
- </b-dropdown-item>
55
- </b-dropdown>
56
- </div>
57
-
58
- <div class="crud-paginator">
59
- <b-pagination
60
- v-if="showPaginator"
61
- v-model="pagination.current_page"
62
- :total-rows="pagination.total"
63
- :per-page="pagination.per_page"
64
- @change="onPaginationChange($event)"
65
- ></b-pagination>
66
- </div>
67
- </div>
68
- </div>
69
- </template>
70
-
71
- <script>
72
- import InfiniteLoading from 'vue-infinite-loading';
73
-
74
- export default {
75
- name: 'CrudPagination',
76
- components: {
77
- InfiniteLoading
78
- },
79
- inject: [
80
- 'infiniteScroll',
81
- 'infiniteScrollKey',
82
- 'messageLoading',
83
- 'messageNoMore',
84
- 'messageEmptyResults',
85
- 'loading',
86
- 'items',
87
- 'pagination',
88
- 'selectedItems',
89
- 'showPaginator',
90
- 'infiniteHandler',
91
- 'onPaginationChange',
92
- 'onPerPageChange',
93
- 'clearSelection'
94
- ],
95
- data() {
96
- return {
97
- perPageOptions: [10, 20, 50, 100]
98
- };
99
- },
100
- computed: {
101
- selectedItemsCount() {
102
- // Computed para forzar reactividad del contador
103
- return this.selectedItems ? this.selectedItems.length : 0;
104
- }
105
- }
106
- };
107
- </script>
108
-
109
- <style scoped>
110
- .paginator-container {
111
- display: grid;
112
- grid-template-columns: 1fr auto 1fr;
113
- align-items: center;
114
- width: 100%;
115
- margin-top: 1rem;
116
- gap: 1rem;
117
- }
118
-
119
- .paginator-data {
120
- display: flex;
121
- flex-wrap: nowrap;
122
- justify-content: flex-start;
123
- align-items: center;
124
- gap: 0.5rem;
125
- font-size: 0.875rem;
126
- grid-column: 1;
127
- }
128
-
129
- .paginator-badge {
130
- display: inline-flex;
131
- align-items: center;
132
- gap: 0.25rem;
133
- padding: 0.375rem 0.625rem;
134
- background-color: #f8f9fa;
135
- border: 1px solid #dee2e6;
136
- border-radius: 0.375rem;
137
- color: #495057;
138
- transition: all 0.2s ease;
139
- }
140
-
141
- .paginator-badge:hover {
142
- background-color: #e9ecef;
143
- border-color: #ced4da;
144
- }
145
-
146
- .paginator-label {
147
- font-weight: 500;
148
- color: #6c757d;
149
- }
150
-
151
- .paginator-value {
152
- font-weight: 600;
153
- color: #212529;
154
- }
155
-
156
- .paginator-dropdown {
157
- font-size: 0.875rem;
158
- }
159
-
160
- .paginator-dropdown >>> .btn {
161
- padding: 0.375rem 0.625rem;
162
- font-size: 0.875rem;
163
- background-color: #f8f9fa;
164
- border: 1px solid #dee2e6;
165
- color: #495057;
166
- }
167
-
168
- .paginator-dropdown >>> .btn:hover {
169
- background-color: #e9ecef;
170
- border-color: #ced4da;
171
- }
172
-
173
- .crud-paginator {
174
- display: flex;
175
- justify-content: center;
176
- align-items: center;
177
- grid-column: 2;
178
- }
179
-
180
- .paginator-badge-dropdown {
181
- z-index: 1;
182
- position: relative;
183
- }
184
-
185
- .paginator-badge-dropdown >>> .btn {
186
- padding: 0.375rem 0.625rem;
187
- font-size: 0.875rem;
188
- background-color: #f8f9fa;
189
- border: 1px solid #dee2e6;
190
- color: #495057;
191
- display: inline-flex;
192
- align-items: center;
193
- gap: 0.25rem;
194
- }
195
-
196
- .paginator-badge-dropdown >>> .btn:hover {
197
- background-color: #e9ecef;
198
- border-color: #ced4da;
199
- }
200
- </style>
1
+ <template>
2
+ <div>
3
+ <!-- Infinite Loading -->
4
+ <infinite-loading
5
+ ref="infiniteLoading"
6
+ @infinite="infiniteHandler"
7
+ v-if="infiniteScroll"
8
+ :forceUseInfiniteWrapper="true"
9
+ :key="infiniteScrollKey"
10
+ >
11
+ <div slot="spinner">
12
+ <div class="text-center">{{ messageLoading }}</div>
13
+ </div>
14
+ <div slot="no-more">
15
+ <div class="text-center" v-if="!loadingValue">{{ messageNoMore }}</div>
16
+ </div>
17
+ <div slot="no-results">
18
+ <div class="text-center" v-if="!loadingValue && firstLoadValue">{{ items.length == 0 ? messageEmptyResults : messageNoMore }}</div>
19
+ </div>
20
+ </infinite-loading>
21
+
22
+ <!-- Paginador -->
23
+ <div class="paginator-container" v-if="!infiniteScroll">
24
+ <div class="paginator-data">
25
+ <span class="paginator-badge">
26
+ <span class="paginator-label">Filas:</span>
27
+ <span class="paginator-value">{{ pagination.total }}</span>
28
+ </span>
29
+ <b-dropdown
30
+ variant="outline-secondary"
31
+ size="sm"
32
+ class="paginator-dropdown"
33
+ :text="`xPág: ${pagination.per_page}`"
34
+ >
35
+ <b-dropdown-item
36
+ v-for="option in perPageOptions"
37
+ :key="option"
38
+ @click="onPerPageChange(option)"
39
+ :active="pagination.per_page === option"
40
+ >
41
+ {{ option }}
42
+ </b-dropdown-item>
43
+ </b-dropdown>
44
+ <b-dropdown
45
+ v-if="selectedItemsCount > 0"
46
+ variant="outline-secondary"
47
+ size="sm"
48
+ class="paginator-dropdown paginator-badge-dropdown"
49
+ :text="`Seleccionados: ${selectedItemsCount}`"
50
+ >
51
+ <b-dropdown-item @click="clearSelection">
52
+ <b-icon-x-circle class="mr-1"></b-icon-x-circle>
53
+ Limpiar selección
54
+ </b-dropdown-item>
55
+ </b-dropdown>
56
+ </div>
57
+
58
+ <div class="crud-paginator">
59
+ <b-pagination
60
+ v-if="showPaginator"
61
+ v-model="pagination.current_page"
62
+ :total-rows="pagination.total"
63
+ :per-page="pagination.per_page"
64
+ @change="onPaginationChange($event)"
65
+ ></b-pagination>
66
+ </div>
67
+ </div>
68
+ </div>
69
+ </template>
70
+
71
+ <script>
72
+ import InfiniteLoading from 'vue-infinite-loading';
73
+
74
+ export default {
75
+ name: 'CrudPagination',
76
+ components: {
77
+ InfiniteLoading
78
+ },
79
+ inject: [
80
+ 'infiniteScroll',
81
+ 'infiniteScrollKey',
82
+ 'messageLoading',
83
+ 'messageNoMore',
84
+ 'messageEmptyResults',
85
+ 'loading',
86
+ 'firstLoad',
87
+ 'items',
88
+ 'pagination',
89
+ 'selectedItems',
90
+ 'showPaginator',
91
+ 'infiniteHandler',
92
+ 'onPaginationChange',
93
+ 'onPerPageChange',
94
+ 'clearSelection'
95
+ ],
96
+ data() {
97
+ return {
98
+ perPageOptions: [10, 20, 50, 100]
99
+ };
100
+ },
101
+ computed: {
102
+ selectedItemsCount() {
103
+ // Computed para forzar reactividad del contador
104
+ return this.selectedItems ? this.selectedItems.length : 0;
105
+ },
106
+ loadingValue() {
107
+ return this.loading && this.loading.value !== undefined ? this.loading.value : this.loading;
108
+ },
109
+ firstLoadValue() {
110
+ return this.firstLoad && this.firstLoad.value !== undefined ? this.firstLoad.value : this.firstLoad;
111
+ }
112
+ }
113
+ };
114
+ </script>
115
+
116
+ <style scoped>
117
+ .paginator-container {
118
+ display: grid;
119
+ grid-template-columns: 1fr auto 1fr;
120
+ align-items: center;
121
+ width: 100%;
122
+ margin-top: 1rem;
123
+ gap: 1rem;
124
+ }
125
+
126
+ .paginator-data {
127
+ display: flex;
128
+ flex-wrap: nowrap;
129
+ justify-content: flex-start;
130
+ align-items: center;
131
+ gap: 0.5rem;
132
+ font-size: 0.875rem;
133
+ grid-column: 1;
134
+ }
135
+
136
+ .paginator-badge {
137
+ display: inline-flex;
138
+ align-items: center;
139
+ gap: 0.25rem;
140
+ padding: 0.375rem 0.625rem;
141
+ background-color: #f8f9fa;
142
+ border: 1px solid #dee2e6;
143
+ border-radius: 0.375rem;
144
+ color: #495057;
145
+ transition: all 0.2s ease;
146
+ }
147
+
148
+ .paginator-badge:hover {
149
+ background-color: #e9ecef;
150
+ border-color: #ced4da;
151
+ }
152
+
153
+ .paginator-label {
154
+ font-weight: 500;
155
+ color: #6c757d;
156
+ }
157
+
158
+ .paginator-value {
159
+ font-weight: 600;
160
+ color: #212529;
161
+ }
162
+
163
+ .paginator-dropdown {
164
+ font-size: 0.875rem;
165
+ }
166
+
167
+ .paginator-dropdown >>> .btn {
168
+ padding: 0.375rem 0.625rem;
169
+ font-size: 0.875rem;
170
+ background-color: #f8f9fa;
171
+ border: 1px solid #dee2e6;
172
+ color: #495057;
173
+ }
174
+
175
+ .paginator-dropdown >>> .btn:hover {
176
+ background-color: #e9ecef;
177
+ border-color: #ced4da;
178
+ }
179
+
180
+ .crud-paginator {
181
+ display: flex;
182
+ justify-content: center;
183
+ align-items: center;
184
+ grid-column: 2;
185
+ }
186
+
187
+ .paginator-badge-dropdown {
188
+ z-index: 1;
189
+ position: relative;
190
+ }
191
+
192
+ .paginator-badge-dropdown >>> .btn {
193
+ padding: 0.375rem 0.625rem;
194
+ font-size: 0.875rem;
195
+ background-color: #f8f9fa;
196
+ border: 1px solid #dee2e6;
197
+ color: #495057;
198
+ display: inline-flex;
199
+ align-items: center;
200
+ gap: 0.25rem;
201
+ }
202
+
203
+ .paginator-badge-dropdown >>> .btn:hover {
204
+ background-color: #e9ecef;
205
+ border-color: #ced4da;
206
+ }
207
+ </style>
@@ -1,86 +1,103 @@
1
- <template>
2
- <div :class="['table-responsive', tableContainerClass]" v-if="currentDisplayMode == displayModes.MODE_TABLE">
3
- <table :class="['table table-hover table-striped w-100', tableClass]">
4
- <TableHeader />
5
-
6
- <draggable
7
- :list="items"
8
- :group="draggableGroup"
9
- tag="tbody"
10
- :draggable="orderable ? '.item' : '.none'"
11
- @start="drag = true"
12
- @end="drag = false"
13
- @sort="onSort()"
14
- @add="onDraggableAdded($event)"
15
- @change="onDraggableChange($event)"
16
- :options="draggableOptions"
17
- >
18
- <TableRow
19
- v-for="(item, index) in itemsList"
20
- v-bind:key="index"
21
- :item="item"
22
- :index="index"
23
- :grouped="grouped"
24
- >
25
- <template v-for="(slot, name) in $scopedSlots" v-slot:[name]="slotProps">
26
- <slot :name="name" v-bind="slotProps" />
27
- </template>
28
- </TableRow>
29
- </draggable>
30
- </table>
31
-
32
- <p v-if="!loading && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
33
- {{ messageEmptyResults }}
34
- </p>
35
- </div>
36
- </template>
37
-
38
- <script>
39
- import draggable from "vuedraggable";
40
- import TableHeader from './table/TableHeader.vue';
41
- import TableRow from './table/TableRow.vue';
42
-
43
- export default {
44
- name: 'CrudTable',
45
- components: {
46
- draggable,
47
- TableHeader,
48
- TableRow
49
- },
50
- inject: [
51
- 'displayMode',
52
- 'displayModes',
53
- 'tableContainerClass',
54
- 'tableClass',
55
- 'items',
56
- 'draggableGroup',
57
- 'orderable',
58
- 'draggableOptions',
59
- 'itemsList',
60
- 'grouped',
61
- 'loading',
62
- 'infiniteScroll',
63
- 'messageEmptyResults',
64
- 'onSort',
65
- 'onDraggableAdded',
66
- 'onDraggableChange'
67
- ],
68
- data() {
69
- return {
70
- drag: false
71
- };
72
- },
73
- computed: {
74
- currentDisplayMode() {
75
- if (!this.displayMode) return 1;
76
- if (this.displayMode.value !== undefined) {
77
- return this.displayMode.value;
78
- }
79
- if (typeof this.displayMode === 'function') {
80
- return this.displayMode();
81
- }
82
- return this.displayMode;
83
- }
84
- }
85
- };
86
- </script>
1
+ <template>
2
+ <div :class="['table-responsive', tableContainerClass]" v-if="currentDisplayMode == displayModes.MODE_TABLE">
3
+ <!-- Spinner durante la carga inicial -->
4
+ <div v-if="loadingValue || !firstLoadValue" class="text-center p-5">
5
+ <b-spinner variant="primary" label="Cargando..."></b-spinner>
6
+ <p class="mt-2">{{ messageLoading }}</p>
7
+ </div>
8
+
9
+ <!-- Tabla con datos -->
10
+ <template v-else>
11
+ <table :class="['table table-hover table-striped w-100', tableClass]">
12
+ <TableHeader />
13
+
14
+ <draggable
15
+ :list="items"
16
+ :group="draggableGroup"
17
+ tag="tbody"
18
+ :draggable="orderable ? '.item' : '.none'"
19
+ @start="drag = true"
20
+ @end="drag = false"
21
+ @sort="onSort()"
22
+ @add="onDraggableAdded($event)"
23
+ @change="onDraggableChange($event)"
24
+ :options="draggableOptions"
25
+ >
26
+ <TableRow
27
+ v-for="(item, index) in itemsList"
28
+ v-bind:key="index"
29
+ :item="item"
30
+ :index="index"
31
+ :grouped="grouped"
32
+ >
33
+ <template v-for="(slot, name) in $scopedSlots" v-slot:[name]="slotProps">
34
+ <slot :name="name" v-bind="slotProps" />
35
+ </template>
36
+ </TableRow>
37
+ </draggable>
38
+ </table>
39
+
40
+ <p v-if="firstLoadValue && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
41
+ {{ messageEmptyResults }}
42
+ </p>
43
+ </template>
44
+ </div>
45
+ </template>
46
+
47
+ <script>
48
+ import draggable from "vuedraggable";
49
+ import TableHeader from './table/TableHeader.vue';
50
+ import TableRow from './table/TableRow.vue';
51
+
52
+ export default {
53
+ name: 'CrudTable',
54
+ components: {
55
+ draggable,
56
+ TableHeader,
57
+ TableRow
58
+ },
59
+ inject: [
60
+ 'displayMode',
61
+ 'displayModes',
62
+ 'tableContainerClass',
63
+ 'tableClass',
64
+ 'items',
65
+ 'draggableGroup',
66
+ 'orderable',
67
+ 'draggableOptions',
68
+ 'itemsList',
69
+ 'grouped',
70
+ 'loading',
71
+ 'firstLoad',
72
+ 'infiniteScroll',
73
+ 'messageEmptyResults',
74
+ 'messageLoading',
75
+ 'onSort',
76
+ 'onDraggableAdded',
77
+ 'onDraggableChange'
78
+ ],
79
+ data() {
80
+ return {
81
+ drag: false
82
+ };
83
+ },
84
+ computed: {
85
+ currentDisplayMode() {
86
+ if (!this.displayMode) return 1;
87
+ if (this.displayMode.value !== undefined) {
88
+ return this.displayMode.value;
89
+ }
90
+ if (typeof this.displayMode === 'function') {
91
+ return this.displayMode();
92
+ }
93
+ return this.displayMode;
94
+ },
95
+ loadingValue() {
96
+ return this.loading && this.loading.value !== undefined ? this.loading.value : this.loading;
97
+ },
98
+ firstLoadValue() {
99
+ return this.firstLoad && this.firstLoad.value !== undefined ? this.firstLoad.value : this.firstLoad;
100
+ }
101
+ }
102
+ };
103
+ </script>