adminforth 1.1.5 → 1.1.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.
@@ -363,7 +363,7 @@ class CodeInjector {
363
363
  }
364
364
  yield this.runNpmShell({ command: 'ci', verbose, cwd: CodeInjector.SPA_TMP_PATH });
365
365
  // get packages with version from customPackage
366
- const IGNORE_PACKAGES = ['tsx', 'typescript', 'express', 'nodemon'];
366
+ const IGNORE_PACKAGES = ['tsx', 'typescript', 'express', 'nodemon', 'adminforth'];
367
367
  const customPackgeNames = [...Object.keys(usersPackage.dependencies), ...Object.keys(usersPackage.devDependencies || [])]
368
368
  .filter((packageName) => !IGNORE_PACKAGES.includes(packageName))
369
369
  .reduce((acc, packageName) => {
@@ -152,7 +152,7 @@ const router = useRouter();
152
152
 
153
153
  const props = defineProps({
154
154
  loading: Boolean,
155
- resourceColumns: Object,
155
+ resource: Object,
156
156
  record: Object,
157
157
  validating: Boolean,
158
158
  customComponentsPerColumn: Object,
@@ -228,7 +228,7 @@ onMounted(() => {
228
228
 
229
229
  const columnOptions = computedAsync(async () => {
230
230
  return (await Promise.all(
231
- Object.values(props.resourceColumns).map(async (column) => {
231
+ Object.values(props.resource.columns).map(async (column) => {
232
232
  if (column.foreignResource) {
233
233
  const list = await callAdminForthApi({
234
234
  method: 'POST',
@@ -251,7 +251,7 @@ const coreStore = useCoreStore();
251
251
 
252
252
  const editableColumns = computed(() => {
253
253
  const mode = props.record ? 'edit' : 'create';
254
- return props.resourceColumns?.filter(column => column.showIn.includes(mode));
254
+ return props.resource?.columns?.filter(column => column.showIn.includes(mode));
255
255
  });
256
256
 
257
257
  const isValid = computed(() => {
@@ -146,7 +146,13 @@
146
146
  <div class="flex">
147
147
  <RouterLink
148
148
  v-if="resource.options?.allowedActions.show"
149
- :to="{ name: 'resource-show', params: { resourceId: $route.params.resourceId, primaryKey: row._primaryKeyValue } }"
149
+ :to="{
150
+ name: 'resource-show',
151
+ params: {
152
+ resourceId: resource.resourceId,
153
+ primaryKey: row._primaryKeyValue,
154
+ }
155
+ }"
150
156
  class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
151
157
  :data-tooltip-target="`tooltip-show-${rowI}`"
152
158
  >
@@ -164,7 +170,7 @@
164
170
  :to="{
165
171
  name: 'resource-edit',
166
172
  params: {
167
- resourceId: resource.id,
173
+ resourceId: resource.resourceId,
168
174
  primaryKey: row._primaryKeyValue
169
175
  }
170
176
  }"
@@ -4,6 +4,7 @@ import { useModalStore } from '../stores/modal';
4
4
  import { useCoreStore } from '@/stores/core';
5
5
  import { useFiltersStore } from '@/stores/filters';
6
6
  import router from '@/router'
7
+ import type { AdminForthResourceColumn } from '@/types/AdminForthConfig';
7
8
 
8
9
 
9
10
 
@@ -65,7 +66,7 @@ export class FrontendAPI implements FrontendAPIInterface {
65
66
  } else {
66
67
  if(!this.coreStore) this.coreStore = useCoreStore()
67
68
  console.log(this.coreStore.resourceColumnsWithFilters,'core store')
68
- const filterField = this.coreStore.resourceColumnsWithFilters.find((col) => col.name === filter.field)
69
+ const filterField = this.coreStore.resourceColumnsWithFilters.find((col: AdminForthResourceColumn) => col.name === filter.field)
69
70
  if(!filterField){
70
71
  throw new Error(`Field ${filter.field} is not available for filtering`)
71
72
  }
@@ -97,7 +98,7 @@ export class FrontendAPI implements FrontendAPIInterface {
97
98
  updateListFilter(filter: FilterParams): void {
98
99
  if(this.listFilterValidation(filter)){
99
100
  this.filtersStore = useFiltersStore()
100
- const index = this.filtersStore.filters.findIndex((f) => f.field === filter.field)
101
+ const index = this.filtersStore.filters.findIndex((f: FilterParams) => f.field === filter.field)
101
102
  if(index === -1) {
102
103
  this.filtersStore.setFilter(filter)
103
104
  } else {
@@ -1,19 +1,21 @@
1
1
  import { ref, computed } from 'vue'
2
2
  import { defineStore } from 'pinia'
3
3
  import { callAdminForthApi } from '@/utils';
4
+ import type { AdminForthResource, AdminForthResourceColumn } from '@/types/AdminForthConfig';
5
+ import type { Ref } from 'vue'
4
6
 
5
7
  export const useCoreStore = defineStore('core', () => {
6
- const resourceById = ref([]);
8
+ const resourceById: Ref<Object> = ref({});
7
9
  const menu = ref([]);
8
10
  const config = ref({});
9
11
  const record = ref({});
10
- const resourceColumns = ref(null);
11
- const resource = ref(null);
12
+ const resource: Ref<AdminForthResource | null> = ref(null);
13
+
12
14
  const resourceColumnsWithFilters = computed(() => {
13
- if (!resourceColumns.value) {
15
+ if (!resource.value) {
14
16
  return [];
15
17
  }
16
- return resourceColumns.value.filter((col) => col.showIn.includes('filter'));
18
+ return resource.value.columns.filter((col: AdminForthResourceColumn) => col.showIn?.includes('filter'));
17
19
  })
18
20
 
19
21
  const resourceOptions = ref(null);
@@ -30,7 +32,7 @@ export const useCoreStore = defineStore('core', () => {
30
32
  return
31
33
  }
32
34
  menu.value = resp.menu;
33
- resourceById.value = resp.resources.reduce((acc, resource) => {
35
+ resourceById.value = resp.resources.reduce((acc: Object, resource: AdminForthResource) => {
34
36
  acc[resource.resourceId] = resource;
35
37
  return acc;
36
38
  }, {});
@@ -42,7 +44,7 @@ export const useCoreStore = defineStore('core', () => {
42
44
  async function fetchRecord({ resourceId, primaryKey }) {
43
45
  record.value = null;
44
46
 
45
- if (!resourceColumns.value) {
47
+ if (!resource.value) {
46
48
  throw new Error('Columns not fetched yet');
47
49
  }
48
50
 
@@ -54,7 +56,7 @@ export const useCoreStore = defineStore('core', () => {
54
56
  resourceId: resourceId,
55
57
  filters: [
56
58
  {
57
- field: resourceColumns.value.find((col) => col.primaryKey).name,
59
+ field: resource.value.columns.find((col: AdminForthResourceColumn) => col.primaryKey).name,
58
60
  operator: 'eq',
59
61
  value: primaryKey
60
62
  }
@@ -70,13 +72,12 @@ export const useCoreStore = defineStore('core', () => {
70
72
  resourceOptions.value = respData.options;
71
73
  }
72
74
 
73
- async function fetchResourceFull({ resourceId }) {
74
- if (resourceColumnsId.value === resourceId && resourceColumns.value) {
75
+ async function fetchResourceFull({ resourceId }: { resourceId: string }) {
76
+ if (resourceColumnsId.value === resourceId && resource.value) {
75
77
  // already fetched
76
78
  return;
77
79
  }
78
80
  resourceColumnsId.value = resourceId;
79
- resourceColumns.value = null;
80
81
  resourceColumnsError.value = '';
81
82
  const res = await callAdminForthApi({
82
83
  path: '/get_resource',
@@ -88,7 +89,6 @@ export const useCoreStore = defineStore('core', () => {
88
89
  if (res.error) {
89
90
  resourceColumnsError.value = res.error;
90
91
  } else {
91
- resourceColumns.value = res.resource.columns;
92
92
  resourceById.value[resourceId] = res.resource;
93
93
  resource.value = res.resource;
94
94
  resourceOptions.value = res.resource.options;
@@ -131,7 +131,6 @@ export const useCoreStore = defineStore('core', () => {
131
131
  fetchMenuAndResource,
132
132
  fetchRecord,
133
133
  record,
134
- resourceColumns,
135
134
  fetchResourceFull,
136
135
  resourceColumnsError,
137
136
  resourceOptions,
@@ -46,7 +46,7 @@
46
46
  <ResourceForm
47
47
  v-else
48
48
  :record="initalValues"
49
- :resourceColumns="coreStore.resourceColumns"
49
+ :resource="coreStore.resource"
50
50
  @update:record="onUpdateRecord"
51
51
  @update:isValid="isValid = $event"
52
52
  :validating="validating"
@@ -95,7 +95,10 @@ let createComponentsPerColumn = {};
95
95
  const coreStore = useCoreStore();
96
96
 
97
97
  const initalValues = computed(() => {
98
- return route.query || {};
98
+ if (!route.query.values) {
99
+ return {};
100
+ }
101
+ return JSON.parse(decodeURIComponent(route.query.values));
99
102
  });
100
103
 
101
104
  async function onUpdateRecord(newRecord) {
@@ -108,7 +111,7 @@ onMounted(async () => {
108
111
  await coreStore.fetchResourceFull({
109
112
  resourceId: route.params.resourceId
110
113
  });
111
- createComponentsPerColumn = coreStore.resourceColumns.reduce((acc, column) => {
114
+ createComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
112
115
  if (column.components?.create) {
113
116
  acc[column.name] = getCustomComponent(column.components.create);
114
117
  }
@@ -135,11 +138,17 @@ async function saveRecord() {
135
138
  },
136
139
  });
137
140
  saving.value = false;
138
- router.push({ name: 'resource-show', params: {
139
- resourceId: route.params.resourceId,
140
- primaryKey: response.newRecordId
141
-
142
- } });
141
+ if (route.query.returnTo) {
142
+ router.push(route.query.returnTo);
143
+ } else {
144
+ router.push({
145
+ name: 'resource-show',
146
+ params: {
147
+ resourceId: route.params.resourceId,
148
+ primaryKey: response.newRecordId
149
+ }
150
+ });
151
+ }
143
152
  }
144
153
 
145
154
 
@@ -95,10 +95,10 @@ async function onUpdateRecord(newRecord) {
95
95
 
96
96
  const editableRecord = computed(() => {
97
97
  const newRecord = { ...coreStore.record };
98
- if (!coreStore.resourceColumns) {
98
+ if (!coreStore.resource) {
99
99
  return {};
100
100
  }
101
- coreStore.resourceColumns.forEach(column => {
101
+ coreStore.resource.columns.forEach(column => {
102
102
  if (column.foreignResource) {
103
103
  newRecord[column.name] = newRecord[column.name]?.pk
104
104
  }
@@ -119,7 +119,7 @@ onMounted(async () => {
119
119
  });
120
120
  checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'edit');
121
121
 
122
- editComponentsPerColumn = coreStore.resourceColumns.reduce((acc, column) => {
122
+ editComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
123
123
  if (column.components?.edit) {
124
124
  acc[column.name] = getCustomComponent(column.components.edit);
125
125
  }
@@ -2,7 +2,7 @@
2
2
  <div class="relative">
3
3
  <Teleport to="body">
4
4
  <Filters
5
- :columns="coreStore.resourceColumns"
5
+ :columns="coreStore.resource?.columns"
6
6
  :columnsMinMax="columnsMinMax" :show="filtersShow"
7
7
  @hide="filtersShow = false"
8
8
  />
@@ -159,6 +159,8 @@ watch([page], async () => {
159
159
 
160
160
  watch(()=>filtersStore.filters, async () => {
161
161
  page.value = 1;
162
+ checkboxes.value = [];
163
+
162
164
  await getList();
163
165
  }, {deep: true});
164
166
 
@@ -183,7 +185,7 @@ async function getList() {
183
185
  });
184
186
 
185
187
  rows.value = data.data?.map(row => {
186
- row._primaryKeyValue = row[coreStore.resourceColumns.find(c => c.primaryKey).name];
188
+ row._primaryKeyValue = row[coreStore.resource.columns.find(c => c.primaryKey).name];
187
189
  return row;
188
190
  });
189
191
  totalRows.value = data.total;
@@ -58,7 +58,7 @@
58
58
  </tr>
59
59
  </thead>
60
60
  <tbody>
61
- <tr v-for="column in coreStore.resourceColumns?.filter(c => c.showIn.includes('show'))" :key="column.name"
61
+ <tr v-for="column in coreStore.resource?.columns.filter(c => c.showIn.includes('show'))" :key="column.name"
62
62
  class="bg-form-view-bg odd:dark:bg-gray-900 even:dark:bg-gray-800 border-b dark:border-gray-700"
63
63
  >
64
64
  <component
@@ -145,7 +145,7 @@ onMounted(async () => {
145
145
  });
146
146
  checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
147
147
 
148
- showComponentsPerColumn = coreStore.resourceColumns.reduce((acc, column) => {
148
+ showComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
149
149
  if (column.components?.show) {
150
150
  acc[column.name] = getCustomComponent(column.components.show);
151
151
  }
@@ -416,7 +416,7 @@ class CodeInjector implements CodeInjectorType {
416
416
  await this.runNpmShell({command: 'ci', verbose, cwd: CodeInjector.SPA_TMP_PATH});
417
417
 
418
418
  // get packages with version from customPackage
419
- const IGNORE_PACKAGES = ['tsx', 'typescript', 'express', 'nodemon'];
419
+ const IGNORE_PACKAGES = ['tsx', 'typescript', 'express', 'nodemon', 'adminforth'];
420
420
  const customPackgeNames = [...Object.keys(usersPackage.dependencies), ...Object.keys(usersPackage.devDependencies || [])]
421
421
  .filter((packageName) => !IGNORE_PACKAGES.includes(packageName))
422
422
  .reduce(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -3,13 +3,12 @@
3
3
  <!-- todo exclude foreign column-->
4
4
  <Filters
5
5
  v-if="listResource"
6
- :columns="listResource.columns"
6
+ :columns="listResource.columns.filter((c) => c.name !== listResourceRefColumn.name)"
7
7
  v-model:filters="filters"
8
8
  :columnsMinMax="columnsMinMax"
9
9
  :show="filtersShow"
10
10
  @hide="filtersShow = false"
11
11
  />
12
- {{ listResource?.columns}}
13
12
  </Teleport>
14
13
 
15
14
  <td colspan="2">
@@ -56,23 +55,24 @@
56
55
  name: 'resource-create',
57
56
  params: { resourceId: listResource.resourceId },
58
57
  query: {
59
- [listResourceRefColumn.name]: props.record[selfPrimaryKeyColumn.name]
60
- }
58
+ values: encodeURIComponent(JSON.stringify({[listResourceRefColumn.name]: props.record[selfPrimaryKeyColumn.name]})),
59
+ returnTo: $route.fullPath,
60
+ },
61
61
  }"
62
- 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 rounded-default"
62
+ 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 rounded-default"
63
63
  >
64
64
  <IconPlusOutline class="w-4 h-4 me-2"/>
65
65
  Create
66
66
  </RouterLink>
67
67
 
68
68
  <button
69
- class="flex gap-1 items-center py-1 px-3 me-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 rounded-default"
69
+ class="flex gap-1 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 rounded-default"
70
70
  @click="()=>{filtersShow = !filtersShow}"
71
71
  >
72
72
  <IconFilterOutline class="w-4 h-4 me-2"/>
73
73
  Filter
74
74
  <span
75
- class="bg-red-100 text-red-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400"
75
+ class="bg-red-100 text-red-800 text-xs font-medium px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400"
76
76
  v-if="filters.length">
77
77
  {{ filters.length }}
78
78
  </span>
@@ -88,6 +88,7 @@
88
88
  @update:checkboxes="checkboxes = $event"
89
89
  :pageSize="pageSize"
90
90
  :totalRows="totalRows"
91
+ :checkboxes="checkboxes"
91
92
  />
92
93
  </td>
93
94
  </template>
@@ -96,13 +97,15 @@
96
97
  import { callAdminForthApi } from '@/utils';
97
98
  import { ref, onMounted, watch, computed } from 'vue';
98
99
  import ResourceListTable from '@/components/ResourceListTable.vue';
99
-
100
+ import Filters from '@/components/Filters.vue';
100
101
  import {
101
102
  IconBanOutline,
102
103
  IconFilterOutline,
103
104
  IconPlusOutline,
104
105
  } from '@iconify-prerendered/vue-flowbite';
105
106
 
107
+ import { getIcon } from '@/utils';
108
+
106
109
  const props = defineProps(['column', 'record', 'meta', 'resource', 'adminUser']);
107
110
 
108
111
  const listResource = ref(null);
@@ -118,6 +121,7 @@ const totalRows = ref(0);
118
121
 
119
122
  const filters = ref([]);
120
123
  const filtersShow = ref(false);
124
+ const columnsMinMax = ref(null);
121
125
 
122
126
  const listResourceRefColumn = computed(() => {
123
127
  if (!listResource.value) {
@@ -164,6 +168,28 @@ watch([sort], async () => {
164
168
  await getList();
165
169
  }, {deep: true});
166
170
 
171
+ watch([filters], async () => {
172
+ page.value = 1;
173
+ checkboxes.value = [];
174
+ await getList();
175
+ }, {deep: true});
176
+
177
+
178
+ async function startBulkAction(actionId) {
179
+ const data = await callAdminForthApi({
180
+ path: '/start_bulk_action',
181
+ method: 'POST',
182
+ body: {
183
+ resourceId: listResource.value.resourceId,
184
+ actionId: actionId,
185
+ recordIds: checkboxes.value
186
+ }
187
+ });
188
+ if (data?.status === 'success') {
189
+ checkboxes.value = [];
190
+ }
191
+ await getList();
192
+ }
167
193
 
168
194
  async function getList() {
169
195
  rows.value = null;
@@ -188,7 +214,6 @@ async function getList() {
188
214
  totalRows.value = data.total;
189
215
  }
190
216
 
191
-
192
217
  onMounted( async () => {
193
218
  loading.value = true;
194
219
  const foreighResourceId = props.meta.foreignResourceId;
@@ -197,6 +222,13 @@ onMounted( async () => {
197
222
  method: 'POST',
198
223
  body: {},
199
224
  })).resource;
225
+ columnsMinMax.value = await callAdminForthApi({
226
+ path: '/get_min_max_for_columns',
227
+ method: 'POST',
228
+ body: {
229
+ resourceId: foreighResourceId,
230
+ }
231
+ });
200
232
  loading.value = false;
201
233
  await getList();
202
234
  });
@@ -152,7 +152,7 @@ const router = useRouter();
152
152
 
153
153
  const props = defineProps({
154
154
  loading: Boolean,
155
- resourceColumns: Object,
155
+ resource: Object,
156
156
  record: Object,
157
157
  validating: Boolean,
158
158
  customComponentsPerColumn: Object,
@@ -228,7 +228,7 @@ onMounted(() => {
228
228
 
229
229
  const columnOptions = computedAsync(async () => {
230
230
  return (await Promise.all(
231
- Object.values(props.resourceColumns).map(async (column) => {
231
+ Object.values(props.resource.columns).map(async (column) => {
232
232
  if (column.foreignResource) {
233
233
  const list = await callAdminForthApi({
234
234
  method: 'POST',
@@ -251,7 +251,7 @@ const coreStore = useCoreStore();
251
251
 
252
252
  const editableColumns = computed(() => {
253
253
  const mode = props.record ? 'edit' : 'create';
254
- return props.resourceColumns?.filter(column => column.showIn.includes(mode));
254
+ return props.resource?.columns?.filter(column => column.showIn.includes(mode));
255
255
  });
256
256
 
257
257
  const isValid = computed(() => {
@@ -146,7 +146,13 @@
146
146
  <div class="flex">
147
147
  <RouterLink
148
148
  v-if="resource.options?.allowedActions.show"
149
- :to="{ name: 'resource-show', params: { resourceId: $route.params.resourceId, primaryKey: row._primaryKeyValue } }"
149
+ :to="{
150
+ name: 'resource-show',
151
+ params: {
152
+ resourceId: resource.resourceId,
153
+ primaryKey: row._primaryKeyValue,
154
+ }
155
+ }"
150
156
  class="font-medium text-blue-600 dark:text-blue-500 hover:underline"
151
157
  :data-tooltip-target="`tooltip-show-${rowI}`"
152
158
  >
@@ -164,7 +170,7 @@
164
170
  :to="{
165
171
  name: 'resource-edit',
166
172
  params: {
167
- resourceId: resource.id,
173
+ resourceId: resource.resourceId,
168
174
  primaryKey: row._primaryKeyValue
169
175
  }
170
176
  }"
@@ -4,6 +4,7 @@ import { useModalStore } from '../stores/modal';
4
4
  import { useCoreStore } from '@/stores/core';
5
5
  import { useFiltersStore } from '@/stores/filters';
6
6
  import router from '@/router'
7
+ import type { AdminForthResourceColumn } from '@/types/AdminForthConfig';
7
8
 
8
9
 
9
10
 
@@ -65,7 +66,7 @@ export class FrontendAPI implements FrontendAPIInterface {
65
66
  } else {
66
67
  if(!this.coreStore) this.coreStore = useCoreStore()
67
68
  console.log(this.coreStore.resourceColumnsWithFilters,'core store')
68
- const filterField = this.coreStore.resourceColumnsWithFilters.find((col) => col.name === filter.field)
69
+ const filterField = this.coreStore.resourceColumnsWithFilters.find((col: AdminForthResourceColumn) => col.name === filter.field)
69
70
  if(!filterField){
70
71
  throw new Error(`Field ${filter.field} is not available for filtering`)
71
72
  }
@@ -97,7 +98,7 @@ export class FrontendAPI implements FrontendAPIInterface {
97
98
  updateListFilter(filter: FilterParams): void {
98
99
  if(this.listFilterValidation(filter)){
99
100
  this.filtersStore = useFiltersStore()
100
- const index = this.filtersStore.filters.findIndex((f) => f.field === filter.field)
101
+ const index = this.filtersStore.filters.findIndex((f: FilterParams) => f.field === filter.field)
101
102
  if(index === -1) {
102
103
  this.filtersStore.setFilter(filter)
103
104
  } else {
@@ -1,19 +1,21 @@
1
1
  import { ref, computed } from 'vue'
2
2
  import { defineStore } from 'pinia'
3
3
  import { callAdminForthApi } from '@/utils';
4
+ import type { AdminForthResource, AdminForthResourceColumn } from '@/types/AdminForthConfig';
5
+ import type { Ref } from 'vue'
4
6
 
5
7
  export const useCoreStore = defineStore('core', () => {
6
- const resourceById = ref([]);
8
+ const resourceById: Ref<Object> = ref({});
7
9
  const menu = ref([]);
8
10
  const config = ref({});
9
11
  const record = ref({});
10
- const resourceColumns = ref(null);
11
- const resource = ref(null);
12
+ const resource: Ref<AdminForthResource | null> = ref(null);
13
+
12
14
  const resourceColumnsWithFilters = computed(() => {
13
- if (!resourceColumns.value) {
15
+ if (!resource.value) {
14
16
  return [];
15
17
  }
16
- return resourceColumns.value.filter((col) => col.showIn.includes('filter'));
18
+ return resource.value.columns.filter((col: AdminForthResourceColumn) => col.showIn?.includes('filter'));
17
19
  })
18
20
 
19
21
  const resourceOptions = ref(null);
@@ -30,7 +32,7 @@ export const useCoreStore = defineStore('core', () => {
30
32
  return
31
33
  }
32
34
  menu.value = resp.menu;
33
- resourceById.value = resp.resources.reduce((acc, resource) => {
35
+ resourceById.value = resp.resources.reduce((acc: Object, resource: AdminForthResource) => {
34
36
  acc[resource.resourceId] = resource;
35
37
  return acc;
36
38
  }, {});
@@ -42,7 +44,7 @@ export const useCoreStore = defineStore('core', () => {
42
44
  async function fetchRecord({ resourceId, primaryKey }) {
43
45
  record.value = null;
44
46
 
45
- if (!resourceColumns.value) {
47
+ if (!resource.value) {
46
48
  throw new Error('Columns not fetched yet');
47
49
  }
48
50
 
@@ -54,7 +56,7 @@ export const useCoreStore = defineStore('core', () => {
54
56
  resourceId: resourceId,
55
57
  filters: [
56
58
  {
57
- field: resourceColumns.value.find((col) => col.primaryKey).name,
59
+ field: resource.value.columns.find((col: AdminForthResourceColumn) => col.primaryKey).name,
58
60
  operator: 'eq',
59
61
  value: primaryKey
60
62
  }
@@ -70,13 +72,12 @@ export const useCoreStore = defineStore('core', () => {
70
72
  resourceOptions.value = respData.options;
71
73
  }
72
74
 
73
- async function fetchResourceFull({ resourceId }) {
74
- if (resourceColumnsId.value === resourceId && resourceColumns.value) {
75
+ async function fetchResourceFull({ resourceId }: { resourceId: string }) {
76
+ if (resourceColumnsId.value === resourceId && resource.value) {
75
77
  // already fetched
76
78
  return;
77
79
  }
78
80
  resourceColumnsId.value = resourceId;
79
- resourceColumns.value = null;
80
81
  resourceColumnsError.value = '';
81
82
  const res = await callAdminForthApi({
82
83
  path: '/get_resource',
@@ -88,7 +89,6 @@ export const useCoreStore = defineStore('core', () => {
88
89
  if (res.error) {
89
90
  resourceColumnsError.value = res.error;
90
91
  } else {
91
- resourceColumns.value = res.resource.columns;
92
92
  resourceById.value[resourceId] = res.resource;
93
93
  resource.value = res.resource;
94
94
  resourceOptions.value = res.resource.options;
@@ -131,7 +131,6 @@ export const useCoreStore = defineStore('core', () => {
131
131
  fetchMenuAndResource,
132
132
  fetchRecord,
133
133
  record,
134
- resourceColumns,
135
134
  fetchResourceFull,
136
135
  resourceColumnsError,
137
136
  resourceOptions,
@@ -46,7 +46,7 @@
46
46
  <ResourceForm
47
47
  v-else
48
48
  :record="initalValues"
49
- :resourceColumns="coreStore.resourceColumns"
49
+ :resource="coreStore.resource"
50
50
  @update:record="onUpdateRecord"
51
51
  @update:isValid="isValid = $event"
52
52
  :validating="validating"
@@ -95,7 +95,10 @@ let createComponentsPerColumn = {};
95
95
  const coreStore = useCoreStore();
96
96
 
97
97
  const initalValues = computed(() => {
98
- return route.query || {};
98
+ if (!route.query.values) {
99
+ return {};
100
+ }
101
+ return JSON.parse(decodeURIComponent(route.query.values));
99
102
  });
100
103
 
101
104
  async function onUpdateRecord(newRecord) {
@@ -108,7 +111,7 @@ onMounted(async () => {
108
111
  await coreStore.fetchResourceFull({
109
112
  resourceId: route.params.resourceId
110
113
  });
111
- createComponentsPerColumn = coreStore.resourceColumns.reduce((acc, column) => {
114
+ createComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
112
115
  if (column.components?.create) {
113
116
  acc[column.name] = getCustomComponent(column.components.create);
114
117
  }
@@ -135,11 +138,17 @@ async function saveRecord() {
135
138
  },
136
139
  });
137
140
  saving.value = false;
138
- router.push({ name: 'resource-show', params: {
139
- resourceId: route.params.resourceId,
140
- primaryKey: response.newRecordId
141
-
142
- } });
141
+ if (route.query.returnTo) {
142
+ router.push(route.query.returnTo);
143
+ } else {
144
+ router.push({
145
+ name: 'resource-show',
146
+ params: {
147
+ resourceId: route.params.resourceId,
148
+ primaryKey: response.newRecordId
149
+ }
150
+ });
151
+ }
143
152
  }
144
153
 
145
154
 
@@ -95,10 +95,10 @@ async function onUpdateRecord(newRecord) {
95
95
 
96
96
  const editableRecord = computed(() => {
97
97
  const newRecord = { ...coreStore.record };
98
- if (!coreStore.resourceColumns) {
98
+ if (!coreStore.resource) {
99
99
  return {};
100
100
  }
101
- coreStore.resourceColumns.forEach(column => {
101
+ coreStore.resource.columns.forEach(column => {
102
102
  if (column.foreignResource) {
103
103
  newRecord[column.name] = newRecord[column.name]?.pk
104
104
  }
@@ -119,7 +119,7 @@ onMounted(async () => {
119
119
  });
120
120
  checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'edit');
121
121
 
122
- editComponentsPerColumn = coreStore.resourceColumns.reduce((acc, column) => {
122
+ editComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
123
123
  if (column.components?.edit) {
124
124
  acc[column.name] = getCustomComponent(column.components.edit);
125
125
  }
@@ -2,7 +2,7 @@
2
2
  <div class="relative">
3
3
  <Teleport to="body">
4
4
  <Filters
5
- :columns="coreStore.resourceColumns"
5
+ :columns="coreStore.resource?.columns"
6
6
  :columnsMinMax="columnsMinMax" :show="filtersShow"
7
7
  @hide="filtersShow = false"
8
8
  />
@@ -159,6 +159,8 @@ watch([page], async () => {
159
159
 
160
160
  watch(()=>filtersStore.filters, async () => {
161
161
  page.value = 1;
162
+ checkboxes.value = [];
163
+
162
164
  await getList();
163
165
  }, {deep: true});
164
166
 
@@ -183,7 +185,7 @@ async function getList() {
183
185
  });
184
186
 
185
187
  rows.value = data.data?.map(row => {
186
- row._primaryKeyValue = row[coreStore.resourceColumns.find(c => c.primaryKey).name];
188
+ row._primaryKeyValue = row[coreStore.resource.columns.find(c => c.primaryKey).name];
187
189
  return row;
188
190
  });
189
191
  totalRows.value = data.total;
@@ -58,7 +58,7 @@
58
58
  </tr>
59
59
  </thead>
60
60
  <tbody>
61
- <tr v-for="column in coreStore.resourceColumns?.filter(c => c.showIn.includes('show'))" :key="column.name"
61
+ <tr v-for="column in coreStore.resource?.columns.filter(c => c.showIn.includes('show'))" :key="column.name"
62
62
  class="bg-form-view-bg odd:dark:bg-gray-900 even:dark:bg-gray-800 border-b dark:border-gray-700"
63
63
  >
64
64
  <component
@@ -145,7 +145,7 @@ onMounted(async () => {
145
145
  });
146
146
  checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'show');
147
147
 
148
- showComponentsPerColumn = coreStore.resourceColumns.reduce((acc, column) => {
148
+ showComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
149
149
  if (column.components?.show) {
150
150
  acc[column.name] = getCustomComponent(column.components.show);
151
151
  }