mirror of
https://github.com/strapi/strapi.git
synced 2025-11-09 22:59:14 +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 = {};
|
injectedComponents = {};
|
||||||
|
|
||||||
internals = {};
|
apis = {};
|
||||||
|
|
||||||
constructor(pluginConf) {
|
constructor(pluginConf) {
|
||||||
this.pluginId = pluginConf.id;
|
this.pluginId = pluginConf.id;
|
||||||
this.decorators = pluginConf.decorators || {};
|
this.decorators = pluginConf.decorators || {};
|
||||||
this.injectedComponents = pluginConf.injectedComponents || {};
|
this.injectedComponents = pluginConf.injectedComponents || {};
|
||||||
this.internals = pluginConf.internals || {};
|
this.apis = pluginConf.apis || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
decorate(compoName, compo) {
|
decorate(compoName, compo) {
|
||||||
|
|||||||
@ -22,59 +22,34 @@ const forms = {
|
|||||||
return attr !== options.initialData.name;
|
return attr !== options.initialData.name;
|
||||||
});
|
});
|
||||||
|
|
||||||
const validators = [];
|
|
||||||
const attributeFormExtensions = extensions.attribute[attributeType];
|
|
||||||
|
|
||||||
if (attributeFormExtensions) {
|
|
||||||
attributeFormExtensions.forEach(({ validator }) => {
|
|
||||||
if (validator) {
|
|
||||||
validators.push(validator);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let shape = attributeTypes[attributeType](
|
let attributeShape = attributeTypes[attributeType](
|
||||||
usedAttributeNames,
|
usedAttributeNames,
|
||||||
reservedNames.attributes,
|
reservedNames.attributes,
|
||||||
alreadyTakenTargetContentTypeAttributes,
|
alreadyTakenTargetContentTypeAttributes,
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
|
|
||||||
validators.forEach(validator => {
|
return extensions.makeValidator(
|
||||||
console.log({ validator });
|
['attribute', attributeType],
|
||||||
shape = shape.shape(validator);
|
attributeShape,
|
||||||
});
|
usedAttributeNames,
|
||||||
|
reservedNames.attributes,
|
||||||
return shape;
|
alreadyTakenTargetContentTypeAttributes,
|
||||||
|
options
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('form', err);
|
console.error('Error yup build schema', err);
|
||||||
|
|
||||||
return attributeTypes.default(usedAttributeNames, reservedNames.attributes);
|
return attributeTypes.default(usedAttributeNames, reservedNames.attributes);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
advanced(data, type, step, actionType, attributes, extensions) {
|
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 {
|
try {
|
||||||
const baseForm = attributesForm.advanced[type](data, step).items;
|
const baseForm = attributesForm.advanced[type](data, step).items;
|
||||||
|
|
||||||
return { items: [...baseForm, ...customForms] };
|
return extensions.makeAdvancedForm(['attribute', type], baseForm, data, step);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
@ -91,12 +66,19 @@ const forms = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
contentType: {
|
contentType: {
|
||||||
schema(alreadyTakenNames, isEditing, ctUid, reservedNames) {
|
schema(alreadyTakenNames, isEditing, ctUid, reservedNames, extensions) {
|
||||||
const takenNames = isEditing
|
const takenNames = isEditing
|
||||||
? alreadyTakenNames.filter(uid => uid !== ctUid)
|
? alreadyTakenNames.filter(uid => uid !== ctUid)
|
||||||
: alreadyTakenNames;
|
: alreadyTakenNames;
|
||||||
|
|
||||||
return createContentTypeSchema(takenNames, reservedNames.models);
|
const contentTypeShape = createContentTypeSchema(takenNames, reservedNames.models);
|
||||||
|
|
||||||
|
return extensions.makeValidator(
|
||||||
|
['contentType'],
|
||||||
|
contentTypeShape,
|
||||||
|
takenNames,
|
||||||
|
reservedNames.models
|
||||||
|
);
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
base(data = {}, type, step, actionType) {
|
base(data = {}, type, step, actionType) {
|
||||||
@ -110,19 +92,8 @@ const forms = {
|
|||||||
},
|
},
|
||||||
advanced(data, type, step, actionType, attributes, extensions) {
|
advanced(data, type, step, actionType, attributes, extensions) {
|
||||||
const baseForm = contentTypeForm.advanced.default().items;
|
const baseForm = contentTypeForm.advanced.default().items;
|
||||||
const customForms = [];
|
|
||||||
|
|
||||||
extensions.contentType.forEach(({ form }) => {
|
return extensions.makeAdvancedForm(['contentType'], baseForm);
|
||||||
if (form.advanced) {
|
|
||||||
const blocksToAdd = form.advanced(data, type, step, actionType, attributes);
|
|
||||||
|
|
||||||
blocksToAdd.forEach(block => {
|
|
||||||
customForms.push(block);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return { items: [...baseForm, ...customForms] };
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -75,8 +75,8 @@ const FormModal = () => {
|
|||||||
strapi: { getPlugin },
|
strapi: { getPlugin },
|
||||||
} = useStrapi();
|
} = useStrapi();
|
||||||
const ctbPlugin = getPlugin(pluginId);
|
const ctbPlugin = getPlugin(pluginId);
|
||||||
const types = ctbPlugin.internals.forms.types;
|
const ctbFormsAPI = ctbPlugin.apis.forms;
|
||||||
const inputsFromPlugins = ctbPlugin.internals.forms.components.inputs;
|
const inputsFromPlugins = ctbFormsAPI.components.inputs;
|
||||||
|
|
||||||
const query = useQuery();
|
const query = useQuery();
|
||||||
const attributeOptionRef = useRef();
|
const attributeOptionRef = useRef();
|
||||||
@ -404,7 +404,8 @@ const FormModal = () => {
|
|||||||
state.actionType === 'edit',
|
state.actionType === 'edit',
|
||||||
// currentUID
|
// currentUID
|
||||||
get(allDataSchema, [...state.pathToSchema, 'uid'], null),
|
get(allDataSchema, [...state.pathToSchema, 'uid'], null),
|
||||||
reservedNames
|
reservedNames,
|
||||||
|
ctbFormsAPI
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check form validity for component
|
// Check form validity for component
|
||||||
@ -415,7 +416,8 @@ const FormModal = () => {
|
|||||||
modifiedData.category || '',
|
modifiedData.category || '',
|
||||||
reservedNames,
|
reservedNames,
|
||||||
state.actionType === 'edit',
|
state.actionType === 'edit',
|
||||||
get(allDataSchema, [...state.pathToSchema, 'uid'], null)
|
get(allDataSchema, [...state.pathToSchema, 'uid'], null),
|
||||||
|
ctbFormsAPI
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check for validity for creating a component
|
// Check for validity for creating a component
|
||||||
@ -426,7 +428,8 @@ const FormModal = () => {
|
|||||||
schema = forms.component.schema(
|
schema = forms.component.schema(
|
||||||
Object.keys(components),
|
Object.keys(components),
|
||||||
get(modifiedData, 'componentToCreate.category', ''),
|
get(modifiedData, 'componentToCreate.category', ''),
|
||||||
reservedNames
|
reservedNames,
|
||||||
|
ctbFormsAPI
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check form validity for creating a 'common attribute'
|
// Check form validity for creating a 'common attribute'
|
||||||
@ -465,10 +468,10 @@ const FormModal = () => {
|
|||||||
reservedNames,
|
reservedNames,
|
||||||
alreadyTakenTargetContentTypeAttributes,
|
alreadyTakenTargetContentTypeAttributes,
|
||||||
{ modifiedData, initialData },
|
{ modifiedData, initialData },
|
||||||
types
|
ctbFormsAPI
|
||||||
);
|
);
|
||||||
} else if (isEditingCategory) {
|
} else if (isEditingCategory) {
|
||||||
schema = forms.editCategory.schema(allComponentsCategories, initialData);
|
schema = forms.editCategory.schema(allComponentsCategories, initialData, ctbFormsAPI);
|
||||||
} else {
|
} else {
|
||||||
// The user is either in the addComponentToDynamicZone modal or
|
// 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
|
// 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(
|
schema = forms.component.schema(
|
||||||
Object.keys(components),
|
Object.keys(components),
|
||||||
get(modifiedData, 'componentToCreate.category', ''),
|
get(modifiedData, 'componentToCreate.category', ''),
|
||||||
reservedNames
|
reservedNames,
|
||||||
|
ctbFormsAPI
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// The form is valid
|
// The form is valid
|
||||||
@ -1208,7 +1212,7 @@ const FormModal = () => {
|
|||||||
state.step,
|
state.step,
|
||||||
state.actionType,
|
state.actionType,
|
||||||
attributes,
|
attributes,
|
||||||
types
|
ctbFormsAPI
|
||||||
).items.map((row, index) => {
|
).items.map((row, index) => {
|
||||||
return (
|
return (
|
||||||
<div className="row" key={index}>
|
<div className="row" key={index}>
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import trads from './translations';
|
|||||||
import pluginPermissions from './permissions';
|
import pluginPermissions from './permissions';
|
||||||
import pluginId from './pluginId';
|
import pluginId from './pluginId';
|
||||||
import reducers from './reducers';
|
import reducers from './reducers';
|
||||||
|
import formsAPI from './utils/formAPI';
|
||||||
|
|
||||||
export default strapi => {
|
export default strapi => {
|
||||||
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
|
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
|
// Internal APIs exposed by the CTB for the other plugins to use
|
||||||
internals: {
|
apis: {
|
||||||
forms: {
|
forms: formsAPI,
|
||||||
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];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
trads,
|
||||||
boot(app) {
|
boot(app) {
|
||||||
const ctbPlugin = app.getPlugin('content-type-builder');
|
const ctbPlugin = app.getPlugin('content-type-builder');
|
||||||
const ctbForms = ctbPlugin.internals.forms;
|
|
||||||
|
|
||||||
if (ctbPlugin) {
|
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({
|
ctbFormsAPI.extendContentType({
|
||||||
validator: {
|
validator: () => ({
|
||||||
i18n: yup.bool().required(),
|
i18n: yup.bool(),
|
||||||
},
|
}),
|
||||||
form: {
|
form: {
|
||||||
advanced() {
|
advanced() {
|
||||||
return [
|
return [
|
||||||
@ -70,10 +70,10 @@ export default strapi => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ctbForms.extendFields(['text', 'string'], {
|
ctbFormsAPI.extendFields(['text', 'string'], {
|
||||||
validator: {
|
validator: () => ({
|
||||||
localize: yup.bool(),
|
localize: yup.bool(),
|
||||||
},
|
}),
|
||||||
form: {
|
form: {
|
||||||
advanced(args) {
|
advanced(args) {
|
||||||
console.log('advanced', args);
|
console.log('advanced', args);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user