adminforth 1.0.41 → 1.0.43

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.
@@ -123,27 +123,6 @@ class MongoConnector {
123
123
  async getData({ resource, limit, offset, sort, filters }) {
124
124
  // const columns = resource.dataSourceColumns.filter(c=> !c.virtual).map((col) => col.name).join(', ');
125
125
  const tableName = resource.table;
126
-
127
- for (const filter of filters) {
128
- if (!this.OperatorsMap[filter.operator]) {
129
- throw new Error(`Operator ${filter.operator} is not allowed`);
130
- }
131
-
132
- if (!resource.dataSourceColumns.some((col) => col.name === filter.field)) {
133
- throw new Error(`Field ${filter.field} is not in resource ${resource.resourceId}. Available fields: ${resource.dataSourceColumns.map((col) => col.name).join(', ')}`);
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
- }
146
- }
147
126
 
148
127
  const collection = this.db.db().collection(tableName);
149
128
  const query = {};
@@ -180,14 +180,6 @@ class PostgresConnector {
180
180
  const columns = resource.dataSourceColumns.filter(c=> !c.virtual).map((col) => `"${col.name}"`).join(', ');
181
181
  const tableName = resource.table;
182
182
 
183
- for (const filter of filters) {
184
- if (!this.OperatorsMap[filter.operator]) {
185
- throw new Error(`Operator ${filter.operator} is not allowed`);
186
- }
187
- if (!resource.dataSourceColumns.some((col) => col.name == filter.field)) {
188
- throw new Error(`Field ${filter.field} is not in resource ${resource.resourceId}. Available fields: ${resource.dataSourceColumns.map((col) => col.name).join(', ')}`);
189
- }
190
- }
191
183
  let totalCounter = 1;
192
184
  const where = filters.length ? `WHERE ${filters.map((f, i) => {
193
185
  let placeholder = '$'+(totalCounter);
@@ -138,18 +138,9 @@ class SQLiteConnector {
138
138
 
139
139
 
140
140
  getData({ resource, limit, offset, sort, filters }) {
141
+ console.log('SQLITE getData', { resource, limit, offset, sort, filters });
141
142
  const columns = resource.dataSourceColumns.map((col) => col.name).join(', ');
142
143
  const tableName = resource.table;
143
-
144
- for (const filter of filters) {
145
- if (!this.OperatorsMap[filter.operator]) {
146
- throw new Error(`Operator ${filter.operator} is not allowed`);
147
- }
148
-
149
- if (!resource.dataSourceColumns.some((col) => col.name == filter.field)) {
150
- throw new Error(`Field "${filter.field}" is not in resource ${resource.resourceId}, available fields: ${resource.dataSourceColumns.map((col) => '"'+col.name+'"').join(', ')}`);
151
- }
152
- }
153
144
 
154
145
  const where = filters.length ? `WHERE ${filters.map((f, i) => {
155
146
  let placeholder = '?';
@@ -130,23 +130,6 @@ class MongoConnector {
130
130
  return __awaiter(this, arguments, void 0, function* ({ resource, limit, offset, sort, filters }) {
131
131
  // const columns = resource.dataSourceColumns.filter(c=> !c.virtual).map((col) => col.name).join(', ');
132
132
  const tableName = resource.table;
133
- for (const filter of filters) {
134
- if (!this.OperatorsMap[filter.operator]) {
135
- throw new Error(`Operator ${filter.operator} is not allowed`);
136
- }
137
- if (!resource.dataSourceColumns.some((col) => col.name === filter.field)) {
138
- throw new Error(`Field ${filter.field} is not in resource ${resource.resourceId}. Available fields: ${resource.dataSourceColumns.map((col) => col.name).join(', ')}`);
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
- }
149
- }
150
133
  const collection = this.db.db().collection(tableName);
151
134
  const query = {};
152
135
  for (const filter of filters) {
@@ -182,14 +182,6 @@ class PostgresConnector {
182
182
  return __awaiter(this, arguments, void 0, function* ({ resource, limit, offset, sort, filters }) {
183
183
  const columns = resource.dataSourceColumns.filter(c => !c.virtual).map((col) => `"${col.name}"`).join(', ');
184
184
  const tableName = resource.table;
185
- for (const filter of filters) {
186
- if (!this.OperatorsMap[filter.operator]) {
187
- throw new Error(`Operator ${filter.operator} is not allowed`);
188
- }
189
- if (!resource.dataSourceColumns.some((col) => col.name == filter.field)) {
190
- throw new Error(`Field ${filter.field} is not in resource ${resource.resourceId}. Available fields: ${resource.dataSourceColumns.map((col) => col.name).join(', ')}`);
191
- }
192
- }
193
185
  let totalCounter = 1;
194
186
  const where = filters.length ? `WHERE ${filters.map((f, i) => {
195
187
  let placeholder = '$' + (totalCounter);
@@ -148,16 +148,9 @@ class SQLiteConnector {
148
148
  return value;
149
149
  }
150
150
  getData({ resource, limit, offset, sort, filters }) {
151
+ console.log('SQLITE getData', { resource, limit, offset, sort, filters });
151
152
  const columns = resource.dataSourceColumns.map((col) => col.name).join(', ');
152
153
  const tableName = resource.table;
153
- for (const filter of filters) {
154
- if (!this.OperatorsMap[filter.operator]) {
155
- throw new Error(`Operator ${filter.operator} is not allowed`);
156
- }
157
- if (!resource.dataSourceColumns.some((col) => col.name == filter.field)) {
158
- throw new Error(`Field "${filter.field}" is not in resource ${resource.resourceId}, available fields: ${resource.dataSourceColumns.map((col) => '"' + col.name + '"').join(', ')}`);
159
- }
160
- }
161
154
  const where = filters.length ? `WHERE ${filters.map((f, i) => {
162
155
  let placeholder = '?';
163
156
  let field = f.field;
package/dist/index.js CHANGED
@@ -471,6 +471,23 @@ class AdminForth {
471
471
  }
472
472
  }
473
473
  const { limit, offset, filters, sort } = body;
474
+ for (const filter of (filters || [])) {
475
+ if (AdminForthFilterOperators[filter.operator] === undefined) {
476
+ throw new Error(`Operator '${filter.operator}' is not allowed`);
477
+ }
478
+ if (!resource.columns.some((col) => col.name === filter.field)) {
479
+ throw new Error(`Field '${filter.field}' is not in resource '${resource.resourceId}'. Available fields: ${resource.columns.map((col) => col.name).join(', ')}`);
480
+ }
481
+ if (filter.operator === AdminForthFilterOperators.IN || filter.operator === AdminForthFilterOperators.NIN) {
482
+ if (!Array.isArray(filter.value)) {
483
+ throw new Error(`Value for operator '${filter.operator}'' should be an array`);
484
+ }
485
+ }
486
+ if (filter.operator === AdminForthFilterOperators.IN && filter.value.length === 0) {
487
+ // nonsense
488
+ return { data: [], total: 0 };
489
+ }
490
+ }
474
491
  const data = yield this.connectors[resource.dataSource].getData({
475
492
  resource,
476
493
  limit,
@@ -483,6 +500,10 @@ class AdminForth {
483
500
  const targetResource = this.config.resources.find((res) => res.resourceId == col.foreignResource.resourceId);
484
501
  const targetConnector = this.connectors[targetResource.dataSource];
485
502
  const targetResourcePkField = targetResource.columns.find((col) => col.primaryKey).name;
503
+ const pksUnique = [...new Set(data.data.map((item) => item[col.name]))];
504
+ if (pksUnique.length === 0) {
505
+ return;
506
+ }
486
507
  const targetData = yield targetConnector.getData({
487
508
  resource: targetResource,
488
509
  limit: limit,
@@ -491,7 +512,7 @@ class AdminForth {
491
512
  {
492
513
  field: targetResourcePkField,
493
514
  operator: AdminForthFilterOperators.IN,
494
- value: data.data.map((item) => item[col.name]),
515
+ value: pksUnique,
495
516
  }
496
517
  ],
497
518
  sort: [],
@@ -42,10 +42,10 @@ import debounce from 'debounce'
42
42
 
43
43
  const props = defineProps({
44
44
  valueStart: {
45
- default: 0,
45
+ default: '',
46
46
  },
47
47
  valueEnd: {
48
- default: 10,
48
+ default: '',
49
49
  },
50
50
  min: {
51
51
  default: 0,
@@ -61,19 +61,18 @@ const minFormatted = computed(() => Math.floor(props.min));
61
61
  const maxFormatted = computed(() => Math.ceil(props.max));
62
62
 
63
63
  const isChanged = computed(() => {
64
- return start.value !== minFormatted.value || end.value !== maxFormatted.value;
64
+ return start.value && start.value !== minFormatted.value || end.value && end.value !== maxFormatted.value;
65
65
  });
66
66
 
67
- const start = ref(minFormatted.value);
68
- const end = ref(maxFormatted.value);
67
+ const start = ref(props.valueStart);
68
+ const end = ref(props.valueEnd);
69
69
 
70
- const sliderValue = ref([start.value, end.value]);
70
+ const sliderValue = ref([minFormatted.value, maxFormatted.value]);
71
71
 
72
72
  const updateFromSlider =
73
73
  debounce((value: [number, number]) => {
74
- console.log('start end', value)
75
- start.value = value[0];
76
- end.value = value[1];
74
+ start.value = value[0] === minFormatted.value ? '': value[0];
75
+ end.value = value[1] === maxFormatted.value ? '': value[1];
77
76
  }, 500);
78
77
 
79
78
  onMounted(() => {
@@ -90,24 +89,13 @@ onMounted(() => {
90
89
  })
91
90
 
92
91
  function updateStartFromProps() {
93
- if (props.valueStart || props.valueStart === 0) {
94
- start.value = props.valueStart ? props.valueStart : minFormatted.value;
95
- sliderValue.value = [start.value, end.value]
96
- } else {
97
- console.log(props.valueStart)
98
- start.value = minFormatted.value;
99
- sliderValue.value = [minFormatted.value, end.value];
100
- }
92
+ start.value = props.valueStart;
93
+ setSliderValues(start.value, end.value)
101
94
  }
102
95
 
103
96
  function updateEndFromProps() {
104
- if (props.valueEnd || props.valueStart === 0) {
105
- end.value = props.valueEnd ? props.valueEnd : minFormatted.value;
106
- sliderValue.value = [start.value, end.value]
107
- } else {
108
- end.value = maxFormatted.value;
109
- sliderValue.value = [start.value, maxFormatted.value];
110
- }
97
+ end.value = props.valueEnd;
98
+ setSliderValues(start.value, end.value)
111
99
  }
112
100
 
113
101
  watch(start, () => {
@@ -121,9 +109,13 @@ watch(end, () => {
121
109
  })
122
110
 
123
111
  const clear = () => {
124
- start.value = minFormatted.value;
125
- end.value = maxFormatted.value;
126
- sliderValue.value = [start.value, end.value]
112
+ start.value = ''
113
+ end.value = ''
114
+ setSliderValues('', '')
115
+ }
116
+
117
+ function setSliderValues(start, end) {
118
+ sliderValue.value = [start || minFormatted.value, end || maxFormatted.value];
127
119
  }
128
120
  </script>
129
121
 
package/index.ts CHANGED
@@ -523,6 +523,7 @@ class AdminForth {
523
523
  if (!resource) {
524
524
  return { error: `Resource ${resourceId} not found` };
525
525
  }
526
+
526
527
  if (resource.hooks?.[source]?.beforeDatasourceRequest) {
527
528
  const resp = await resource.hooks?.[source]?.beforeDatasourceRequest({ resource, query: body, adminUser });
528
529
  if (!resp || (!resp.ok && !resp.error)) {
@@ -535,6 +536,26 @@ class AdminForth {
535
536
  }
536
537
  const { limit, offset, filters, sort } = body;
537
538
 
539
+ for (const filter of (filters || [])) {
540
+ if (AdminForthFilterOperators[filter.operator] === undefined) {
541
+ throw new Error(`Operator '${filter.operator}' is not allowed`);
542
+ }
543
+
544
+ if (!resource.columns.some((col) => col.name === filter.field)) {
545
+ throw new Error(`Field '${filter.field}' is not in resource '${resource.resourceId}'. Available fields: ${resource.columns.map((col) => col.name).join(', ')}`);
546
+ }
547
+
548
+ if (filter.operator === AdminForthFilterOperators.IN || filter.operator === AdminForthFilterOperators.NIN) {
549
+ if (!Array.isArray(filter.value)) {
550
+ throw new Error(`Value for operator '${filter.operator}'' should be an array`);
551
+ }
552
+ }
553
+
554
+ if (filter.operator === AdminForthFilterOperators.IN && filter.value.length === 0) {
555
+ // nonsense
556
+ return { data: [], total: 0 };
557
+ }
558
+ }
538
559
 
539
560
  const data = await this.connectors[resource.dataSource].getData({
540
561
  resource,
@@ -549,6 +570,10 @@ class AdminForth {
549
570
  const targetResource = this.config.resources.find((res) => res.resourceId == col.foreignResource.resourceId);
550
571
  const targetConnector = this.connectors[targetResource.dataSource];
551
572
  const targetResourcePkField = targetResource.columns.find((col) => col.primaryKey).name;
573
+ const pksUnique = [...new Set(data.data.map((item) => item[col.name]))];
574
+ if (pksUnique.length === 0) {
575
+ return;
576
+ }
552
577
  const targetData = await targetConnector.getData({
553
578
  resource: targetResource,
554
579
  limit: limit,
@@ -557,7 +582,7 @@ class AdminForth {
557
582
  {
558
583
  field: targetResourcePkField,
559
584
  operator: AdminForthFilterOperators.IN,
560
- value: data.data.map((item) => item[col.name]),
585
+ value: pksUnique,
561
586
  }
562
587
  ],
563
588
  sort: [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.0.41",
3
+ "version": "1.0.43",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -42,10 +42,10 @@ import debounce from 'debounce'
42
42
 
43
43
  const props = defineProps({
44
44
  valueStart: {
45
- default: 0,
45
+ default: '',
46
46
  },
47
47
  valueEnd: {
48
- default: 10,
48
+ default: '',
49
49
  },
50
50
  min: {
51
51
  default: 0,
@@ -61,19 +61,18 @@ const minFormatted = computed(() => Math.floor(props.min));
61
61
  const maxFormatted = computed(() => Math.ceil(props.max));
62
62
 
63
63
  const isChanged = computed(() => {
64
- return start.value !== minFormatted.value || end.value !== maxFormatted.value;
64
+ return start.value && start.value !== minFormatted.value || end.value && end.value !== maxFormatted.value;
65
65
  });
66
66
 
67
- const start = ref(minFormatted.value);
68
- const end = ref(maxFormatted.value);
67
+ const start = ref(props.valueStart);
68
+ const end = ref(props.valueEnd);
69
69
 
70
- const sliderValue = ref([start.value, end.value]);
70
+ const sliderValue = ref([minFormatted.value, maxFormatted.value]);
71
71
 
72
72
  const updateFromSlider =
73
73
  debounce((value: [number, number]) => {
74
- console.log('start end', value)
75
- start.value = value[0];
76
- end.value = value[1];
74
+ start.value = value[0] === minFormatted.value ? '': value[0];
75
+ end.value = value[1] === maxFormatted.value ? '': value[1];
77
76
  }, 500);
78
77
 
79
78
  onMounted(() => {
@@ -90,24 +89,13 @@ onMounted(() => {
90
89
  })
91
90
 
92
91
  function updateStartFromProps() {
93
- if (props.valueStart || props.valueStart === 0) {
94
- start.value = props.valueStart ? props.valueStart : minFormatted.value;
95
- sliderValue.value = [start.value, end.value]
96
- } else {
97
- console.log(props.valueStart)
98
- start.value = minFormatted.value;
99
- sliderValue.value = [minFormatted.value, end.value];
100
- }
92
+ start.value = props.valueStart;
93
+ setSliderValues(start.value, end.value)
101
94
  }
102
95
 
103
96
  function updateEndFromProps() {
104
- if (props.valueEnd || props.valueStart === 0) {
105
- end.value = props.valueEnd ? props.valueEnd : minFormatted.value;
106
- sliderValue.value = [start.value, end.value]
107
- } else {
108
- end.value = maxFormatted.value;
109
- sliderValue.value = [start.value, maxFormatted.value];
110
- }
97
+ end.value = props.valueEnd;
98
+ setSliderValues(start.value, end.value)
111
99
  }
112
100
 
113
101
  watch(start, () => {
@@ -121,9 +109,13 @@ watch(end, () => {
121
109
  })
122
110
 
123
111
  const clear = () => {
124
- start.value = minFormatted.value;
125
- end.value = maxFormatted.value;
126
- sliderValue.value = [start.value, end.value]
112
+ start.value = ''
113
+ end.value = ''
114
+ setSliderValues('', '')
115
+ }
116
+
117
+ function setSliderValues(start, end) {
118
+ sliderValue.value = [start || minFormatted.value, end || maxFormatted.value];
127
119
  }
128
120
  </script>
129
121