adminforth 1.2.96 → 1.2.98

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.
Files changed (101) hide show
  1. package/dist/index.js +2 -1
  2. package/dist/modules/restApi.js +22 -23
  3. package/dist/spa/index.html +4 -4
  4. package/dist/spa/package-lock.json +421 -6
  5. package/dist/spa/package.json +10 -2
  6. package/dist/spa/src/App.vue +236 -94
  7. package/dist/spa/src/assets/base.css +2 -0
  8. package/dist/spa/src/assets/logo.svg +19 -1
  9. package/dist/spa/src/components/AcceptModal.vue +3 -10
  10. package/dist/spa/src/components/Breadcrumbs.vue +3 -2
  11. package/dist/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
  12. package/dist/spa/src/components/CustomDatePicker.vue +25 -10
  13. package/dist/spa/src/components/CustomDateRangePicker.vue +14 -5
  14. package/dist/spa/src/components/Dropdown.vue +19 -5
  15. package/dist/spa/src/components/Filters.vue +103 -38
  16. package/dist/spa/src/components/MenuLink.vue +3 -3
  17. package/dist/spa/src/components/ResourceForm.vue +205 -116
  18. package/dist/spa/{spa/src → src}/components/ResourceListTable.vue +6 -3
  19. package/dist/spa/{spa/src → src}/components/Toast.vue +9 -3
  20. package/dist/spa/src/components/ValueRenderer.vue +30 -8
  21. package/dist/spa/src/index.scss +2 -1
  22. package/dist/spa/src/main.ts +2 -2
  23. package/dist/spa/src/router/index.ts +29 -19
  24. package/dist/spa/src/stores/core.ts +65 -59
  25. package/dist/spa/src/stores/modal.ts +13 -3
  26. package/dist/spa/src/types/AdminForthConfig.ts +1477 -0
  27. package/dist/spa/src/types/FrontendAPI.ts +121 -0
  28. package/dist/spa/src/utils.ts +69 -10
  29. package/dist/spa/src/views/CreateView.vue +69 -16
  30. package/dist/spa/src/views/EditView.vue +68 -14
  31. package/dist/spa/src/views/ListView.vue +100 -371
  32. package/dist/spa/src/views/LoginView.vue +67 -29
  33. package/dist/spa/src/views/ResourceParent.vue +1 -2
  34. package/dist/spa/src/views/ShowView.vue +116 -25
  35. package/dist/spa/tailwind.config.js +8 -3
  36. package/dist/spa/vite.config.ts +13 -0
  37. package/index.ts +2 -1
  38. package/modules/restApi.ts +27 -26
  39. package/package.json +1 -1
  40. package/dist/spa/.vscode/extensions.json +0 -6
  41. package/dist/spa/public/favicon.ico +0 -0
  42. package/dist/spa/spa/.eslintrc.cjs +0 -14
  43. package/dist/spa/spa/.vscode/extensions.json +0 -6
  44. package/dist/spa/spa/README.md +0 -39
  45. package/dist/spa/spa/env.d.ts +0 -1
  46. package/dist/spa/spa/index.html +0 -23
  47. package/dist/spa/spa/package-lock.json +0 -4573
  48. package/dist/spa/spa/package.json +0 -49
  49. package/dist/spa/spa/postcss.config.js +0 -6
  50. package/dist/spa/spa/public/favicon.ico +0 -0
  51. package/dist/spa/spa/src/App.vue +0 -314
  52. package/dist/spa/spa/src/assets/base.css +0 -0
  53. package/dist/spa/spa/src/assets/logo.svg +0 -19
  54. package/dist/spa/spa/src/components/AcceptModal.vue +0 -45
  55. package/dist/spa/spa/src/components/Breadcrumbs.vue +0 -40
  56. package/dist/spa/spa/src/components/BreadcrumbsWithButtons.vue +0 -26
  57. package/dist/spa/spa/src/components/CustomDatePicker.vue +0 -174
  58. package/dist/spa/spa/src/components/CustomDateRangePicker.vue +0 -218
  59. package/dist/spa/spa/src/components/Dropdown.vue +0 -168
  60. package/dist/spa/spa/src/components/Filters.vue +0 -222
  61. package/dist/spa/spa/src/components/HelloWorld.vue +0 -17
  62. package/dist/spa/spa/src/components/MenuLink.vue +0 -24
  63. package/dist/spa/spa/src/components/ResourceForm.vue +0 -289
  64. package/dist/spa/spa/src/components/SingleSkeletLoader.vue +0 -13
  65. package/dist/spa/spa/src/components/ValueRenderer.vue +0 -66
  66. package/dist/spa/spa/src/components/icons/IconCalendar.vue +0 -5
  67. package/dist/spa/spa/src/components/icons/IconCommunity.vue +0 -7
  68. package/dist/spa/spa/src/components/icons/IconDocumentation.vue +0 -7
  69. package/dist/spa/spa/src/components/icons/IconEcosystem.vue +0 -7
  70. package/dist/spa/spa/src/components/icons/IconSupport.vue +0 -7
  71. package/dist/spa/spa/src/components/icons/IconTime.vue +0 -5
  72. package/dist/spa/spa/src/components/icons/IconTooling.vue +0 -19
  73. package/dist/spa/spa/src/index.scss +0 -27
  74. package/dist/spa/spa/src/main.ts +0 -18
  75. package/dist/spa/spa/src/router/index.ts +0 -63
  76. package/dist/spa/spa/src/stores/core.ts +0 -144
  77. package/dist/spa/spa/src/stores/modal.ts +0 -48
  78. package/dist/spa/spa/src/utils.ts +0 -103
  79. package/dist/spa/spa/src/views/CreateView.vue +0 -156
  80. package/dist/spa/spa/src/views/EditView.vue +0 -157
  81. package/dist/spa/spa/src/views/HomeView.vue +0 -8
  82. package/dist/spa/spa/src/views/ListView.vue +0 -258
  83. package/dist/spa/spa/src/views/LoginView.vue +0 -143
  84. package/dist/spa/spa/src/views/ResourceParent.vue +0 -17
  85. package/dist/spa/spa/src/views/ShowView.vue +0 -184
  86. package/dist/spa/spa/tailwind.config.js +0 -17
  87. package/dist/spa/spa/tsconfig.app.json +0 -14
  88. package/dist/spa/spa/tsconfig.json +0 -11
  89. package/dist/spa/spa/tsconfig.node.json +0 -19
  90. package/dist/spa/spa/vite.config.ts +0 -56
  91. package/dist/spa/src/views/HomeView.vue +0 -8
  92. package/dist/types.js +0 -30
  93. /package/dist/spa/{spa/public → public}/assets/favicon.png +0 -0
  94. /package/dist/spa/{spa/src → src}/components/CustomRangePicker.vue +0 -0
  95. /package/dist/spa/{spa/src → src}/components/SkeleteLoader.vue +0 -0
  96. /package/dist/spa/{spa/src → src}/composables/useFrontendApi.ts +0 -0
  97. /package/dist/spa/{spa/src → src}/composables/useStores.ts +0 -0
  98. /package/dist/spa/{spa/src → src}/spa_types/core.ts +0 -0
  99. /package/dist/spa/{spa/src → src}/stores/filters.ts +0 -0
  100. /package/dist/spa/{spa/src → src}/stores/toast.ts +0 -0
  101. /package/dist/spa/{spa/src → src}/stores/user.ts +0 -0
@@ -26,7 +26,7 @@
26
26
  <div class="mx-auto grid grid-cols-2 gap-4 mb-2" :class="{hidden: !showTimeInputs}">
27
27
  <div>
28
28
  <div class="relative">
29
- <div class="absolute inset-y-0 end-0 top-0 flex items-center pe-3.5">
29
+ <div class="absolute inset-y-0 end-0 top-0 flex items-center pe-3.5 pointer-events-none">
30
30
  <IconTime class="w-4 h-4 text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-700"/>
31
31
  </div>
32
32
 
@@ -101,6 +101,9 @@ const endDate = ref('');
101
101
  const startTime = ref('');
102
102
  const endTime = ref('');
103
103
 
104
+ const datepickerStartObject = ref('')
105
+ const datepickerEndObject = ref('')
106
+
104
107
  const start = computed(() => {
105
108
  if (!startDate.value) {
106
109
  return;
@@ -132,11 +135,11 @@ const end = computed(() => {
132
135
  })
133
136
 
134
137
  function updateFromProps() {
135
- if (props.valueStart === undefined) {
138
+ if (!props.valueStart) {
136
139
  datepickerStartEl.value.value = '';
137
140
  startTime.value = '';
138
141
  }
139
- if (props.valueEnd === undefined) {
142
+ if (!props.valueEnd) {
140
143
  datepickerEndEl.value.value = '';
141
144
  endTime.value = '';
142
145
  }
@@ -162,9 +165,9 @@ watch(end, () => {
162
165
 
163
166
  function initDatepickers() {
164
167
 
165
- new Datepicker(datepickerStartEl.value, {format: 'dd M yyyy'});
168
+ datepickerStartObject.value = new Datepicker(datepickerStartEl.value, {format: 'dd M yyyy'});
166
169
 
167
- new Datepicker(datepickerEndEl.value, {format: 'dd M yyyy'});
170
+ datepickerEndObject.value = new Datepicker(datepickerEndEl.value, {format: 'dd M yyyy'});
168
171
  addChangeDateListener();
169
172
  }
170
173
 
@@ -178,6 +181,11 @@ function removeChangeDateListener() {
178
181
  datepickerEndEl.value.removeEventListener('changeDate', setEndDate);
179
182
  }
180
183
 
184
+ function destroyDatepickerElement() {
185
+ datepickerStartObject.value.destroy();
186
+ datepickerEndObject.value.destroy();
187
+ }
188
+
181
189
  function setStartDate(event) {
182
190
  startDate.value = event.detail.date
183
191
  }
@@ -205,5 +213,6 @@ onMounted(() => {
205
213
 
206
214
  onBeforeUnmount(() => {
207
215
  removeChangeDateListener();
216
+ destroyDatepickerElement();
208
217
  })
209
218
  </script>
@@ -6,10 +6,11 @@
6
6
  v-model="search"
7
7
  @focus="showDropdown = true"
8
8
  class="block w-full pl-3 pr-10 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 sm:text-sm transition duration-150 ease-in-out dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
9
- :placeholder="selectedItems.length ? '' : 'Select...'"
9
+ :placeholder="selectedItems.length ? '' : placeholder || 'Select...'"
10
10
  />
11
11
  <div class="absolute inset-y-0 left-2 flex items-center pr-2 flex-wrap">
12
- <div v-for="item in selectedItems" :key="item.name" class="bg-blue-100 text-blue-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">
12
+ {{ }}
13
+ <div v-for="item in selectedItems" :key="item?.name" class="bg-blue-100 text-blue-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">
13
14
  <span>{{ item.label }}</span>
14
15
  <button
15
16
  type="button"
@@ -34,7 +35,7 @@
34
35
  <IconCaretUpSolid v-else class="h-5 w-5 text-gray-400" />
35
36
  </div>
36
37
  </div>
37
- <div v-if="showDropdown" class="absolute z-10 mt-1 w-full bg-white shadow-lg rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm">
38
+ <div v-if="showDropdown" class="absolute z-10 mt-1 w-full bg-white shadow-lg dark:shadow-black rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm">
38
39
  <div
39
40
  v-for="item in filteredItems"
40
41
  :key="item.value"
@@ -66,6 +67,11 @@ const props = defineProps({
66
67
  type: Boolean,
67
68
  default: false,
68
69
  },
70
+ placeholder: {
71
+ type: String,
72
+ default: '',
73
+
74
+ },
69
75
  });
70
76
 
71
77
  const emit = defineEmits(['update:modelValue']);
@@ -76,10 +82,14 @@ const showDropdown = ref(false);
76
82
  const selectedItems = ref([]);
77
83
 
78
84
  function updateFromProps() {
79
- console.log('⚡ updateFromProps', props.modelValue)
80
85
  if (props.modelValue !== undefined) {
81
86
  if (props.single) {
82
- selectedItems.value = [props.options.find(item => item.value === props.modelValue)];
87
+ const el = props.options.find(item => item.value === props.modelValue);
88
+ if (el) {
89
+ selectedItems.value = [el];
90
+ } else {
91
+ selectedItems.value = [];
92
+ }
83
93
  } else {
84
94
  selectedItems.value = props.options.filter(item => props.modelValue.includes(item.value));
85
95
  }
@@ -93,6 +103,10 @@ onMounted(() => {
93
103
  updateFromProps();
94
104
  });
95
105
 
106
+ watch(() => props.options, () => {
107
+ updateFromProps();
108
+ });
109
+
96
110
  addClickListener();
97
111
 
98
112
  });
@@ -2,11 +2,11 @@
2
2
  <!-- drawer component -->
3
3
  <div id="drawer-navigation"
4
4
 
5
- class="fixed top-14 right-0 z-40 p-4 overflow-y-auto transition-transform translate-x-full bg-white w-80 dark:bg-gray-800 shadow-xl"
5
+ class="fixed right-0 z-50 p-4 overflow-y-auto transition-transform translate-x-full bg-white w-80 dark:bg-gray-800 shadow-xl dark:shadow-gray-900"
6
6
 
7
7
  :class="show ? 'top-0 transform-none' : ''"
8
8
  tabindex="-1" aria-labelledby="drawer-navigation-label"
9
- :style="{ height: `calc(100vh - 3.5rem)` }"
9
+ :style="{ height: `calc(100vh ` }"
10
10
  >
11
11
  <h5 id="drawer-navigation-label" class="text-base font-semibold text-gray-500 uppercase dark:text-gray-400">
12
12
  Filters
@@ -22,11 +22,17 @@
22
22
  <li v-for="c in columnsWithFilter" :key="c">
23
23
  <p class="dark:text-gray-400">{{ c.label }}</p>
24
24
 
25
- <Dropdown
26
- v-if="c.type === 'boolean'"
25
+ <Dropdown
26
+ v-if="c.foreignResource"
27
+ :options="columnOptions[c.name] || []"
28
+ @update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
29
+ :modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
30
+ />
31
+ <Dropdown
32
+ v-else-if="c.type === 'boolean'"
27
33
  :options="[{ label: 'Yes', value: true }, { label: 'No', value: false }, { label: 'Unset', value: null }]"
28
34
  @update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
29
- :modelValue="filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
35
+ :modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
30
36
  />
31
37
 
32
38
  <Dropdown
@@ -34,7 +40,7 @@
34
40
  :options="c.enum"
35
41
  :allowCustom="c.allowCustom"
36
42
  @update:modelValue="setFilterItem({ column: c, operator: 'in', value: $event })"
37
- :modelValue="filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
43
+ :modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
38
44
  />
39
45
 
40
46
  <input
@@ -48,9 +54,9 @@
48
54
  <CustomDateRangePicker
49
55
  v-else-if="['datetime'].includes(c.type)"
50
56
  :column="c"
51
- :valueStart="filters.find(f => f.field === c.name && f.operator === 'gte')?.value || undefined"
57
+ :valueStart="filtersStore.filters.find(f => f.field === c.name && f.operator === 'gte')?.value || undefined"
52
58
  @update:valueStart="setFilterItem({ column: c, operator: 'gte', value: $event || undefined })"
53
- :valueEnd="filters.find(f => f.field === c.name && f.operator === 'lte')?.value || undefined"
59
+ :valueEnd="filtersStore.filters.find(f => f.field === c.name && f.operator === 'lte')?.value || undefined"
54
60
  @update:valueEnd="setFilterItem({ column: c, operator: 'lte', value: $event || undefined })"
55
61
  />
56
62
 
@@ -62,22 +68,32 @@
62
68
  :value="getFilterItem({ column: c, operator: 'ilike' })"
63
69
  >
64
70
 
65
- <div v-else-if="['integer', 'decimal', 'float'].includes(c.type)" class="flex gap-2">
66
- <input
67
- type="number" aria-describedby="helper-text-explanation"
68
- class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
69
- placeholder="From"
70
- @input="setFilterItem({ column: c, operator: 'gte', value: $event.target.value || undefined })"
71
- :value="getFilterItem({ column: c, operator: 'gte' })"
72
- >
73
- <input
74
- type="number" aria-describedby="helper-text-explanation"
75
- class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
76
- placeholder="To"
77
- @input="setFilterItem({ column: c, operator: 'lte', value: $event.target.value || undefined})"
78
- :value="getFilterItem({ column: c, operator: 'lte' })"
79
- >
80
- </div>
71
+ <CustomRangePicker
72
+ v-else-if="['integer', 'decimal', 'float'].includes(c.type) && c.allowMinMaxQuery"
73
+ :min="getFilterMinValue(c.name)"
74
+ :max="getFilterMaxValue(c.name)"
75
+ :valueStart="getFilterItem({ column: c, operator: 'gte' })"
76
+ @update:valueStart="setFilterItem({ column: c, operator: 'gte', value: $event || undefined })"
77
+ :valueEnd="getFilterItem({ column: c, operator: 'lte' })"
78
+ @update:valueEnd="setFilterItem({ column: c, operator: 'lte', value: $event || undefined })"
79
+ />
80
+
81
+ <div v-else-if="['integer', 'decimal', 'float'].includes(c.type)" class="flex gap-2">
82
+ <input
83
+ type="number" aria-describedby="helper-text-explanation"
84
+ class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
85
+ placeholder="From"
86
+ @input="setFilterItem({ column: c, operator: 'gte', value: $event.target.value || undefined })"
87
+ :value="getFilterItem({ column: c, operator: 'gte' })"
88
+ >
89
+ <input
90
+ type="number" aria-describedby="helper-text-explanation"
91
+ class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
92
+ placeholder="To"
93
+ @input="setFilterItem({ column: c, operator: 'lte', value: $event.target.value || undefined})"
94
+ :value="getFilterItem({ column: c, operator: 'lte' })"
95
+ >
96
+ </div>
81
97
 
82
98
  </li>
83
99
  </ul>
@@ -85,33 +101,71 @@
85
101
 
86
102
  <div class="flex justify-end gap-2">
87
103
  <button
88
- :disabled="!filters.length"
104
+ :disabled="!filtersStore.filters.length"
89
105
  type="button"
90
- class="flex items-center py-1 px-3 mb-2 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
106
+ class="flex items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
91
107
  @click="clear">Clear all</button>
92
108
 
93
109
  </div>
94
110
  </div>
95
111
 
96
- <div v-if="show" drawer-backdrop="" class="bg-gray-900/50 dark:bg-gray-900/80 fixed inset-0 z-30"
112
+ <div v-if="show" class="bg-gray-900/50 dark:bg-gray-900/80 fixed inset-0 z-30"
97
113
  @click="$emit('hide')">
98
114
  </div>
99
115
  </template>
100
116
 
101
117
  <script setup>
102
- import { watch, computed } from 'vue'
118
+ import { watch, computed, ref, onMounted } from 'vue'
103
119
  import Dropdown from '@/components/Dropdown.vue';
104
120
  import CustomDateRangePicker from '@/components/CustomDateRangePicker.vue';
121
+ import { callAdminForthApi } from '@/utils';
122
+ import { useRouter } from 'vue-router';
123
+ import { computedAsync } from '@vueuse/core'
124
+ import CustomRangePicker from "@/components/CustomRangePicker.vue";
125
+ import { useFiltersStore } from '@/stores/filters';
126
+
127
+ const filtersStore = useFiltersStore();
128
+
105
129
 
106
130
  // props: columns
107
131
  // add support for v-model:filers
108
132
  const props = defineProps(['columns', 'filters', 'show', 'columnsMinMax']);
109
133
  const emits = defineEmits(['update:filters', 'hide']);
110
134
 
111
- const columnsWithFilter = computed(
135
+ const router = useRouter();
136
+
137
+
138
+ const columnsWithFilter = computed(
112
139
  () => props.columns?.filter(column => column.showIn.includes('filter')) || []
113
140
  );
114
141
 
142
+ const columnOptions = computedAsync(async () => {
143
+ const ret = {};
144
+ if (!props.columns) {
145
+ return ret;
146
+ }
147
+ await Promise.all(
148
+ Object.values(props.columns).map(async (column) => {
149
+ if (column.foreignResource) {
150
+ const list = await callAdminForthApi({
151
+ method: 'POST',
152
+ path: `/get_resource_foreign_data`,
153
+ body: {
154
+ resourceId: router.currentRoute.value.params.resourceId,
155
+ column: column.name,
156
+ limit: 1000,
157
+ offset: 0,
158
+ },
159
+ });
160
+ ret[column.name] = list.items;
161
+ }
162
+ })
163
+ );
164
+
165
+ return ret;
166
+ }, {});
167
+
168
+
115
169
  // sync 'body' class 'overflow-hidden' with show prop show
116
170
  watch(() => props.show, (show) => {
117
171
  if (show) {
@@ -130,28 +184,39 @@ watch(() => props.show, (show) => {
130
184
 
131
185
  function setFilterItem({ column, operator, value }) {
132
186
 
133
- const index = props.filters.findIndex(f => f.field === column.name && f.operator === operator);
187
+ const index = filtersStore.filters.findIndex(f => f.field === column.name && f.operator === operator);
134
188
  if (value === undefined) {
135
189
  if (index !== -1) {
136
- props.filters.splice(index, 1);
190
+ filtersStore.filters.splice(index, 1);
137
191
  }
138
- emits('update:filters', [...props.filters]);
139
- return;
140
192
  } else {
141
193
  if (index === -1) {
142
- props.filters.push({ field: column.name, value, operator });
194
+ filtersStore.setFilter({ field: column.name, value, operator });
143
195
  } else {
144
- props.filters[index].value = value;
196
+ filtersStore.setFilters([...filtersStore.filters.slice(0, index), { field: column.name, value, operator }, ...filtersStore.filters.slice(index + 1)])
145
197
  }
146
198
  }
147
- emits('update:filters', [...props.filters]);
199
+ emits('update:filters', [...filtersStore.filters]);
148
200
  }
149
201
 
150
202
  function getFilterItem({ column, operator }) {
151
- return props.filters.find(f => f.field === column.name && f.operator === operator)?.value || '';
203
+ return filtersStore.filters.find(f => f.field === column.name && f.operator === operator)?.value || '';
152
204
  }
153
205
 
154
206
  async function clear() {
155
- emits('update:filters', []);
207
+ filtersStore.clearFilters();
208
+ emits('update:filters', [...filtersStore.filters]);
209
+ }
210
+
211
+ function getFilterMinValue(columnName) {
212
+ if(props.columnsMinMax && props.columnsMinMax[columnName]) {
213
+ return props.columnsMinMax[columnName]?.min
214
+ }
215
+ }
216
+
217
+ function getFilterMaxValue(columnName) {
218
+ if(props.columnsMinMax && props.columnsMinMax[columnName]) {
219
+ return props.columnsMinMax[columnName]?.max
220
+ }
156
221
  }
157
222
  </script>
@@ -1,16 +1,16 @@
1
1
  <template>
2
2
  <RouterLink
3
3
  :to="{name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {}}"
4
- class="flex items-center py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white" role="menuitem"
4
+ class="flex group items-center py-2 text-lightSidebarText dark:text-darkSidebarText rounded-default hover:bg-lightSidebarItemHover hover:text-lightSidebarTextHover dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextHover active:bg-lightSidebarActive dark:active:bg-darkSidebarHover" role="menuitem"
5
5
  :class="{
6
6
  'px-4': isChild,
7
7
  'px-2': !isChild,
8
- 'bg-blue-100 dark:bg-gray-700': item.resourceId ?
8
+ 'bg-lightSidebarItemActive dark:bg-darkSidebarItemActive': item.resourceId ?
9
9
  ($route.params.resourceId === item.resourceId && $route.name === 'resource-list') :
10
10
  ($route.name === item.path)
11
11
  }"
12
12
  >
13
- <component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" ></component>
13
+ <component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-lightSidebarIcons dark:text-darkSidebarIcons transition duration-75 group-hover:text-lightSidebarIconsHover dark:group-hover:text-darkSidebarIconsHover" ></component>
14
14
  <span class="ms-3">{{ item.label }}</span>
15
15
  </RouterLink>
16
16
  </template>