vue-laravel-crud 2.0.4 → 2.0.6
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/dist/vue-laravel-crud.esm.js +1359 -228
- package/dist/vue-laravel-crud.min.js +3 -3
- package/dist/vue-laravel-crud.ssr.js +1378 -241
- package/package.json +2 -1
- package/src/ItemCard.vue +68 -5
- package/src/components/CrudCards.vue +24 -4
- package/src/components/CrudCustom.vue +14 -2
- package/src/components/CrudFilters.vue +247 -32
- package/src/components/CrudHeader.vue +12 -2
- package/src/components/CrudKanban.vue +19 -3
- package/src/components/CrudModals.vue +49 -21
- package/src/components/CrudTable.vue +18 -2
- package/src/components/kanban/KanbanBoard.vue +9 -1
- package/src/components/kanban/KanbanCard.vue +68 -5
- package/src/components/kanban/KanbanColumn.vue +11 -3
- package/src/components/table/TableCell.vue +95 -24
- package/src/components/table/TableHeader.vue +46 -22
- package/src/components/table/TableRow.vue +5 -1
- package/src/vue-laravel-crud.vue +27 -4
|
@@ -5,22 +5,26 @@
|
|
|
5
5
|
<b-overlay :show="loading" rounded="sm">
|
|
6
6
|
<template v-if="validate">
|
|
7
7
|
<form @submit="saveItem">
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
<b-form-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
<template v-if="reactiveItem">
|
|
9
|
+
<slot name="form" v-bind:item="reactiveItem">
|
|
10
|
+
<b-form-group label="Nombre:" description="Nombre ">
|
|
11
|
+
<b-form-input v-model="reactiveItem.title" type="text" required placeholder="Nombre"></b-form-input>
|
|
12
|
+
</b-form-group>
|
|
13
|
+
</slot>
|
|
14
|
+
</template>
|
|
13
15
|
<b-button block type="submit" variant="success" :disabled="loading">
|
|
14
16
|
<b-spinner small v-if="loading"></b-spinner>{{ messageSave }}
|
|
15
17
|
</b-button>
|
|
16
18
|
</form>
|
|
17
19
|
</template>
|
|
18
20
|
<template v-if="!validate">
|
|
19
|
-
<
|
|
20
|
-
<
|
|
21
|
-
<b-form-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
<template v-if="reactiveItem">
|
|
22
|
+
<slot name="form" v-bind:item="reactiveItem">
|
|
23
|
+
<b-form-group :label="key" v-for="(value, key) in reactiveItem" :key="key">
|
|
24
|
+
<b-form-input v-model="reactiveItem[key]" type="text" required></b-form-input>
|
|
25
|
+
</b-form-group>
|
|
26
|
+
</slot>
|
|
27
|
+
</template>
|
|
24
28
|
<b-button block type="submit" variant="success" :disabled="loading" @click="saveItem()">
|
|
25
29
|
<b-spinner small v-if="loading"></b-spinner>{{ messageSave }}
|
|
26
30
|
</b-button>
|
|
@@ -30,16 +34,18 @@
|
|
|
30
34
|
|
|
31
35
|
<!-- Modal de visualización -->
|
|
32
36
|
<b-modal :id="'modal-show-item-' + modelName" hide-footer size="xl" :title="title" no-close-on-backdrop>
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
<b-list-group
|
|
36
|
-
<b-
|
|
37
|
-
<b-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
<template v-if="reactiveItem">
|
|
38
|
+
<slot name="show" v-bind:item="reactiveItem">
|
|
39
|
+
<b-list-group>
|
|
40
|
+
<b-list-group-item v-for="(value, key) in reactiveItem" :key="key">
|
|
41
|
+
<b-row class="w-100">
|
|
42
|
+
<b-col cols="4" class="font-weight-bold">{{ key }}</b-col>
|
|
43
|
+
<b-col cols="8">{{ JSON.stringify(value) }}</b-col>
|
|
44
|
+
</b-row>
|
|
45
|
+
</b-list-group-item>
|
|
46
|
+
</b-list-group>
|
|
47
|
+
</slot>
|
|
48
|
+
</template>
|
|
43
49
|
</b-modal>
|
|
44
50
|
|
|
45
51
|
<!-- Modal de importación -->
|
|
@@ -92,6 +98,7 @@ export default {
|
|
|
92
98
|
'loading',
|
|
93
99
|
'validate',
|
|
94
100
|
'item',
|
|
101
|
+
'getItem',
|
|
95
102
|
'messageSave',
|
|
96
103
|
'showImport',
|
|
97
104
|
'showExport',
|
|
@@ -101,6 +108,27 @@ export default {
|
|
|
101
108
|
'saveItem',
|
|
102
109
|
'importItems',
|
|
103
110
|
'exportItems'
|
|
104
|
-
]
|
|
111
|
+
],
|
|
112
|
+
computed: {
|
|
113
|
+
// Computed property para asegurar reactividad del item inyectado
|
|
114
|
+
reactiveItem() {
|
|
115
|
+
// Si hay una función getItem, usarla para obtener el item actual
|
|
116
|
+
if (this.getItem && typeof this.getItem === 'function') {
|
|
117
|
+
return this.getItem();
|
|
118
|
+
}
|
|
119
|
+
// Si no, usar el item inyectado directamente
|
|
120
|
+
return this.item;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
watch: {
|
|
124
|
+
// Watch el item inyectado para forzar actualización
|
|
125
|
+
item: {
|
|
126
|
+
handler() {
|
|
127
|
+
this.$forceUpdate();
|
|
128
|
+
},
|
|
129
|
+
deep: true,
|
|
130
|
+
immediate: true
|
|
131
|
+
}
|
|
132
|
+
}
|
|
105
133
|
};
|
|
106
134
|
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :class="['table-responsive', tableContainerClass]" v-if="
|
|
2
|
+
<div :class="['table-responsive', tableContainerClass]" v-if="currentDisplayMode == displayModes.MODE_TABLE">
|
|
3
3
|
<table :class="['table table-hover table-striped w-100', tableClass]">
|
|
4
4
|
<TableHeader />
|
|
5
5
|
|
|
@@ -21,7 +21,11 @@
|
|
|
21
21
|
:item="item"
|
|
22
22
|
:index="index"
|
|
23
23
|
:grouped="grouped"
|
|
24
|
-
|
|
24
|
+
>
|
|
25
|
+
<template v-for="(slot, name) in $scopedSlots" v-slot:[name]="slotProps">
|
|
26
|
+
<slot :name="name" v-bind="slotProps" />
|
|
27
|
+
</template>
|
|
28
|
+
</TableRow>
|
|
25
29
|
</draggable>
|
|
26
30
|
</table>
|
|
27
31
|
|
|
@@ -65,6 +69,18 @@ export default {
|
|
|
65
69
|
return {
|
|
66
70
|
drag: false
|
|
67
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
|
+
}
|
|
68
84
|
}
|
|
69
85
|
};
|
|
70
86
|
</script>
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
:columns="columns"
|
|
9
9
|
:itemValue="itemValue"
|
|
10
10
|
:getStateValue="getStateValue"
|
|
11
|
+
:getStateOptions="getStateOptions"
|
|
12
|
+
:getStateBadgeVariant="getStateBadgeVariant"
|
|
11
13
|
:getArrayValue="getArrayValue"
|
|
12
14
|
:showItem="showItem"
|
|
13
15
|
:updateItem="updateItem"
|
|
@@ -15,7 +17,11 @@
|
|
|
15
17
|
:cardClass="cardClass"
|
|
16
18
|
:cardHideFooter="cardHideFooter"
|
|
17
19
|
@draggableChange="onDraggableChange"
|
|
18
|
-
|
|
20
|
+
>
|
|
21
|
+
<template v-for="(slot, name) in $scopedSlots" v-slot:[name]="slotProps">
|
|
22
|
+
<slot :name="name" v-bind="slotProps" />
|
|
23
|
+
</template>
|
|
24
|
+
</KanbanColumn>
|
|
19
25
|
</div>
|
|
20
26
|
</div>
|
|
21
27
|
</template>
|
|
@@ -34,6 +40,8 @@ export default {
|
|
|
34
40
|
'columns',
|
|
35
41
|
'itemValue',
|
|
36
42
|
'getStateValue',
|
|
43
|
+
'getStateOptions',
|
|
44
|
+
'getStateBadgeVariant',
|
|
37
45
|
'getArrayValue',
|
|
38
46
|
'showItem',
|
|
39
47
|
'updateItem',
|
|
@@ -22,11 +22,29 @@
|
|
|
22
22
|
{{ itemValue(column, item) }}
|
|
23
23
|
</span>
|
|
24
24
|
<span v-else-if="column.type === 'state'">
|
|
25
|
-
|
|
25
|
+
<template v-if="getStateOptionsForColumn(column, item).length > 0">
|
|
26
|
+
<b-badge
|
|
27
|
+
v-for="(option, optIndex) in getStateOptionsForColumn(column, item)"
|
|
28
|
+
:key="optIndex"
|
|
29
|
+
:variant="getStateBadgeVariant(option)"
|
|
30
|
+
class="mr-1"
|
|
31
|
+
>
|
|
32
|
+
{{ option.text }}
|
|
33
|
+
</b-badge>
|
|
34
|
+
</template>
|
|
35
|
+
<span v-else>
|
|
36
|
+
{{ itemValue(column, item) }}
|
|
37
|
+
</span>
|
|
26
38
|
</span>
|
|
27
39
|
<span v-else-if="column.type === 'array'">
|
|
28
40
|
{{ getArrayValue(itemValue(column, item), column.displayProp, column.options) }}
|
|
29
41
|
</span>
|
|
42
|
+
<span v-else-if="column.type === 'money' || column.type === 'price'">
|
|
43
|
+
{{ formatMoney(itemValue(column, item), column) }}
|
|
44
|
+
</span>
|
|
45
|
+
<span v-else-if="column.type === 'number' && (column.thousandsSeparator || column.decimalSeparator || column.decimals !== undefined)">
|
|
46
|
+
{{ formatNumber(itemValue(column, item), column) }}
|
|
47
|
+
</span>
|
|
30
48
|
<span v-else>
|
|
31
49
|
{{ itemValue(column, item) }}
|
|
32
50
|
</span>
|
|
@@ -38,11 +56,14 @@
|
|
|
38
56
|
|
|
39
57
|
<template v-slot:footer>
|
|
40
58
|
<b-button-group size="sm">
|
|
41
|
-
<slot name="
|
|
59
|
+
<slot name="rowActions" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
|
|
42
60
|
v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
61
|
+
<slot name="rowAction" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
|
|
62
|
+
v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
|
|
63
|
+
<b-button variant="primary" @click="showItem(item.id, index)"><b-icon-eye></b-icon-eye></b-button>
|
|
64
|
+
<b-button variant="secondary" @click="updateItem(item.id, index)"><b-icon-pencil></b-icon-pencil></b-button>
|
|
65
|
+
<b-button variant="danger" @click="removeItem(item.id, index)"><b-icon-trash></b-icon-trash></b-button>
|
|
66
|
+
</slot>
|
|
46
67
|
</slot>
|
|
47
68
|
</b-button-group>
|
|
48
69
|
</template>
|
|
@@ -61,10 +82,52 @@ export default {
|
|
|
61
82
|
cardHideFooter: Boolean,
|
|
62
83
|
itemValue: Function,
|
|
63
84
|
getStateValue: Function,
|
|
85
|
+
getStateOptions: Function,
|
|
86
|
+
getStateBadgeVariant: Function,
|
|
64
87
|
getArrayValue: Function,
|
|
65
88
|
showItem: Function,
|
|
66
89
|
updateItem: Function,
|
|
67
90
|
removeItem: Function,
|
|
91
|
+
},
|
|
92
|
+
methods: {
|
|
93
|
+
getStateOptionsForColumn(column, item) {
|
|
94
|
+
if (column.type === 'state' && column.options) {
|
|
95
|
+
return this.getStateOptions(this.itemValue(column, item), column.options);
|
|
96
|
+
}
|
|
97
|
+
return [];
|
|
98
|
+
},
|
|
99
|
+
formatNumber(value, column) {
|
|
100
|
+
if (value === null || value === undefined || value === '') {
|
|
101
|
+
return '';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const numValue = parseFloat(value);
|
|
105
|
+
if (isNaN(numValue)) {
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const thousandsSep = column.thousandsSeparator || '.';
|
|
110
|
+
const decimalSep = column.decimalSeparator || ',';
|
|
111
|
+
const decimals = column.decimals !== undefined ? column.decimals : (numValue % 1 === 0 ? 0 : 2);
|
|
112
|
+
|
|
113
|
+
// Formatear número con separadores
|
|
114
|
+
const parts = numValue.toFixed(decimals).split('.');
|
|
115
|
+
const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSep);
|
|
116
|
+
const decimalPart = parts[1] || '';
|
|
117
|
+
|
|
118
|
+
if (decimals > 0 && decimalPart) {
|
|
119
|
+
return `${integerPart}${decimalSep}${decimalPart}`;
|
|
120
|
+
}
|
|
121
|
+
return integerPart;
|
|
122
|
+
},
|
|
123
|
+
formatMoney(value, column) {
|
|
124
|
+
const formatted = this.formatNumber(value, column);
|
|
125
|
+
if (formatted === '') {
|
|
126
|
+
return '';
|
|
127
|
+
}
|
|
128
|
+
const symbol = column.symbol || '$';
|
|
129
|
+
return `${symbol}${formatted}`;
|
|
130
|
+
}
|
|
68
131
|
}
|
|
69
132
|
};
|
|
70
133
|
</script>
|
|
@@ -24,12 +24,18 @@
|
|
|
24
24
|
:cardClass="cardClass"
|
|
25
25
|
:cardHideFooter="cardHideFooter"
|
|
26
26
|
:itemValue="itemValue"
|
|
27
|
-
:getStateValue="getStateValue"
|
|
27
|
+
:getStateValue="getStateValue"
|
|
28
|
+
:getStateOptions="getStateOptions"
|
|
29
|
+
:getStateBadgeVariant="getStateBadgeVariant"
|
|
28
30
|
:getArrayValue="getArrayValue"
|
|
29
31
|
:showItem="showItem"
|
|
30
32
|
:updateItem="updateItem"
|
|
31
|
-
:removeItem="removeItem"
|
|
32
|
-
|
|
33
|
+
:removeItem="removeItem"
|
|
34
|
+
>
|
|
35
|
+
<template v-for="(slot, name) in $scopedSlots" v-slot:[name]="slotProps">
|
|
36
|
+
<slot :name="name" v-bind="slotProps" />
|
|
37
|
+
</template>
|
|
38
|
+
</KanbanCard>
|
|
33
39
|
</slot>
|
|
34
40
|
</div>
|
|
35
41
|
</draggable>
|
|
@@ -53,6 +59,8 @@ export default {
|
|
|
53
59
|
columns: Array,
|
|
54
60
|
itemValue: Function,
|
|
55
61
|
getStateValue: Function,
|
|
62
|
+
getStateOptions: Function,
|
|
63
|
+
getStateBadgeVariant: Function,
|
|
56
64
|
getArrayValue: Function,
|
|
57
65
|
showItem: Function,
|
|
58
66
|
updateItem: Function,
|
|
@@ -30,10 +30,20 @@
|
|
|
30
30
|
<b-form-checkbox v-model="item.selected" @change="onCheckSelect($event, item)">
|
|
31
31
|
</b-form-checkbox>
|
|
32
32
|
</span>
|
|
33
|
-
<span v-else-if="column.type == 'state'
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
<span v-else-if="column.type == 'state'">
|
|
34
|
+
<template v-if="stateOptions.length > 0">
|
|
35
|
+
<b-badge
|
|
36
|
+
v-for="(option, optIndex) in stateOptions"
|
|
37
|
+
:key="optIndex"
|
|
38
|
+
:variant="getStateBadgeVariant(option)"
|
|
39
|
+
class="mr-1"
|
|
40
|
+
>
|
|
41
|
+
{{ option.text }}
|
|
42
|
+
</b-badge>
|
|
43
|
+
</template>
|
|
44
|
+
<span v-else>
|
|
45
|
+
{{ itemValue(column, item) }}
|
|
46
|
+
</span>
|
|
37
47
|
</span>
|
|
38
48
|
<span v-else-if="column.type == 'array' && optionsLoaded">
|
|
39
49
|
{{
|
|
@@ -44,7 +54,14 @@
|
|
|
44
54
|
)
|
|
45
55
|
}}
|
|
46
56
|
</span>
|
|
57
|
+
<span v-else-if="column.type == 'money' || column.type == 'price'">
|
|
58
|
+
{{ formatMoney(itemValue(column, item), column) }}
|
|
59
|
+
</span>
|
|
60
|
+
<span v-else-if="column.type == 'number' && (column.thousandsSeparator || column.decimalSeparator || column.decimals !== undefined)">
|
|
61
|
+
{{ formatNumber(itemValue(column, item), column) }}
|
|
62
|
+
</span>
|
|
47
63
|
<span v-else>
|
|
64
|
+
|
|
48
65
|
{{ itemValue(column, item) }}
|
|
49
66
|
</span>
|
|
50
67
|
</slot>
|
|
@@ -57,33 +74,39 @@
|
|
|
57
74
|
<template #button-content>
|
|
58
75
|
<b-icon-list></b-icon-list>
|
|
59
76
|
</template>
|
|
60
|
-
<slot name="
|
|
77
|
+
<slot name="rowActions" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
|
|
61
78
|
v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
<slot name="rowAction" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
|
|
80
|
+
v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
|
|
81
|
+
<b-dropdown-item @click="showItem(item.id, index)">
|
|
82
|
+
<b-icon-eye></b-icon-eye> Ver
|
|
83
|
+
</b-dropdown-item>
|
|
84
|
+
<b-dropdown-item @click="updateItem(item.id, index)">
|
|
85
|
+
<b-icon-pencil></b-icon-pencil> Editar
|
|
86
|
+
</b-dropdown-item>
|
|
87
|
+
<b-dropdown-item @click="removeItem(item.id, index)" class="text-danger">
|
|
88
|
+
<b-icon-trash></b-icon-trash> Eliminar
|
|
89
|
+
</b-dropdown-item>
|
|
90
|
+
</slot>
|
|
71
91
|
</slot>
|
|
72
92
|
</b-dropdown>
|
|
73
93
|
|
|
74
94
|
<!-- Modo botones normal (comportamiento original) -->
|
|
75
95
|
<b-button-group v-else-if="column.type == 'actions'" class="actions-button-group">
|
|
76
|
-
<slot name="
|
|
96
|
+
<slot name="rowActions" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
|
|
77
97
|
v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
<slot name="rowAction" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
|
|
99
|
+
v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
|
|
100
|
+
<b-button variant="primary" @click="showItem(item.id, index)">
|
|
101
|
+
<b-icon-eye></b-icon-eye>
|
|
102
|
+
</b-button>
|
|
103
|
+
<b-button variant="secondary" @click="updateItem(item.id, index)">
|
|
104
|
+
<b-icon-pencil></b-icon-pencil>
|
|
105
|
+
</b-button>
|
|
106
|
+
<b-button variant="danger" @click="removeItem(item.id, index)">
|
|
107
|
+
<b-icon-trash></b-icon-trash>
|
|
108
|
+
</b-button>
|
|
109
|
+
</slot>
|
|
87
110
|
</slot>
|
|
88
111
|
</b-button-group>
|
|
89
112
|
</td>
|
|
@@ -103,6 +126,8 @@ export default {
|
|
|
103
126
|
inject: [
|
|
104
127
|
'itemValue',
|
|
105
128
|
'getStateValue',
|
|
129
|
+
'getStateOptions',
|
|
130
|
+
'getStateBadgeVariant',
|
|
106
131
|
'getArrayValue',
|
|
107
132
|
'onCheckSelect',
|
|
108
133
|
'showItem',
|
|
@@ -114,6 +139,52 @@ export default {
|
|
|
114
139
|
return {
|
|
115
140
|
moment: moment
|
|
116
141
|
};
|
|
142
|
+
},
|
|
143
|
+
computed: {
|
|
144
|
+
stateOptions() {
|
|
145
|
+
// Permitir usar opciones incluso si optionsLoaded es false, ya que getStateOptions normaliza internamente
|
|
146
|
+
if (this.column.type === 'state' && this.column.options && Array.isArray(this.column.options)) {
|
|
147
|
+
const itemVal = this.itemValue(this.column, this.item);
|
|
148
|
+
const options = this.column.options;
|
|
149
|
+
const result = this.getStateOptions(itemVal, options);
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
methods: {
|
|
156
|
+
formatNumber(value, column) {
|
|
157
|
+
if (value === null || value === undefined || value === '') {
|
|
158
|
+
return '';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const numValue = parseFloat(value);
|
|
162
|
+
if (isNaN(numValue)) {
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const thousandsSep = column.thousandsSeparator || '.';
|
|
167
|
+
const decimalSep = column.decimalSeparator || ',';
|
|
168
|
+
const decimals = column.decimals !== undefined ? column.decimals : (numValue % 1 === 0 ? 0 : 2);
|
|
169
|
+
|
|
170
|
+
// Formatear número con separadores
|
|
171
|
+
const parts = numValue.toFixed(decimals).split('.');
|
|
172
|
+
const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSep);
|
|
173
|
+
const decimalPart = parts[1] || '';
|
|
174
|
+
|
|
175
|
+
if (decimals > 0 && decimalPart) {
|
|
176
|
+
return `${integerPart}${decimalSep}${decimalPart}`;
|
|
177
|
+
}
|
|
178
|
+
return integerPart;
|
|
179
|
+
},
|
|
180
|
+
formatMoney(value, column) {
|
|
181
|
+
const formatted = this.formatNumber(value, column);
|
|
182
|
+
if (formatted === '') {
|
|
183
|
+
return '';
|
|
184
|
+
}
|
|
185
|
+
const symbol = column.symbol || '$';
|
|
186
|
+
return `${symbol}${formatted}`;
|
|
187
|
+
}
|
|
117
188
|
}
|
|
118
189
|
};
|
|
119
190
|
</script>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
v-bind:internalFilterByProp="internalFilterByProp" v-if="enableFilters &&
|
|
13
13
|
filtersVisible &&
|
|
14
14
|
isColumnHasFilter(column) &&
|
|
15
|
-
internalFilterByProp(column.prop)
|
|
15
|
+
(internalFilterByProp(column.prop) || internalFilterByProp(column.prop + '_from'))
|
|
16
16
|
">
|
|
17
17
|
|
|
18
18
|
<div class="form-group">
|
|
@@ -36,33 +36,42 @@
|
|
|
36
36
|
</div>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
-
<
|
|
39
|
+
<div class="row" v-else-if="column.type == 'number' || column.type == 'money' || column.type == 'price'">
|
|
40
|
+
<div class="col-6">
|
|
41
|
+
<input
|
|
42
|
+
type="number"
|
|
43
|
+
class="form-control form-control-md p-2"
|
|
44
|
+
v-model.number="internalFilterByProp(column.prop + '_from').value"
|
|
45
|
+
:step="column.type == 'money' || column.type == 'price' ? '0.01' : '1'"
|
|
46
|
+
@change="onChangeFilter($event)"
|
|
47
|
+
placeholder="Desde" />
|
|
48
|
+
</div>
|
|
49
|
+
<div class="col-6">
|
|
50
|
+
<input
|
|
51
|
+
type="number"
|
|
52
|
+
class="form-control form-control-md p-2"
|
|
53
|
+
v-model.number="internalFilterByProp(column.prop + '_to').value"
|
|
54
|
+
:step="column.type == 'money' || column.type == 'price' ? '0.01' : '1'"
|
|
55
|
+
@change="onChangeFilter($event)"
|
|
56
|
+
placeholder="Hasta" />
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<select v-else-if="column.type == 'state' && column.options && Array.isArray(column.options)" class="form-control form-control-md p-2"
|
|
40
61
|
v-model="internalFilterByProp(column.prop).value" @change="onChangeFilter($event)"
|
|
41
62
|
:placeholder="column.label">
|
|
42
63
|
<option value="">{{ column.label }}</option>
|
|
43
|
-
<option :value="option.
|
|
44
|
-
{{
|
|
45
|
-
option.text
|
|
46
|
-
? option.text
|
|
47
|
-
: option.label
|
|
48
|
-
? option.label
|
|
49
|
-
: ""
|
|
50
|
-
}}
|
|
64
|
+
<option :value="option.value" v-for="(option, indexo) in column.options" :key="indexo">
|
|
65
|
+
{{ option.text }}
|
|
51
66
|
</option>
|
|
52
67
|
</select>
|
|
53
68
|
|
|
54
|
-
<select v-else-if="column.type == 'array' &&
|
|
69
|
+
<select v-else-if="column.type == 'array' && column.options && Array.isArray(column.options)" class="form-control form-control-md p-2"
|
|
55
70
|
v-model="internalFilterByProp(column.prop).value" @change="onChangeFilter($event)"
|
|
56
71
|
:placeholder="column.label">
|
|
57
72
|
<option value="">{{ column.label }}</option>
|
|
58
|
-
<option :value="option.
|
|
59
|
-
{{
|
|
60
|
-
option.text
|
|
61
|
-
? option.text
|
|
62
|
-
: option.label
|
|
63
|
-
? option.label
|
|
64
|
-
: ""
|
|
65
|
-
}}
|
|
73
|
+
<option :value="option.value" v-for="(option, indexo) in column.options" :key="indexo">
|
|
74
|
+
{{ option.text }}
|
|
66
75
|
</option>
|
|
67
76
|
</select>
|
|
68
77
|
|
|
@@ -95,12 +104,17 @@
|
|
|
95
104
|
<span v-else>{{ column.label }}</span>
|
|
96
105
|
|
|
97
106
|
<span
|
|
98
|
-
v-if="isSortableColumn(column)
|
|
99
|
-
class="sort-filter
|
|
107
|
+
v-if="isSortableColumn(column)"
|
|
108
|
+
class="sort-filter ml-1"
|
|
109
|
+
:class="{ 'sort-filter-visible': shouldShowSortIcon(column) }"
|
|
110
|
+
@click="toggleSortFilter(column)">
|
|
100
111
|
<b-icon-sort-up
|
|
101
112
|
v-if="getSortIconDirection(column) === 'up'"></b-icon-sort-up>
|
|
102
113
|
<b-icon-sort-down
|
|
103
|
-
v-if="getSortIconDirection(column) === 'down'"></b-icon-sort-down>
|
|
114
|
+
v-else-if="getSortIconDirection(column) === 'down'"></b-icon-sort-down>
|
|
115
|
+
<b-icon-sort-up
|
|
116
|
+
v-else
|
|
117
|
+
style="visibility: hidden;"></b-icon-sort-up>
|
|
104
118
|
</span>
|
|
105
119
|
</th>
|
|
106
120
|
</slot>
|
|
@@ -163,4 +177,14 @@ export default {
|
|
|
163
177
|
width: 1%;
|
|
164
178
|
white-space: nowrap;
|
|
165
179
|
}
|
|
180
|
+
|
|
181
|
+
.sort-filter {
|
|
182
|
+
cursor: pointer;
|
|
183
|
+
visibility: hidden;
|
|
184
|
+
display: inline-block;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.sort-filter-visible {
|
|
188
|
+
visibility: visible;
|
|
189
|
+
}
|
|
166
190
|
</style>
|
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
:item="item"
|
|
17
17
|
:index="index"
|
|
18
18
|
:columnIndex="indexc"
|
|
19
|
-
|
|
19
|
+
>
|
|
20
|
+
<template v-for="(slot, name) in $scopedSlots" v-slot:[name]="slotProps">
|
|
21
|
+
<slot :name="name" v-bind="slotProps" />
|
|
22
|
+
</template>
|
|
23
|
+
</TableCell>
|
|
20
24
|
</slot>
|
|
21
25
|
</tr>
|
|
22
26
|
</template>
|