mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 19:04:38 +00:00
Improve form api
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
3395ab5bca
commit
2d6d30643e
@ -5,13 +5,13 @@ class Plugin {
|
||||
|
||||
injectedComponents = {};
|
||||
|
||||
internals = {};
|
||||
apis = {};
|
||||
|
||||
constructor(pluginConf) {
|
||||
this.pluginId = pluginConf.id;
|
||||
this.decorators = pluginConf.decorators || {};
|
||||
this.injectedComponents = pluginConf.injectedComponents || {};
|
||||
this.internals = pluginConf.internals || {};
|
||||
this.apis = pluginConf.apis || {};
|
||||
}
|
||||
|
||||
decorate(compoName, compo) {
|
||||
|
||||
@ -22,59 +22,34 @@ const forms = {
|
||||
return attr !== options.initialData.name;
|
||||
});
|
||||
|
||||
const validators = [];
|
||||
const attributeFormExtensions = extensions.attribute[attributeType];
|
||||
|
||||
if (attributeFormExtensions) {
|
||||
attributeFormExtensions.forEach(({ validator }) => {
|
||||
if (validator) {
|
||||
validators.push(validator);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
let shape = attributeTypes[attributeType](
|
||||
let attributeShape = attributeTypes[attributeType](
|
||||
usedAttributeNames,
|
||||
reservedNames.attributes,
|
||||
alreadyTakenTargetContentTypeAttributes,
|
||||
options
|
||||
);
|
||||
|
||||
validators.forEach(validator => {
|
||||
console.log({ validator });
|
||||
shape = shape.shape(validator);
|
||||
});
|
||||
|
||||
return shape;
|
||||
return extensions.makeValidator(
|
||||
['attribute', attributeType],
|
||||
attributeShape,
|
||||
usedAttributeNames,
|
||||
reservedNames.attributes,
|
||||
alreadyTakenTargetContentTypeAttributes,
|
||||
options
|
||||
);
|
||||
} catch (err) {
|
||||
console.error('form', err);
|
||||
console.error('Error yup build schema', err);
|
||||
|
||||
return attributeTypes.default(usedAttributeNames, reservedNames.attributes);
|
||||
}
|
||||
},
|
||||
form: {
|
||||
advanced(data, type, step, actionType, attributes, extensions) {
|
||||
const attributeFormExtensions = extensions.attribute[type];
|
||||
|
||||
let customForms = [];
|
||||
|
||||
if (attributeFormExtensions) {
|
||||
attributeFormExtensions.forEach(({ form }) => {
|
||||
if (form.advanced) {
|
||||
const blocksToAdd = form.advanced(data, type, step, actionType, attributes);
|
||||
|
||||
blocksToAdd.forEach(block => {
|
||||
customForms.push(block);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const baseForm = attributesForm.advanced[type](data, step).items;
|
||||
|
||||
return { items: [...baseForm, ...customForms] };
|
||||
return extensions.makeAdvancedForm(['attribute', type], baseForm, data, step);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
@ -91,12 +66,19 @@ const forms = {
|
||||
},
|
||||
},
|
||||
contentType: {
|
||||
schema(alreadyTakenNames, isEditing, ctUid, reservedNames) {
|
||||
schema(alreadyTakenNames, isEditing, ctUid, reservedNames, extensions) {
|
||||
const takenNames = isEditing
|
||||
? alreadyTakenNames.filter(uid => uid !== ctUid)
|
||||
: alreadyTakenNames;
|
||||
|
||||
return createContentTypeSchema(takenNames, reservedNames.models);
|
||||
const contentTypeShape = createContentTypeSchema(takenNames, reservedNames.models);
|
||||
|
||||
return extensions.makeValidator(
|
||||
['contentType'],
|
||||
contentTypeShape,
|
||||
takenNames,
|
||||
reservedNames.models
|
||||
);
|
||||
},
|
||||
form: {
|
||||
base(data = {}, type, step, actionType) {
|
||||
@ -110,19 +92,8 @@ const forms = {
|
||||
},
|
||||
advanced(data, type, step, actionType, attributes, extensions) {
|
||||
const baseForm = contentTypeForm.advanced.default().items;
|
||||
const customForms = [];
|
||||
|
||||
extensions.contentType.forEach(({ form }) => {
|
||||
if (form.advanced) {
|
||||
const blocksToAdd = form.advanced(data, type, step, actionType, attributes);
|
||||
|
||||
blocksToAdd.forEach(block => {
|
||||
customForms.push(block);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return { items: [...baseForm, ...customForms] };
|
||||
return extensions.makeAdvancedForm(['contentType'], baseForm);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -75,8 +75,8 @@ const FormModal = () => {
|
||||
strapi: { getPlugin },
|
||||
} = useStrapi();
|
||||
const ctbPlugin = getPlugin(pluginId);
|
||||
const types = ctbPlugin.internals.forms.types;
|
||||
const inputsFromPlugins = ctbPlugin.internals.forms.components.inputs;
|
||||
const ctbFormsAPI = ctbPlugin.apis.forms;
|
||||
const inputsFromPlugins = ctbFormsAPI.components.inputs;
|
||||
|
||||
const query = useQuery();
|
||||
const attributeOptionRef = useRef();
|
||||
@ -404,7 +404,8 @@ const FormModal = () => {
|
||||
state.actionType === 'edit',
|
||||
// currentUID
|
||||
get(allDataSchema, [...state.pathToSchema, 'uid'], null),
|
||||
reservedNames
|
||||
reservedNames,
|
||||
ctbFormsAPI
|
||||
);
|
||||
|
||||
// Check form validity for component
|
||||
@ -415,7 +416,8 @@ const FormModal = () => {
|
||||
modifiedData.category || '',
|
||||
reservedNames,
|
||||
state.actionType === 'edit',
|
||||
get(allDataSchema, [...state.pathToSchema, 'uid'], null)
|
||||
get(allDataSchema, [...state.pathToSchema, 'uid'], null),
|
||||
ctbFormsAPI
|
||||
);
|
||||
|
||||
// Check for validity for creating a component
|
||||
@ -426,7 +428,8 @@ const FormModal = () => {
|
||||
schema = forms.component.schema(
|
||||
Object.keys(components),
|
||||
get(modifiedData, 'componentToCreate.category', ''),
|
||||
reservedNames
|
||||
reservedNames,
|
||||
ctbFormsAPI
|
||||
);
|
||||
|
||||
// Check form validity for creating a 'common attribute'
|
||||
@ -465,10 +468,10 @@ const FormModal = () => {
|
||||
reservedNames,
|
||||
alreadyTakenTargetContentTypeAttributes,
|
||||
{ modifiedData, initialData },
|
||||
types
|
||||
ctbFormsAPI
|
||||
);
|
||||
} else if (isEditingCategory) {
|
||||
schema = forms.editCategory.schema(allComponentsCategories, initialData);
|
||||
schema = forms.editCategory.schema(allComponentsCategories, initialData, ctbFormsAPI);
|
||||
} else {
|
||||
// The user is either in the addComponentToDynamicZone modal or
|
||||
// in step 1 of the add component (modalType=attribute&attributeType=component) but not creating a component
|
||||
@ -478,7 +481,8 @@ const FormModal = () => {
|
||||
schema = forms.component.schema(
|
||||
Object.keys(components),
|
||||
get(modifiedData, 'componentToCreate.category', ''),
|
||||
reservedNames
|
||||
reservedNames,
|
||||
ctbFormsAPI
|
||||
);
|
||||
} else {
|
||||
// The form is valid
|
||||
@ -1208,7 +1212,7 @@ const FormModal = () => {
|
||||
state.step,
|
||||
state.actionType,
|
||||
attributes,
|
||||
types
|
||||
ctbFormsAPI
|
||||
).items.map((row, index) => {
|
||||
return (
|
||||
<div className="row" key={index}>
|
||||
|
||||
@ -16,6 +16,7 @@ import trads from './translations';
|
||||
import pluginPermissions from './permissions';
|
||||
import pluginId from './pluginId';
|
||||
import reducers from './reducers';
|
||||
import formsAPI from './utils/formAPI';
|
||||
|
||||
export default strapi => {
|
||||
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
|
||||
@ -73,41 +74,8 @@ export default strapi => {
|
||||
],
|
||||
},
|
||||
// Internal APIs exposed by the CTB for the other plugins to use
|
||||
internals: {
|
||||
forms: {
|
||||
components: {
|
||||
inputs: {},
|
||||
add({ id, component }) {
|
||||
if (!this.inputs[id]) {
|
||||
this.inputs[id] = component;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
types: {
|
||||
attribute: {
|
||||
test: [],
|
||||
},
|
||||
contentType: [],
|
||||
component: [],
|
||||
},
|
||||
extendContentType(extension) {
|
||||
this.types.contentType.push(extension);
|
||||
},
|
||||
extendFields(fields, extension) {
|
||||
const formType = this.types.attribute;
|
||||
|
||||
fields.forEach(field => {
|
||||
let currentField = formType[field];
|
||||
|
||||
if (currentField) {
|
||||
currentField.push(extension);
|
||||
} else {
|
||||
formType[field] = [extension];
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
apis: {
|
||||
forms: formsAPI,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
import { get } from 'lodash';
|
||||
|
||||
const formsAPI = {
|
||||
components: {
|
||||
inputs: {},
|
||||
add({ id, component }) {
|
||||
if (!this.inputs[id]) {
|
||||
this.inputs[id] = component;
|
||||
}
|
||||
},
|
||||
},
|
||||
types: {
|
||||
attribute: {
|
||||
// test: {
|
||||
// validators: [],
|
||||
// form: {
|
||||
// advanced: [
|
||||
// /* cb */
|
||||
// ],
|
||||
// base: [
|
||||
// /* cb */
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
},
|
||||
contentType: {
|
||||
validators: [],
|
||||
form: {
|
||||
advanced: [],
|
||||
base: [],
|
||||
},
|
||||
},
|
||||
component: {
|
||||
validators: [],
|
||||
form: {
|
||||
advanced: [],
|
||||
base: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
extendContentType({ validator, form: { advanced, base } }) {
|
||||
const { contentType } = this.types;
|
||||
|
||||
contentType.validators.push(validator);
|
||||
contentType.form.advanced.push(advanced);
|
||||
contentType.form.base.push(base);
|
||||
},
|
||||
extendFields(fields, { validator, form: { advanced, base } }) {
|
||||
const formType = this.types.attribute;
|
||||
|
||||
fields.forEach(field => {
|
||||
if (!formType[field]) {
|
||||
formType[field] = {
|
||||
validators: [],
|
||||
form: {
|
||||
advanced: [
|
||||
/* cb */
|
||||
],
|
||||
base: [
|
||||
/* cb */
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
formType[field].validators.push(validator);
|
||||
formType[field].form.advanced.push(advanced);
|
||||
formType[field].form.base.push(base);
|
||||
}
|
||||
});
|
||||
},
|
||||
makeAdvancedForm(target, initSections, ...args) {
|
||||
const sectionsToAdd = get(this.types, [...target, 'form', 'advanced'], []).reduce(
|
||||
(acc, current) => {
|
||||
const sections = current(args);
|
||||
|
||||
return [...acc, ...sections];
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return { items: [...initSections, ...sectionsToAdd] };
|
||||
},
|
||||
makeValidator(target, initShape, ...args) {
|
||||
const validators = get(this.types, [...target, 'validators'], []).reduce((acc, current) => {
|
||||
const validator = current(args);
|
||||
|
||||
return { ...acc, ...validator };
|
||||
}, {});
|
||||
|
||||
return initShape.shape(validators);
|
||||
},
|
||||
};
|
||||
|
||||
export default formsAPI;
|
||||
@ -45,15 +45,15 @@ export default strapi => {
|
||||
trads,
|
||||
boot(app) {
|
||||
const ctbPlugin = app.getPlugin('content-type-builder');
|
||||
const ctbForms = ctbPlugin.internals.forms;
|
||||
|
||||
if (ctbPlugin) {
|
||||
ctbForms.components.add({ id: 'localesPicker', component: () => 'locale picker' });
|
||||
const ctbFormsAPI = ctbPlugin.apis.forms;
|
||||
ctbFormsAPI.components.add({ id: 'localesPicker', component: () => 'locale picker' });
|
||||
|
||||
ctbForms.extendContentType({
|
||||
validator: {
|
||||
i18n: yup.bool().required(),
|
||||
},
|
||||
ctbFormsAPI.extendContentType({
|
||||
validator: () => ({
|
||||
i18n: yup.bool(),
|
||||
}),
|
||||
form: {
|
||||
advanced() {
|
||||
return [
|
||||
@ -70,10 +70,10 @@ export default strapi => {
|
||||
},
|
||||
});
|
||||
|
||||
ctbForms.extendFields(['text', 'string'], {
|
||||
validator: {
|
||||
ctbFormsAPI.extendFields(['text', 'string'], {
|
||||
validator: () => ({
|
||||
localize: yup.bool(),
|
||||
},
|
||||
}),
|
||||
form: {
|
||||
advanced(args) {
|
||||
console.log('advanced', args);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user