@drax/crud-vue 2.11.0 → 3.1.0
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/package.json +6 -6
- package/src/EntityCrud.ts +4 -0
- package/src/components/CrudFiltersDynamic.vue +34 -10
- package/src/components/CrudFormField.vue +6 -1
- package/src/components/CrudList.vue +6 -1
- package/src/components/CrudListGallery.vue +38 -26
- package/src/components/CrudListTable.vue +7 -2
- package/src/components/buttons/CrudFilterButton.vue +42 -0
- package/src/composables/UseCrud.ts +6 -1
- package/src/index.ts +4 -0
- package/src/stores/UseCrudStore.ts +14 -2
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "
|
|
6
|
+
"version": "3.1.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./src/index.ts",
|
|
9
9
|
"module": "./src/index.ts",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"format": "prettier --write src/"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@drax/common-front": "^
|
|
28
|
-
"@drax/crud-front": "^
|
|
29
|
-
"@drax/crud-share": "^
|
|
30
|
-
"@drax/media-vue": "^
|
|
27
|
+
"@drax/common-front": "^3.0.0",
|
|
28
|
+
"@drax/crud-front": "^3.0.0",
|
|
29
|
+
"@drax/crud-share": "^3.1.0",
|
|
30
|
+
"@drax/media-vue": "^3.1.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"pinia": "^3.0.4",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"vue-tsc": "^3.2.4",
|
|
51
51
|
"vuetify": "^3.11.8"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "262ea8f861c84ca1ad4d555545c5a94b95dbf25e"
|
|
54
54
|
}
|
package/src/EntityCrud.ts
CHANGED
|
@@ -7,9 +7,9 @@ import {useAuth} from "@drax/identity-vue";
|
|
|
7
7
|
import {useFilterIcon} from "../composables/UseFilterIcon";
|
|
8
8
|
import {useCrudStore} from "../stores/UseCrudStore";
|
|
9
9
|
import {useEntityStore} from "../stores/UseEntityStore";
|
|
10
|
-
import {useDynamicFilters} from "../composables/UseDynamicFilters
|
|
10
|
+
import {useDynamicFilters} from "../composables/UseDynamicFilters";
|
|
11
11
|
|
|
12
|
-
const {t
|
|
12
|
+
const {t} = useI18n()
|
|
13
13
|
const valueModel = defineModel({type: [Object]})
|
|
14
14
|
const {hasPermission} = useAuth()
|
|
15
15
|
const {filterIcon} = useFilterIcon()
|
|
@@ -65,6 +65,30 @@ function onUpdateValue() {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
function numericIndex(index: string | number) {
|
|
69
|
+
return typeof index === 'number' ? index : Number(index)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function getDynamicFilter(index: string | number) {
|
|
73
|
+
return dynamicFilter.value(numericIndex(index))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function updateDynamicField(index: string | number, resetOperator = false) {
|
|
77
|
+
onUpdateField(numericIndex(index), resetOperator)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function getDynamicOperations(index: string | number) {
|
|
81
|
+
return getOperations.value(numericIndex(index))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function dynamicValueRequired(index: string | number) {
|
|
85
|
+
return isValueRequired.value(numericIndex(index))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function deleteFilter(index: string | number) {
|
|
89
|
+
removeFilter(numericIndex(index))
|
|
90
|
+
}
|
|
91
|
+
|
|
68
92
|
|
|
69
93
|
|
|
70
94
|
const emit = defineEmits(['applyFilter', 'clearFilter'])
|
|
@@ -81,31 +105,31 @@ const emit = defineEmits(['applyFilter', 'clearFilter'])
|
|
|
81
105
|
<v-col cols="12" sm="4">
|
|
82
106
|
<v-select
|
|
83
107
|
:items="selectableFields"
|
|
84
|
-
v-model="
|
|
108
|
+
v-model="getDynamicFilter(index)!.name"
|
|
85
109
|
:label="t('crud.field')"
|
|
86
110
|
density="compact"
|
|
87
111
|
variant="outlined"
|
|
88
112
|
hide-details
|
|
89
|
-
@update:modelValue="(
|
|
113
|
+
@update:modelValue="(_v:string) => updateDynamicField(index, true)"
|
|
90
114
|
/>
|
|
91
115
|
</v-col>
|
|
92
116
|
<v-col cols="12" sm="3">
|
|
93
117
|
<v-select
|
|
94
|
-
:items="
|
|
95
|
-
v-model="
|
|
118
|
+
:items="getDynamicOperations(index)"
|
|
119
|
+
v-model="getDynamicFilter(index)!.operator"
|
|
96
120
|
:label="t('crud.operator')"
|
|
97
121
|
density="compact"
|
|
98
122
|
variant="outlined"
|
|
99
123
|
hide-details
|
|
100
|
-
@update:modelValue="(
|
|
124
|
+
@update:modelValue="(_v:string) => updateDynamicField(index)"
|
|
101
125
|
/>
|
|
102
126
|
</v-col>
|
|
103
127
|
<v-col cols="10" sm="4">
|
|
104
128
|
<crud-form-field
|
|
105
|
-
v-if="
|
|
129
|
+
v-if="dynamicValueRequired(index)"
|
|
106
130
|
:field="filter"
|
|
107
131
|
:entity="entity"
|
|
108
|
-
v-model="
|
|
132
|
+
v-model="getDynamicFilter(index)!.value"
|
|
109
133
|
:clearable="true"
|
|
110
134
|
density="compact"
|
|
111
135
|
variant="outlined"
|
|
@@ -115,7 +139,7 @@ const emit = defineEmits(['applyFilter', 'clearFilter'])
|
|
|
115
139
|
/>
|
|
116
140
|
</v-col>
|
|
117
141
|
<v-col cols="2" sm="1">
|
|
118
|
-
<v-btn @click="
|
|
142
|
+
<v-btn @click="deleteFilter(index)"
|
|
119
143
|
icon="mdi-delete"
|
|
120
144
|
class="mr-1"
|
|
121
145
|
variant="text"
|
|
@@ -9,9 +9,14 @@ import {useI18n} from "vue-i18n";
|
|
|
9
9
|
import {useCrudStore} from "../stores/UseCrudStore";
|
|
10
10
|
import {VDateInput} from 'vuetify/labs/VDateInput'
|
|
11
11
|
import type {IEntityCrud, IEntityCrudField, IEntityCrudFilter} from "@drax/crud-share";
|
|
12
|
-
import {MediaField, MediaFullField} from "@drax/media-vue";
|
|
13
12
|
import {useAuth} from "@drax/identity-vue";
|
|
14
13
|
|
|
14
|
+
//TODO: Ver si esto no puede traer problemas...
|
|
15
|
+
import MediaField from "@drax/media-vue/src/components/MediaField.vue";
|
|
16
|
+
import MediaFullField from "@drax/media-vue/src/components/MediaFullField.vue";
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
15
20
|
const {t, te} = useI18n()
|
|
16
21
|
|
|
17
22
|
const {hasPermission} = useAuth()
|
|
@@ -11,6 +11,7 @@ import CrudDeleteButton from "./buttons/CrudDeleteButton.vue";
|
|
|
11
11
|
import CrudViewButton from "./buttons/CrudViewButton.vue";
|
|
12
12
|
import CrudGroupByButton from "./buttons/CrudGroupByButton.vue";
|
|
13
13
|
import CrudColumnsButton from "./buttons/CrudColumnsButton.vue";
|
|
14
|
+
import CrudFilterButton from "./buttons/CrudFilterButton.vue";
|
|
14
15
|
import CrudExportList from "./CrudExportList.vue";
|
|
15
16
|
import type {IEntityCrud} from "@drax/crud-share";
|
|
16
17
|
import {useI18n} from "vue-i18n";
|
|
@@ -19,6 +20,7 @@ import { useCrudColumns } from "../composables/UseCrudColumns";
|
|
|
19
20
|
import CrudFiltersDynamic from "./CrudFiltersDynamic.vue";
|
|
20
21
|
import CrudFiltersAction from "./CrudFiltersAction.vue";
|
|
21
22
|
|
|
23
|
+
|
|
22
24
|
const {t, te} = useI18n()
|
|
23
25
|
const {hasPermission} = useAuth()
|
|
24
26
|
|
|
@@ -90,7 +92,6 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
|
|
|
90
92
|
<v-spacer></v-spacer>
|
|
91
93
|
|
|
92
94
|
<slot name="toolbar">
|
|
93
|
-
|
|
94
95
|
</slot>
|
|
95
96
|
|
|
96
97
|
<crud-import-button
|
|
@@ -108,6 +109,10 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
|
|
|
108
109
|
:entity="entity"
|
|
109
110
|
/>
|
|
110
111
|
|
|
112
|
+
|
|
113
|
+
<crud-filter-button
|
|
114
|
+
:entity="entity" />
|
|
115
|
+
|
|
111
116
|
<crud-columns-button
|
|
112
117
|
v-if="entity.isColumnSelectable"
|
|
113
118
|
:entity="entity"
|
|
@@ -19,6 +19,7 @@ import CrudFilters from "./CrudFilters.vue";
|
|
|
19
19
|
import {useCrudColumns} from "../composables/UseCrudColumns";
|
|
20
20
|
import CrudFiltersDynamic from "./CrudFiltersDynamic.vue";
|
|
21
21
|
import CrudFiltersAction from "./CrudFiltersAction.vue";
|
|
22
|
+
import CrudFilterButton from "./buttons/CrudFilterButton.vue";
|
|
22
23
|
|
|
23
24
|
const {t, te} = useI18n()
|
|
24
25
|
const {hasPermission} = useAuth()
|
|
@@ -29,7 +30,8 @@ const {entity} = defineProps({
|
|
|
29
30
|
|
|
30
31
|
const {
|
|
31
32
|
loading, itemsPerPage, page, search, totalItems, items,
|
|
32
|
-
doPaginate, filters, applyFilters, clearFilters, paginationError
|
|
33
|
+
doPaginate, filters, applyFilters, clearFilters, paginationError,
|
|
34
|
+
isDynamicFiltersEnable
|
|
33
35
|
} = useCrud(entity)
|
|
34
36
|
|
|
35
37
|
// Usar el composable de columnas
|
|
@@ -51,40 +53,50 @@ onMounted(() => {
|
|
|
51
53
|
<template>
|
|
52
54
|
<div v-if="hasPermission(entity.permissions.view)" class="d-flex flex-column h-100 pb-4">
|
|
53
55
|
<!-- Toolbar -->
|
|
54
|
-
<v-toolbar :class="entity.toolbarClass" :density="entity.toolbarDensity">
|
|
56
|
+
<v-toolbar :class="entity.toolbarClass" :density="entity.toolbarDensity" extended>
|
|
55
57
|
<v-toolbar-title>
|
|
56
58
|
{{ te(`${entity.name.toLowerCase()}.crud`) ? t(`${entity.name.toLowerCase()}.crud`) : entity.name }}
|
|
57
59
|
</v-toolbar-title>
|
|
58
60
|
<v-spacer></v-spacer>
|
|
61
|
+
<template v-slot:extension>
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
<v-row justify="end" class="px-2 border-t-sm" >
|
|
64
|
+
<slot name="toolbar">
|
|
65
|
+
</slot>
|
|
62
66
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
<crud-import-button
|
|
68
|
+
:entity="entity"
|
|
69
|
+
@import="(v:any) => $emit('import', v)"
|
|
70
|
+
/>
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
<crud-export-button
|
|
73
|
+
:entity="entity"
|
|
74
|
+
@export="(v:any) => $emit('export',v)"
|
|
75
|
+
/>
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
<crud-group-by-button
|
|
78
|
+
v-if="entity.isGroupable"
|
|
79
|
+
:entity="entity"
|
|
80
|
+
/>
|
|
81
|
+
|
|
82
|
+
<crud-filter-button
|
|
83
|
+
:entity="entity" />
|
|
84
|
+
|
|
85
|
+
<crud-columns-button
|
|
86
|
+
v-if="entity.isColumnSelectable"
|
|
87
|
+
:entity="entity"
|
|
88
|
+
/>
|
|
89
|
+
|
|
90
|
+
<crud-create-button
|
|
91
|
+
v-if="entity.isCreatable"
|
|
92
|
+
:entity="entity"
|
|
93
|
+
@click="$emit('create')"
|
|
94
|
+
/>
|
|
95
|
+
</v-row>
|
|
96
|
+
|
|
97
|
+
</template>
|
|
77
98
|
|
|
78
|
-
<crud-columns-button
|
|
79
|
-
v-if="entity.isColumnSelectable"
|
|
80
|
-
:entity="entity"
|
|
81
|
-
/>
|
|
82
99
|
|
|
83
|
-
<crud-create-button
|
|
84
|
-
v-if="entity.isCreatable"
|
|
85
|
-
:entity="entity"
|
|
86
|
-
@click="$emit('create')"
|
|
87
|
-
/>
|
|
88
100
|
</v-toolbar>
|
|
89
101
|
|
|
90
102
|
<crud-export-list
|
|
@@ -124,7 +136,7 @@ onMounted(() => {
|
|
|
124
136
|
</crud-filters>
|
|
125
137
|
|
|
126
138
|
<crud-filters-dynamic
|
|
127
|
-
v-if="
|
|
139
|
+
v-if="isDynamicFiltersEnable"
|
|
128
140
|
:entity="entity"
|
|
129
141
|
v-model="filters"
|
|
130
142
|
:auto-filter="!entity.filterButtons"
|
|
@@ -18,6 +18,7 @@ import CrudFilters from "./CrudFilters.vue";
|
|
|
18
18
|
import { useCrudColumns } from "../composables/UseCrudColumns";
|
|
19
19
|
import CrudFiltersDynamic from "./CrudFiltersDynamic.vue";
|
|
20
20
|
import CrudFiltersAction from "./CrudFiltersAction.vue";
|
|
21
|
+
import CrudFilterButton from "./buttons/CrudFilterButton.vue";
|
|
21
22
|
|
|
22
23
|
const {t, te} = useI18n()
|
|
23
24
|
const {hasPermission} = useAuth()
|
|
@@ -28,7 +29,8 @@ const {entity} = defineProps({
|
|
|
28
29
|
|
|
29
30
|
const {
|
|
30
31
|
loading, itemsPerPage, page, sortBy, search, totalItems, items,
|
|
31
|
-
doPaginate, filters, applyFilters, clearFilters, paginationError
|
|
32
|
+
doPaginate, filters, applyFilters, clearFilters, paginationError,
|
|
33
|
+
isDynamicFiltersEnable
|
|
32
34
|
} = useCrud(entity)
|
|
33
35
|
|
|
34
36
|
// Usar el composable de columnas
|
|
@@ -108,6 +110,9 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
|
|
|
108
110
|
:entity="entity"
|
|
109
111
|
/>
|
|
110
112
|
|
|
113
|
+
<crud-filter-button
|
|
114
|
+
:entity="entity" />
|
|
115
|
+
|
|
111
116
|
<crud-columns-button
|
|
112
117
|
v-if="entity.isColumnSelectable"
|
|
113
118
|
:entity="entity"
|
|
@@ -158,7 +163,7 @@ defineEmits(['import', 'export', 'create', 'update', 'delete', 'view', 'edit'])
|
|
|
158
163
|
</crud-filters>
|
|
159
164
|
|
|
160
165
|
<crud-filters-dynamic
|
|
161
|
-
v-if="
|
|
166
|
+
v-if="isDynamicFiltersEnable"
|
|
162
167
|
:entity="entity"
|
|
163
168
|
v-model="filters"
|
|
164
169
|
:auto-filter="!entity.filterButtons"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {useI18n} from "vue-i18n";
|
|
3
|
+
import {computed} from "vue";
|
|
4
|
+
import type {PropType} from "vue";
|
|
5
|
+
import type {IEntityCrud} from "@drax/crud-share";
|
|
6
|
+
import {useCrudStore} from "../../stores/UseCrudStore";
|
|
7
|
+
|
|
8
|
+
const {entity} = defineProps({
|
|
9
|
+
entity: {type: Object as PropType<IEntityCrud>, required: true},
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const store = useCrudStore(entity?.name)
|
|
13
|
+
|
|
14
|
+
let dynamicFiltersEnable = computed({
|
|
15
|
+
get: () => store.dynamicFiltersEnable,
|
|
16
|
+
set: (value: boolean) => store.setDynamicFiltersEnable(value)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const {t} = useI18n()
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<div v-if="entity.isFilterable">
|
|
24
|
+
<v-tooltip location="top">
|
|
25
|
+
<template v-slot:activator="{ props }">
|
|
26
|
+
<v-btn
|
|
27
|
+
v-bind="{ ...$attrs, ...props }"
|
|
28
|
+
:icon="dynamicFiltersEnable ? 'mdi-filter-off' : 'mdi-filter' "
|
|
29
|
+
class="mr-1"
|
|
30
|
+
variant="text"
|
|
31
|
+
@click="dynamicFiltersEnable = !dynamicFiltersEnable"
|
|
32
|
+
>
|
|
33
|
+
</v-btn>
|
|
34
|
+
</template>
|
|
35
|
+
{{ t('action.filters') }}
|
|
36
|
+
</v-tooltip>
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<style scoped>
|
|
41
|
+
|
|
42
|
+
</style>
|
|
@@ -19,6 +19,10 @@ export function useCrud(entity: IEntityCrud) {
|
|
|
19
19
|
|
|
20
20
|
const {t: $t, te: $te} = useI18n()
|
|
21
21
|
|
|
22
|
+
const isDynamicFiltersEnable = computed(() => {
|
|
23
|
+
return entity.dynamicFiltersEnable && store.dynamicFiltersEnable
|
|
24
|
+
})
|
|
25
|
+
|
|
22
26
|
const exportError = computed({
|
|
23
27
|
get() {
|
|
24
28
|
return store.exportError
|
|
@@ -477,7 +481,8 @@ export function useCrud(entity: IEntityCrud) {
|
|
|
477
481
|
loading, itemsPerPage, page, sortBy, search, totalItems, items,
|
|
478
482
|
prepareFilters, filters, clearFilters, applyFilters,
|
|
479
483
|
exportFiles, exportLoading, exportListVisible, exportError,
|
|
480
|
-
cloneItem, cast, prepareEdit
|
|
484
|
+
cloneItem, cast, prepareEdit,
|
|
485
|
+
isDynamicFiltersEnable
|
|
481
486
|
}
|
|
482
487
|
|
|
483
488
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,8 @@ import CrudForm from "./components/CrudForm.vue";
|
|
|
4
4
|
import CrudFormField from "./components/CrudFormField.vue";
|
|
5
5
|
import CrudFormList from "./components/CrudFormList.vue";
|
|
6
6
|
import CrudList from "./components/CrudList.vue";
|
|
7
|
+
import CrudListTable from "./components/CrudListTable.vue";
|
|
8
|
+
import CrudListGallery from "./components/CrudListGallery.vue";
|
|
7
9
|
import CrudFilters from "./components/CrudFilters.vue";
|
|
8
10
|
import CrudNotify from "./components/CrudNotify.vue";
|
|
9
11
|
import CrudSearch from "./components/CrudSearch.vue";
|
|
@@ -25,6 +27,8 @@ export {
|
|
|
25
27
|
CrudFormField,
|
|
26
28
|
CrudFormList,
|
|
27
29
|
CrudList,
|
|
30
|
+
CrudListTable,
|
|
31
|
+
CrudListGallery,
|
|
28
32
|
CrudNotify,
|
|
29
33
|
CrudSearch,
|
|
30
34
|
CrudAutocomplete,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {defineStore} from "pinia";
|
|
2
|
-
import type {IEntityCrudOperation, IDraxFieldFilter} from "@drax/crud-share";
|
|
2
|
+
import type {IEntityCrudOperation, IDraxFieldFilter, IEntityCrudFilter} from "@drax/crud-share";
|
|
3
3
|
|
|
4
4
|
export const useCrudStore = (id: string = 'entity') => defineStore('CrudStore'+id, {
|
|
5
5
|
state: () => (
|
|
@@ -13,7 +13,16 @@ export const useCrudStore = (id: string = 'entity') => defineStore('CrudStore'+i
|
|
|
13
13
|
error: '' as string,
|
|
14
14
|
paginationError: '' as string,
|
|
15
15
|
filters: [] as IDraxFieldFilter[],
|
|
16
|
-
dynamicFilters: [
|
|
16
|
+
dynamicFilters: [{
|
|
17
|
+
default: undefined,
|
|
18
|
+
label: "",
|
|
19
|
+
name: "",
|
|
20
|
+
operator: "eq",
|
|
21
|
+
type: "string",
|
|
22
|
+
permission: "",
|
|
23
|
+
value: ""
|
|
24
|
+
}] as IEntityCrudFilter[],
|
|
25
|
+
dynamicFiltersEnable: false as boolean,
|
|
17
26
|
items: [] as any[],
|
|
18
27
|
totalItems: 0 as number,
|
|
19
28
|
itemsPerPage: 10 as number,
|
|
@@ -150,6 +159,9 @@ export const useCrudStore = (id: string = 'entity') => defineStore('CrudStore'+i
|
|
|
150
159
|
this.dynamicFilters[index].value = value
|
|
151
160
|
}
|
|
152
161
|
},
|
|
162
|
+
setDynamicFiltersEnable(enable: boolean) {
|
|
163
|
+
this.dynamicFiltersEnable = enable
|
|
164
|
+
},
|
|
153
165
|
setVisibleColumns(columns: string[]) {
|
|
154
166
|
this.visibleColumns = columns
|
|
155
167
|
},
|