adminforth 1.0.39 → 1.0.41

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.
@@ -126,12 +126,23 @@ class MongoConnector {
126
126
 
127
127
  for (const filter of filters) {
128
128
  if (!this.OperatorsMap[filter.operator]) {
129
- throw new Error(`Operator ${filter.operator} is not allowed`);
129
+ throw new Error(`Operator ${filter.operator} is not allowed`);
130
130
  }
131
131
 
132
- if (!resource.dataSourceColumns.some((col) => col.name == filter.field)) {
132
+ if (!resource.dataSourceColumns.some((col) => col.name === filter.field)) {
133
133
  throw new Error(`Field ${filter.field} is not in resource ${resource.resourceId}. Available fields: ${resource.dataSourceColumns.map((col) => col.name).join(', ')}`);
134
134
  }
135
+
136
+ if (filter.operator === AdminForthFilterOperators.IN || filter.operator === AdminForthFilterOperators.NIN) {
137
+ if (!Array.isArray(filter.value)) {
138
+ throw new Error(`Value for operator ${filter.operator} should be an array`);
139
+ }
140
+ }
141
+
142
+ if (filter.operator === AdminForthFilterOperators.IN && filter.value.length === 0) {
143
+ // nonsense
144
+ return { data: [], total: 0 };
145
+ }
135
146
  }
136
147
 
137
148
  const collection = this.db.db().collection(tableName);
@@ -134,9 +134,18 @@ class MongoConnector {
134
134
  if (!this.OperatorsMap[filter.operator]) {
135
135
  throw new Error(`Operator ${filter.operator} is not allowed`);
136
136
  }
137
- if (!resource.dataSourceColumns.some((col) => col.name == filter.field)) {
137
+ if (!resource.dataSourceColumns.some((col) => col.name === filter.field)) {
138
138
  throw new Error(`Field ${filter.field} is not in resource ${resource.resourceId}. Available fields: ${resource.dataSourceColumns.map((col) => col.name).join(', ')}`);
139
139
  }
140
+ if (filter.operator === AdminForthFilterOperators.IN || filter.operator === AdminForthFilterOperators.NIN) {
141
+ if (!Array.isArray(filter.value)) {
142
+ throw new Error(`Value for operator ${filter.operator} should be an array`);
143
+ }
144
+ }
145
+ if (filter.operator === AdminForthFilterOperators.IN && filter.value.length === 0) {
146
+ // nonsense
147
+ return { data: [], total: 0 };
148
+ }
140
149
  }
141
150
  const collection = this.db.db().collection(tableName);
142
151
  const query = {};
package/dist/index.js CHANGED
@@ -221,6 +221,20 @@ class AdminForth {
221
221
  if (errors.length > 0) {
222
222
  throw new Error(`Invalid AdminForth config: ${errors.join(', ')}`);
223
223
  }
224
+ // check is all custom components files exists
225
+ for (const resource of this.config.resources) {
226
+ for (const column of resource.columns) {
227
+ if (column.component) {
228
+ for (const [key, value] of Object.entries(column.component)) {
229
+ // console.log(`${key}: ${value}`);
230
+ const path = value.replace('@@', this.config.customization.customComponentsDir);
231
+ if (!fs.existsSync(path)) {
232
+ throw new Error(`Component file ${path} does not exist`);
233
+ }
234
+ }
235
+ }
236
+ }
237
+ }
224
238
  }
225
239
  postProcessAfterDiscover(resource) {
226
240
  resource.columns.forEach((column) => {
@@ -675,7 +689,6 @@ class AdminForth {
675
689
  path: '/update_record',
676
690
  handler: (_7) => __awaiter(this, [_7], void 0, function* ({ body, adminUser }) {
677
691
  var _8, _9, _10, _11, _12, _13, _14, _15;
678
- console.log('update_record', body);
679
692
  const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
680
693
  if (!resource) {
681
694
  return { error: `Resource '${body['resourceId']}' not found` };
@@ -97,6 +97,10 @@ onMounted(() => {
97
97
  updateFromProps();
98
98
  });
99
99
 
100
+ watch(() => props.options, () => {
101
+ updateFromProps();
102
+ });
103
+
100
104
  addClickListener();
101
105
 
102
106
  });
@@ -44,6 +44,7 @@
44
44
  </div>
45
45
  </td>
46
46
  <td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap relative">
47
+
47
48
  <Dropdown
48
49
  single
49
50
  v-if="column.foreignResource"
@@ -23,7 +23,7 @@
23
23
 
24
24
  <ResourceForm
25
25
  v-else
26
- :record="coreStore.record"
26
+ :record="editableRecord"
27
27
  :resourceColumns="coreStore.resourceColumns"
28
28
  @update:record="onUpdateRecord"
29
29
  @update:isValid="isValid = $event"
@@ -43,7 +43,7 @@ import SingleSkeletLoader from '@/components/SingleSkeletLoader.vue';
43
43
  import { useCoreStore } from '@/stores/core';
44
44
  import { callAdminForthApi } from '@/utils';
45
45
  import { IconFloppyDiskSolid } from '@iconify-prerendered/vue-flowbite';
46
- import { defineAsyncComponent, onMounted, ref } from 'vue';
46
+ import { defineAsyncComponent, onMounted, ref, computed } from 'vue';
47
47
  import { useRoute, useRouter } from 'vue-router';
48
48
 
49
49
  const coreStore = useCoreStore();
@@ -65,6 +65,18 @@ async function onUpdateRecord(newRecord) {
65
65
  record.value = newRecord;
66
66
  }
67
67
 
68
+ const editableRecord = computed(() => {
69
+ const newRecord = { ...coreStore.record };
70
+ if (!coreStore.resourceColumns) {
71
+ return {};
72
+ }
73
+ coreStore.resourceColumns.forEach(column => {
74
+ if (column.foreignResource) {
75
+ newRecord[column.name] = newRecord[column.name]?.pk
76
+ }
77
+ });
78
+ return newRecord;
79
+ })
68
80
 
69
81
  onMounted(async () => {
70
82
  loading.value = true;
package/index.ts CHANGED
@@ -267,6 +267,21 @@ class AdminForth {
267
267
  if (errors.length > 0) {
268
268
  throw new Error(`Invalid AdminForth config: ${errors.join(', ')}`);
269
269
  }
270
+
271
+ // check is all custom components files exists
272
+ for (const resource of this.config.resources) {
273
+ for (const column of resource.columns) {
274
+ if (column.component) {
275
+ for (const [key, value] of Object.entries(column.component)) {
276
+ // console.log(`${key}: ${value}`);
277
+ const path = value.replace('@@', this.config.customization.customComponentsDir);
278
+ if (!fs.existsSync(path)) {
279
+ throw new Error(`Component file ${path} does not exist`);
280
+ }
281
+ }
282
+ }
283
+ }
284
+ }
270
285
  }
271
286
 
272
287
  postProcessAfterDiscover(resource) {
@@ -754,7 +769,6 @@ class AdminForth {
754
769
  method: 'POST',
755
770
  path: '/update_record',
756
771
  handler: async ({ body, adminUser }) => {
757
- console.log('update_record', body);
758
772
  const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
759
773
  if (!resource) {
760
774
  return { error: `Resource '${body['resourceId']}' not found` };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.0.39",
3
+ "version": "1.0.41",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -97,6 +97,10 @@ onMounted(() => {
97
97
  updateFromProps();
98
98
  });
99
99
 
100
+ watch(() => props.options, () => {
101
+ updateFromProps();
102
+ });
103
+
100
104
  addClickListener();
101
105
 
102
106
  });
@@ -44,6 +44,7 @@
44
44
  </div>
45
45
  </td>
46
46
  <td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap relative">
47
+
47
48
  <Dropdown
48
49
  single
49
50
  v-if="column.foreignResource"
@@ -23,7 +23,7 @@
23
23
 
24
24
  <ResourceForm
25
25
  v-else
26
- :record="coreStore.record"
26
+ :record="editableRecord"
27
27
  :resourceColumns="coreStore.resourceColumns"
28
28
  @update:record="onUpdateRecord"
29
29
  @update:isValid="isValid = $event"
@@ -43,7 +43,7 @@ import SingleSkeletLoader from '@/components/SingleSkeletLoader.vue';
43
43
  import { useCoreStore } from '@/stores/core';
44
44
  import { callAdminForthApi } from '@/utils';
45
45
  import { IconFloppyDiskSolid } from '@iconify-prerendered/vue-flowbite';
46
- import { defineAsyncComponent, onMounted, ref } from 'vue';
46
+ import { defineAsyncComponent, onMounted, ref, computed } from 'vue';
47
47
  import { useRoute, useRouter } from 'vue-router';
48
48
 
49
49
  const coreStore = useCoreStore();
@@ -65,6 +65,18 @@ async function onUpdateRecord(newRecord) {
65
65
  record.value = newRecord;
66
66
  }
67
67
 
68
+ const editableRecord = computed(() => {
69
+ const newRecord = { ...coreStore.record };
70
+ if (!coreStore.resourceColumns) {
71
+ return {};
72
+ }
73
+ coreStore.resourceColumns.forEach(column => {
74
+ if (column.foreignResource) {
75
+ newRecord[column.name] = newRecord[column.name]?.pk
76
+ }
77
+ });
78
+ return newRecord;
79
+ })
68
80
 
69
81
  onMounted(async () => {
70
82
  loading.value = true;