diff --git a/packages/strapi-admin/admin/src/utils/Plugin.js b/packages/strapi-admin/admin/src/utils/Plugin.js index 60885276fb..0863eb692d 100644 --- a/packages/strapi-admin/admin/src/utils/Plugin.js +++ b/packages/strapi-admin/admin/src/utils/Plugin.js @@ -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) { diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/forms/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/forms/index.js index 060137a375..45b3c6e831 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/forms/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/forms/index.js @@ -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); }, }, }, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js index a98e44a580..9b1a4ee547 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js @@ -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 (
diff --git a/packages/strapi-plugin-content-type-builder/admin/src/index.js b/packages/strapi-plugin-content-type-builder/admin/src/index.js index 8ee32a7acd..1797d6ab71 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/index.js @@ -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, }, }; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/utils/formAPI.js b/packages/strapi-plugin-content-type-builder/admin/src/utils/formAPI.js new file mode 100644 index 0000000000..21a2b0aca3 --- /dev/null +++ b/packages/strapi-plugin-content-type-builder/admin/src/utils/formAPI.js @@ -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; diff --git a/packages/strapi-plugin-i18n/admin/src/index.js b/packages/strapi-plugin-i18n/admin/src/index.js index 61483aedb8..31101b3176 100644 --- a/packages/strapi-plugin-i18n/admin/src/index.js +++ b/packages/strapi-plugin-i18n/admin/src/index.js @@ -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);