-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
119 lines (98 loc) · 3.59 KB
/
Copy pathindex.ts
File metadata and controls
119 lines (98 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { AdminForthPlugin, AdminForthDataTypes } from "adminforth";
import type { IAdminForth, AdminForthResource } from "adminforth";
import type { PluginOptions } from './types.js';
import Validator from 'jsonschema';
export default class JsonFormPlugin extends AdminForthPlugin {
options: PluginOptions;
resourceConfig!: AdminForthResource;
constructor(options: PluginOptions) {
super(options, import.meta.url);
this.options = options;
}
instanceUniqueRepresentation(pluginOptions: any): string {
return pluginOptions.fieldName;
}
validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
}
async modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
super.modifyResourceConfig(adminforth, resourceConfig);
this.resourceConfig = resourceConfig;
if (!this.options.fieldName) {
throw new Error(`[JsonFormPlugin] "fieldName" option is required`);
}
if (!this.options.schema || typeof this.options.schema !== 'object') {
throw new Error(`[JsonFormPlugin] "schema" option is required and must be a JSON Schema object`);
}
const column = resourceConfig.columns.find(c => c.name === this.options.fieldName);
if (!column) {
throw new Error(
`[JsonFormPlugin] Column "${this.options.fieldName}" not found in resource "${resourceConfig.label}"`
);
}
if (column.type !== AdminForthDataTypes.JSON) {
throw new Error(
`[JsonFormPlugin] Column "${this.options.fieldName}" must be of type "json", but got "${column.type}". ` +
`The json-form plugin only works with JSON columns.`
);
}
if (!column.components) {
column.components = {};
}
const meta = {
pluginInstanceId: this.pluginInstanceId,
columnName: this.options.fieldName,
schema: this.options.schema,
};
const formComponent = {
file: this.componentPath('JsonForm.vue'),
meta,
};
column.components.create = formComponent;
column.components.edit = formComponent;
if (!resourceConfig.hooks) {
resourceConfig.hooks = {};
}
if (!resourceConfig.hooks.create) {
resourceConfig.hooks.create = {};
}
if (!resourceConfig.hooks.edit) {
resourceConfig.hooks.edit = {};
}
const pushHook = (hooks: { beforeSave?: any }, fn: any) => {
if (Array.isArray(hooks.beforeSave)) {
hooks.beforeSave.push(fn);
} else if (hooks.beforeSave) {
hooks.beforeSave = [hooks.beforeSave, fn];
} else {
hooks.beforeSave = [fn];
}
};
pushHook(resourceConfig.hooks.create, async ({ record }: { record: any }) => {
return this.validateRecord(record);
});
pushHook(resourceConfig.hooks.edit, async ({ updates }: { updates: any }) => {
if (!(this.options.fieldName in updates)) {
return { ok: true };
}
return this.validateRecord(updates);
});
}
validateRecord(record: any): { ok: boolean; error?: string } {
const value = record?.[this.options.fieldName];
if (value === undefined || value === null) {
return { ok: true };
}
const validator = new Validator.Validator();
const result = validator.validate(value, this.options.schema, { nestedErrors: true });
if (!result.valid) {
const message = result.errors
.map((e) => `${e.property.replace(/^instance/, this.options.fieldName)} ${e.message}`)
.join('; ');
return {
ok: false,
error: `[JsonForm] Invalid value for "${this.options.fieldName}": ${message}`,
};
}
return { ok: true };
}
}