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.
- package/README.md +344 -148
- package/dist/vue-laravel-crud.esm.js +472 -145
- package/dist/vue-laravel-crud.min.js +3 -3
- package/dist/vue-laravel-crud.ssr.js +525 -174
- package/package.json +7 -3
- package/src/components/CrudCards.vue +6 -3
- package/src/components/CrudCustom.vue +2 -2
- package/src/components/CrudHeader.vue +15 -2
- package/src/components/CrudKanban.vue +1 -1
- package/src/components/CrudPagination.vue +145 -18
- package/src/components/CrudTable.vue +2 -2
- package/src/components/table/TableCell.vue +52 -2
- package/src/components/table/TableHeader.vue +64 -11
- package/src/components/table/TableRow.vue +5 -1
- package/src/vue-laravel-crud.vue +695 -655
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue-laravel-crud",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "",
|
|
5
6
|
"homepage": "https://github.com/clonixdev/vue-laravel-crud",
|
|
6
7
|
"main": "dist/vue-laravel-crud.ssr.js",
|
|
@@ -16,14 +17,17 @@
|
|
|
16
17
|
"serve": "vue-cli-service serve dev/serve.js",
|
|
17
18
|
"demo": "concurrently \"npm run demo:api\" \"npm run demo:app\"",
|
|
18
19
|
"demo:api": "node dev/api/mockServer.js",
|
|
19
|
-
"demo:app": "vue-cli-service serve dev/demo/
|
|
20
|
+
"demo:app": "vue-cli-service serve dev/demo/main.js",
|
|
20
21
|
"build": "cross-env NODE_ENV=production rollup --config build/rollup.config.js",
|
|
21
22
|
"build:ssr": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format cjs",
|
|
22
23
|
"build:es": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format es",
|
|
23
|
-
"build:unpkg": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format iife"
|
|
24
|
+
"build:unpkg": "cross-env NODE_ENV=production rollup --config build/rollup.config.js --format iife",
|
|
25
|
+
"build:demo": "cross-env NODE_ENV=production vue-cli-service build --mode production dev/demo/main.js",
|
|
26
|
+
"build:gh-pages": "npm run build:demo"
|
|
24
27
|
},
|
|
25
28
|
"dependencies": {
|
|
26
29
|
"axios": "^1.3.5",
|
|
30
|
+
"bootstrap": "^4.6.2",
|
|
27
31
|
"bootstrap-vue": "^2.21.2",
|
|
28
32
|
"moment": "^2.29.1",
|
|
29
33
|
"sass-loader": "^14.1.1",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-
|
|
2
|
+
<div v-if="displayMode == displayModes.MODE_CARDS">
|
|
3
3
|
<draggable
|
|
4
4
|
v-model="items"
|
|
5
5
|
:group="draggableGroup"
|
|
@@ -35,22 +35,25 @@
|
|
|
35
35
|
</masonry>
|
|
36
36
|
</draggable>
|
|
37
37
|
|
|
38
|
-
<p v-if="!loading &&
|
|
38
|
+
<p v-if="!loading && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
|
|
39
39
|
{{ messageEmptyResults }}
|
|
40
40
|
</p>
|
|
41
41
|
</div>
|
|
42
42
|
</template>
|
|
43
43
|
|
|
44
44
|
<script>
|
|
45
|
+
import Vue from 'vue';
|
|
45
46
|
import draggable from "vuedraggable";
|
|
46
47
|
import VueMasonry from 'vue-masonry-css';
|
|
47
48
|
import ItemCard from '../ItemCard.vue';
|
|
48
49
|
|
|
50
|
+
// Registrar el componente masonry usando el Plugin
|
|
51
|
+
Vue.use(VueMasonry);
|
|
52
|
+
|
|
49
53
|
export default {
|
|
50
54
|
name: 'CrudCards',
|
|
51
55
|
components: {
|
|
52
56
|
draggable,
|
|
53
|
-
VueMasonry,
|
|
54
57
|
ItemCard
|
|
55
58
|
},
|
|
56
59
|
inject: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-
|
|
2
|
+
<div v-if="displayMode == displayModes.MODE_CUSTOM">
|
|
3
3
|
<div :class="listContainerClass">
|
|
4
|
-
<p v-if="!loading &&
|
|
4
|
+
<p v-if="!loading && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
|
|
5
5
|
{{ messageEmptyResults }}
|
|
6
6
|
</p>
|
|
7
7
|
<div :class="listItemClass" v-for="(item, index) in itemsList" v-bind:key="index">
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="crud-header" v-if="showHeader">
|
|
3
3
|
<h4 class="crud-title" v-if="showTitle">{{ title }}</h4>
|
|
4
4
|
|
|
5
|
-
<b-sidebar
|
|
5
|
+
<b-sidebar :visible="sidebarVisible" @hidden="closeSidebar" title="Filtrar" right shadow>
|
|
6
6
|
<CrudFilters />
|
|
7
7
|
</b-sidebar>
|
|
8
8
|
|
|
@@ -89,7 +89,20 @@ export default {
|
|
|
89
89
|
'confirmBulkDelete',
|
|
90
90
|
'toggleFilters',
|
|
91
91
|
'refresh'
|
|
92
|
-
]
|
|
92
|
+
],
|
|
93
|
+
computed: {
|
|
94
|
+
sidebarVisible() {
|
|
95
|
+
// Acceder directamente al componente padre para obtener reactividad
|
|
96
|
+
return this.$parent ? this.$parent.filterSidebarOpen : this.filterSidebarOpen;
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
methods: {
|
|
100
|
+
closeSidebar() {
|
|
101
|
+
if (this.filterSidebarOpen) {
|
|
102
|
+
this.toggleFilters();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
93
106
|
};
|
|
94
107
|
</script>
|
|
95
108
|
|
|
@@ -20,19 +20,50 @@
|
|
|
20
20
|
</infinite-loading>
|
|
21
21
|
|
|
22
22
|
<!-- Paginador -->
|
|
23
|
-
<div class="paginator-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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>
|
|
36
67
|
</div>
|
|
37
68
|
</div>
|
|
38
69
|
</template>
|
|
@@ -57,17 +88,113 @@ export default {
|
|
|
57
88
|
'selectedItems',
|
|
58
89
|
'showPaginator',
|
|
59
90
|
'infiniteHandler',
|
|
60
|
-
'onPaginationChange'
|
|
61
|
-
|
|
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
|
+
}
|
|
62
106
|
};
|
|
63
107
|
</script>
|
|
64
108
|
|
|
65
109
|
<style scoped>
|
|
66
|
-
.
|
|
67
|
-
display:
|
|
110
|
+
.paginator-container {
|
|
111
|
+
display: grid;
|
|
112
|
+
grid-template-columns: 1fr auto 1fr;
|
|
68
113
|
align-items: center;
|
|
69
114
|
width: 100%;
|
|
70
|
-
justify-content: center;
|
|
71
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;
|
|
72
199
|
}
|
|
73
200
|
</style>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<TableHeader />
|
|
5
5
|
|
|
6
6
|
<draggable
|
|
7
|
-
|
|
7
|
+
:list="items"
|
|
8
8
|
:group="draggableGroup"
|
|
9
9
|
tag="tbody"
|
|
10
10
|
:draggable="orderable ? '.item' : '.none'"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
</draggable>
|
|
26
26
|
</table>
|
|
27
27
|
|
|
28
|
-
<p v-if="!loading &&
|
|
28
|
+
<p v-if="!loading && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
|
|
29
29
|
{{ messageEmptyResults }}
|
|
30
30
|
</p>
|
|
31
31
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<td :scope="column.prop == 'id' ? 'row' : ''"
|
|
2
|
+
<td :scope="column.prop == 'id' ? 'row' : ''"
|
|
3
|
+
:class="{ 'actions-cell': column.type == 'actions' }">
|
|
3
4
|
<slot :name="'cell-' + column.prop" v-bind:item="item" v-bind:index="index" v-bind:itemindex="index"
|
|
4
5
|
v-bind:columnindex="columnIndex">
|
|
5
6
|
<span v-if="column.type == 'boolean'">
|
|
@@ -25,6 +26,10 @@
|
|
|
25
26
|
<b-form-checkbox v-model="item.selected" @change="onCheckSelect($event, item)">
|
|
26
27
|
</b-form-checkbox>
|
|
27
28
|
</span>
|
|
29
|
+
<span v-else-if="column.type == 'checkbox'">
|
|
30
|
+
<b-form-checkbox v-model="item.selected" @change="onCheckSelect($event, item)">
|
|
31
|
+
</b-form-checkbox>
|
|
32
|
+
</span>
|
|
28
33
|
<span v-else-if="column.type == 'state' && optionsLoaded">
|
|
29
34
|
{{
|
|
30
35
|
getStateValue(itemValue(column, item), column.options)
|
|
@@ -44,7 +49,30 @@
|
|
|
44
49
|
</span>
|
|
45
50
|
</slot>
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
<!-- Modo dropdown cuando useDropdown está activo -->
|
|
53
|
+
<b-dropdown v-if="column.type == 'actions' && column.useDropdown"
|
|
54
|
+
variant="secondary"
|
|
55
|
+
size="sm"
|
|
56
|
+
class="actions-dropdown">
|
|
57
|
+
<template #button-content>
|
|
58
|
+
<b-icon-list></b-icon-list>
|
|
59
|
+
</template>
|
|
60
|
+
<slot name="rowAction" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
|
|
61
|
+
v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
|
|
62
|
+
<b-dropdown-item @click="showItem(item.id, index)">
|
|
63
|
+
<b-icon-eye></b-icon-eye> Ver
|
|
64
|
+
</b-dropdown-item>
|
|
65
|
+
<b-dropdown-item @click="updateItem(item.id, index)">
|
|
66
|
+
<b-icon-pencil></b-icon-pencil> Editar
|
|
67
|
+
</b-dropdown-item>
|
|
68
|
+
<b-dropdown-item @click="removeItem(item.id, index)" class="text-danger">
|
|
69
|
+
<b-icon-trash></b-icon-trash> Eliminar
|
|
70
|
+
</b-dropdown-item>
|
|
71
|
+
</slot>
|
|
72
|
+
</b-dropdown>
|
|
73
|
+
|
|
74
|
+
<!-- Modo botones normal (comportamiento original) -->
|
|
75
|
+
<b-button-group v-else-if="column.type == 'actions'" class="actions-button-group">
|
|
48
76
|
<slot name="rowAction" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
|
|
49
77
|
v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
|
|
50
78
|
<b-button variant="primary" @click="showItem(item.id, index)">
|
|
@@ -89,3 +117,25 @@ export default {
|
|
|
89
117
|
}
|
|
90
118
|
};
|
|
91
119
|
</script>
|
|
120
|
+
|
|
121
|
+
<style scoped>
|
|
122
|
+
/* Fijar ancho de la columna de acciones */
|
|
123
|
+
.actions-cell {
|
|
124
|
+
width: 1%;
|
|
125
|
+
white-space: nowrap;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.actions-button-group {
|
|
129
|
+
display: inline-flex;
|
|
130
|
+
flex-wrap: nowrap;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.actions-dropdown {
|
|
134
|
+
display: inline-block;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Asegurar que los botones no se expandan */
|
|
138
|
+
.actions-button-group .btn {
|
|
139
|
+
flex-shrink: 0;
|
|
140
|
+
}
|
|
141
|
+
</style>
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
<tr>
|
|
4
4
|
<slot name="rowHead">
|
|
5
5
|
<th v-for="(column, indexc) in columns" :key="indexc"
|
|
6
|
-
:style="{ width: column.width ? column.width : 'inherit' }"
|
|
6
|
+
:style="{ width: column.width ? column.width : (column.type == 'actions' ? '1%' : 'inherit') }"
|
|
7
|
+
:class="{ 'actions-header': column.type == 'actions' }"
|
|
8
|
+
scope="col"
|
|
9
|
+
@mouseenter="hoveredColumn = column.prop"
|
|
10
|
+
@mouseleave="hoveredColumn = null">
|
|
7
11
|
<slot :name="'filter-' + column.prop" v-bind:column="column" v-bind:filter="filter"
|
|
8
12
|
v-bind:internalFilterByProp="internalFilterByProp" v-if="enableFilters &&
|
|
9
13
|
filtersVisible &&
|
|
@@ -63,10 +67,13 @@
|
|
|
63
67
|
</select>
|
|
64
68
|
|
|
65
69
|
<b-form-checkbox v-else-if="column.type == 'checkbox'" name="select-all"
|
|
66
|
-
|
|
70
|
+
:checked="isAllSelected"
|
|
71
|
+
@change="toggleAll">
|
|
67
72
|
</b-form-checkbox>
|
|
68
73
|
|
|
69
|
-
<b-form-checkbox v-else-if="column.type == 'select'" name="select-all"
|
|
74
|
+
<b-form-checkbox v-else-if="column.type == 'select'" name="select-all"
|
|
75
|
+
:checked="isAllSelected"
|
|
76
|
+
@change="toggleAll">
|
|
70
77
|
</b-form-checkbox>
|
|
71
78
|
|
|
72
79
|
<input v-else class="form-control form-control-md p-2"
|
|
@@ -76,17 +83,24 @@
|
|
|
76
83
|
</div>
|
|
77
84
|
</slot>
|
|
78
85
|
<span v-else-if="column.type == 'select'">
|
|
79
|
-
<b-form-checkbox name="select-all"
|
|
86
|
+
<b-form-checkbox name="select-all"
|
|
87
|
+
:checked="isAllSelected"
|
|
88
|
+
@change="toggleAll"></b-form-checkbox>
|
|
89
|
+
</span>
|
|
90
|
+
<span v-else-if="column.type == 'checkbox'">
|
|
91
|
+
<b-form-checkbox name="select-all"
|
|
92
|
+
:checked="isAllSelected"
|
|
93
|
+
@change="toggleAll"></b-form-checkbox>
|
|
80
94
|
</span>
|
|
81
95
|
<span v-else>{{ column.label }}</span>
|
|
82
96
|
|
|
83
97
|
<span
|
|
84
|
-
v-if="
|
|
85
|
-
class="sort-filter" @click="toggleSortFilter(column)"
|
|
86
|
-
|
|
87
|
-
v-if="
|
|
98
|
+
v-if="isSortableColumn(column) && shouldShowSortIcon(column)"
|
|
99
|
+
class="sort-filter" @click="toggleSortFilter(column)">
|
|
100
|
+
<b-icon-sort-up
|
|
101
|
+
v-if="getSortIconDirection(column) === 'up'"></b-icon-sort-up>
|
|
88
102
|
<b-icon-sort-down
|
|
89
|
-
v-if="
|
|
103
|
+
v-if="getSortIconDirection(column) === 'down'"></b-icon-sort-down>
|
|
90
104
|
</span>
|
|
91
105
|
</th>
|
|
92
106
|
</slot>
|
|
@@ -107,7 +121,46 @@ export default {
|
|
|
107
121
|
'toggleAll',
|
|
108
122
|
'toggleSortFilter',
|
|
109
123
|
'sortable',
|
|
110
|
-
'optionsLoaded'
|
|
111
|
-
|
|
124
|
+
'optionsLoaded',
|
|
125
|
+
'isAllSelected'
|
|
126
|
+
],
|
|
127
|
+
data() {
|
|
128
|
+
return {
|
|
129
|
+
hoveredColumn: null
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
methods: {
|
|
133
|
+
isSortableColumn(column) {
|
|
134
|
+
return this.sortable &&
|
|
135
|
+
column.type != 'select' &&
|
|
136
|
+
column.type != 'checkbox' &&
|
|
137
|
+
this.internalFilterByProp(column.prop + '_sort');
|
|
138
|
+
},
|
|
139
|
+
shouldShowSortIcon(column) {
|
|
140
|
+
const sortFilter = this.internalFilterByProp(column.prop + '_sort');
|
|
141
|
+
return this.hoveredColumn === column.prop || sortFilter.value;
|
|
142
|
+
},
|
|
143
|
+
getSortIconDirection(column) {
|
|
144
|
+
const sortFilter = this.internalFilterByProp(column.prop + '_sort');
|
|
145
|
+
const sortValue = sortFilter.value;
|
|
146
|
+
|
|
147
|
+
if (sortValue === 'DESC') {
|
|
148
|
+
return 'down';
|
|
149
|
+
} else if (sortValue === 'ASC') {
|
|
150
|
+
return 'up';
|
|
151
|
+
} else if (this.hoveredColumn === column.prop) {
|
|
152
|
+
return 'up';
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
112
157
|
};
|
|
113
158
|
</script>
|
|
159
|
+
|
|
160
|
+
<style scoped>
|
|
161
|
+
/* Fijar ancho de la columna de acciones en el header */
|
|
162
|
+
.actions-header {
|
|
163
|
+
width: 1%;
|
|
164
|
+
white-space: nowrap;
|
|
165
|
+
}
|
|
166
|
+
</style>
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<tr
|
|
2
|
+
<tr
|
|
3
|
+
@mouseover="onRowHover(item, index)"
|
|
4
|
+
@click="onRowClick(item, index)"
|
|
5
|
+
:class="['item', { 'selected': item.selected }]"
|
|
6
|
+
>
|
|
3
7
|
<th :colspan="columns.length" v-if="grouped && item.crudgroup">
|
|
4
8
|
<span>{{ item.crudgrouplabel }}</span>
|
|
5
9
|
</th>
|