adminforth 1.3.27 → 1.3.29
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/dataConnectors/baseConnector.ts +19 -7
- package/dataConnectors/clickhouse.ts +1 -2
- package/dataConnectors/mongo.ts +1 -1
- package/dataConnectors/postgres.ts +1 -1
- package/dataConnectors/sqlite.ts +3 -3
- package/dist/dataConnectors/baseConnector.js +16 -4
- package/dist/dataConnectors/clickhouse.js +1 -2
- package/dist/dataConnectors/mongo.js +1 -1
- package/dist/dataConnectors/postgres.js +1 -1
- package/dist/dataConnectors/sqlite.js +3 -3
- package/dist/index.js +113 -21
- package/dist/modules/codeInjector.js +8 -8
- package/dist/modules/restApi.js +23 -88
- package/index.ts +128 -24
- package/modules/codeInjector.ts +8 -8
- package/modules/operationalResource.ts +1 -1
- package/modules/restApi.ts +23 -92
- package/package.json +1 -1
- package/spa/src/components/ResourceForm.vue +14 -16
- package/spa/src/utils.ts +34 -1
- package/spa/src/views/CreateView.vue +2 -1
- package/spa/src/views/EditView.vue +3 -2
- package/types/AdminForthConfig.ts +37 -10
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
|
|
146
146
|
import CustomDatePicker from "@/components/CustomDatePicker.vue";
|
|
147
147
|
import Dropdown from '@/components/Dropdown.vue';
|
|
148
|
-
import { callAdminForthApi, getCustomComponent } from '@/utils';
|
|
148
|
+
import { applyRegexValidation, callAdminForthApi, getCustomComponent } from '@/utils';
|
|
149
149
|
import { IconExclamationCircleSolid, IconEyeSlashSolid, IconEyeSolid } from '@iconify-prerendered/vue-flowbite';
|
|
150
150
|
import { computedAsync } from '@vueuse/core';
|
|
151
151
|
import { initFlowbite } from 'flowbite';
|
|
@@ -172,7 +172,7 @@ const currentValues = ref(null);
|
|
|
172
172
|
|
|
173
173
|
const customComponentsInValidity = ref({});
|
|
174
174
|
const customComponentsEmptiness = ref({});
|
|
175
|
-
|
|
175
|
+
|
|
176
176
|
|
|
177
177
|
const columnError = (column) => {
|
|
178
178
|
const val = computed(() => {
|
|
@@ -197,7 +197,13 @@ const columnError = (column) => {
|
|
|
197
197
|
if ( column.maxLength && currentValues.value[column.name]?.length > column.maxLength ) {
|
|
198
198
|
return `This field must be shorter than ${column.maxLength} characters`;
|
|
199
199
|
}
|
|
200
|
+
|
|
200
201
|
if ( column.minLength && currentValues.value[column.name]?.length < column.minLength ) {
|
|
202
|
+
// if column.required[mode.value] is false, then we check if the field is empty
|
|
203
|
+
let needToCheckEmpty = column.required[mode.value] || currentValues.value[column.name]?.length > 0;
|
|
204
|
+
if (!needToCheckEmpty) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
201
207
|
return `This field must be longer than ${column.minLength} characters`;
|
|
202
208
|
}
|
|
203
209
|
}
|
|
@@ -212,22 +218,14 @@ const columnError = (column) => {
|
|
|
212
218
|
return `This field must be less than ${column.maxValue}`;
|
|
213
219
|
}
|
|
214
220
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
let value = currentValues.value[column.name];
|
|
221
|
-
if (value === undefined || value === null) {
|
|
222
|
-
value = '';
|
|
223
|
-
}
|
|
224
|
-
if (!regExp.test(value)) {
|
|
225
|
-
return validationArray[i].message;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
221
|
+
console.log('column.validation: ', JSON.stringify(column), 'aa', JSON.stringify(currentValues.value[column.name]));
|
|
222
|
+
if (currentValues.value[column.name] && column.validation) {
|
|
223
|
+
const error = applyRegexValidation(currentValues.value[column.name], column.validation);
|
|
224
|
+
if (error) {
|
|
225
|
+
return error;
|
|
228
226
|
}
|
|
229
|
-
|
|
230
227
|
}
|
|
228
|
+
|
|
231
229
|
return null;
|
|
232
230
|
});
|
|
233
231
|
return val.value;
|
package/spa/src/utils.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { onMounted, ref, resolveComponent } from 'vue';
|
|
2
|
-
import type {
|
|
2
|
+
import type { CoreConfig } from './spa_types/core';
|
|
3
|
+
import type { ValidationObject } from './types/AdminForthConfig';
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
import router from "./router";
|
|
5
7
|
import { useCoreStore } from './stores/core';
|
|
@@ -113,4 +115,35 @@ export function initThreeDotsDropdown() {
|
|
|
113
115
|
dd.hide();
|
|
114
116
|
}
|
|
115
117
|
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function applyRegexValidation(value: any, validation: ValidationObject[] | undefined) {
|
|
121
|
+
|
|
122
|
+
if ( validation?.length ) {
|
|
123
|
+
const validationArray = validation;
|
|
124
|
+
for (let i = 0; i < validationArray.length; i++) {
|
|
125
|
+
if (validationArray[i].regExp) {
|
|
126
|
+
let flags = '';
|
|
127
|
+
if (validationArray[i].caseSensitive) {
|
|
128
|
+
flags += 'i';
|
|
129
|
+
}
|
|
130
|
+
if (validationArray[i].multiline) {
|
|
131
|
+
flags += 'm';
|
|
132
|
+
}
|
|
133
|
+
if (validationArray[i].global) {
|
|
134
|
+
flags += 'g';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const regExp = new RegExp(validationArray[i].regExp, flags);
|
|
138
|
+
if (value === undefined || value === null) {
|
|
139
|
+
value = '';
|
|
140
|
+
}
|
|
141
|
+
let valueS = `${value}`;
|
|
142
|
+
|
|
143
|
+
if (!regExp.test(valueS)) {
|
|
144
|
+
return validationArray[i].message;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
116
149
|
}
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
Cancel
|
|
19
19
|
</button>
|
|
20
20
|
|
|
21
|
-
<button
|
|
21
|
+
<button
|
|
22
|
+
@click="saveRecord"
|
|
22
23
|
class="flex items-center py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-red-500 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50"
|
|
23
24
|
:disabled="saving || (validating && !isValid)"
|
|
24
25
|
>
|
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
Cancel
|
|
18
18
|
</button>
|
|
19
19
|
|
|
20
|
-
<button
|
|
21
|
-
|
|
20
|
+
<button
|
|
21
|
+
@click="saveRecord"
|
|
22
|
+
class="flex items-center py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-red-500 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50"
|
|
22
23
|
:disabled="saving || (validating && !isValid)"
|
|
23
24
|
>
|
|
24
25
|
<IconFloppyDiskSolid class="w-4 h-4" />
|
|
@@ -189,14 +189,12 @@ export interface IAdminForthDataSourceConnector {
|
|
|
189
189
|
createRecordOriginalValues({ resource, record }: { resource: AdminForthResource, record: any }): Promise<void>;
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
|
-
*
|
|
192
|
+
* Update record in database. newValues might have not all fields in record, but only changed ones.
|
|
193
193
|
* recordId is value of field which is marked as {@link AdminForthResourceColumn.primaryKey}
|
|
194
|
-
* newValues is array of fields which should be updated (might be not all fields in record, but only changed fields).
|
|
195
194
|
*/
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
195
|
+
updateRecordOriginalValues({ resource, recordId, newValues }: { resource: AdminForthResource; recordId: string; newValues: any; }): Promise<void>;
|
|
196
|
+
|
|
197
|
+
|
|
200
198
|
/**
|
|
201
199
|
* Used to delete record in database.
|
|
202
200
|
*/
|
|
@@ -228,12 +226,18 @@ export interface IAdminForthDataSourceConnectorBase extends IAdminForthDataSourc
|
|
|
228
226
|
adminUser: AdminUser
|
|
229
227
|
}): Promise<{ok: boolean, error?: string, createdRecord?: any}>;
|
|
230
228
|
|
|
229
|
+
updateRecord({ resource, recordId, newValues }: {
|
|
230
|
+
resource: AdminForthResource,
|
|
231
|
+
recordId: string,
|
|
232
|
+
newValues: any,
|
|
233
|
+
}): Promise<{ok: boolean, error?: string}>;
|
|
234
|
+
|
|
231
235
|
getMinMaxForColumns({ resource, columns }: { resource: AdminForthResource, columns: AdminForthResourceColumn[] }): Promise<{ [key: string]: { min: any, max: any } }>;
|
|
232
236
|
}
|
|
233
237
|
|
|
234
238
|
|
|
235
239
|
export interface IAdminForthDataSourceConnectorConstructor {
|
|
236
|
-
new ({ url }: { url: string }):
|
|
240
|
+
new ({ url }: { url: string }): IAdminForthDataSourceConnectorBase;
|
|
237
241
|
}
|
|
238
242
|
|
|
239
243
|
export interface IAdminForthAuth {
|
|
@@ -266,7 +270,15 @@ export interface IAdminForth {
|
|
|
266
270
|
|
|
267
271
|
createResourceRecord(
|
|
268
272
|
params: { resource: AdminForthResource, record: any, adminUser: AdminUser }
|
|
269
|
-
): Promise<{
|
|
273
|
+
): Promise<{ error?: string, createdRecord?: any }>;
|
|
274
|
+
|
|
275
|
+
updateResourceRecord(
|
|
276
|
+
params: { resource: AdminForthResource, recordId: any, record: any, oldRecord: any, adminUser: AdminUser }
|
|
277
|
+
): Promise<{ error?: string }>;
|
|
278
|
+
|
|
279
|
+
deleteResourceRecord(
|
|
280
|
+
params: { resource: AdminForthResource, recordId: string, adminUser: AdminUser, record: any }
|
|
281
|
+
): Promise<{ error?: string }>;
|
|
270
282
|
|
|
271
283
|
auth: IAdminForthAuth;
|
|
272
284
|
|
|
@@ -701,13 +713,13 @@ export type AfterDataSourceResponseFunction = (params: {resource: AdminForthReso
|
|
|
701
713
|
* Modify record to change how data is saved to database.
|
|
702
714
|
* Return ok: false and error: string to stop execution and show error message to user. Return ok: true to continue execution.
|
|
703
715
|
*/
|
|
704
|
-
export type BeforeSaveFunction = (params: {resource: AdminForthResource, recordId: any, adminUser: AdminUser, record: any}) => Promise<{ok: boolean, error?: string}>;
|
|
716
|
+
export type BeforeSaveFunction = (params: {resource: AdminForthResource, recordId: any, adminUser: AdminUser, record: any, oldRecord?: any}) => Promise<{ok: boolean, error?: string}>;
|
|
705
717
|
|
|
706
718
|
/**
|
|
707
719
|
* Modify record to change how data is saved to database.
|
|
708
720
|
* Return ok: false and error: string to stop execution and show error message to user. Return ok: true to continue execution.
|
|
709
721
|
*/
|
|
710
|
-
export type AfterSaveFunction = (params: {resource: AdminForthResource, recordId: any, adminUser: AdminUser, record: any}) => Promise<{ok: boolean, error?: string}>;
|
|
722
|
+
export type AfterSaveFunction = (params: {resource: AdminForthResource, recordId: any, adminUser: AdminUser, record: any, oldRecord?: any}) => Promise<{ok: boolean, error?: string}>;
|
|
711
723
|
|
|
712
724
|
/**
|
|
713
725
|
* Allow to get user data before login confirmation, will triger when user try to login.
|
|
@@ -1508,6 +1520,21 @@ export type ValidationObject = {
|
|
|
1508
1520
|
* Example: "Invalid email format"
|
|
1509
1521
|
*/
|
|
1510
1522
|
message: string,
|
|
1523
|
+
|
|
1524
|
+
/**
|
|
1525
|
+
* Whether to check case sensitivity (i flag)
|
|
1526
|
+
*/
|
|
1527
|
+
caseSensitive?: boolean,
|
|
1528
|
+
|
|
1529
|
+
/**
|
|
1530
|
+
* Whether to check Multiline strings (m flag)
|
|
1531
|
+
*/
|
|
1532
|
+
multiline?: boolean,
|
|
1533
|
+
|
|
1534
|
+
/**
|
|
1535
|
+
* Whether to check global strings (g flag)
|
|
1536
|
+
*/
|
|
1537
|
+
global?: boolean
|
|
1511
1538
|
}
|
|
1512
1539
|
|
|
1513
1540
|
export type AdminForthComponentDeclarationFull = {
|