mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 19:04:38 +00:00
Created PluginAPI and improve plugin registration in order to add a boot lifecycle for enabling a plugin to interact with another internal API.
Update the ctb to expose a form api. Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
2155b9842c
commit
46dc0e6a12
@ -62,6 +62,8 @@ const pluginsToLoad = [];
|
||||
|
||||
Object.keys(plugins).forEach(current => {
|
||||
const registerPlugin = plugin => {
|
||||
strapi.registerPlugin(plugin);
|
||||
|
||||
return plugin;
|
||||
};
|
||||
const currentPluginFn = plugins[current];
|
||||
@ -115,6 +117,12 @@ const { dispatch } = store;
|
||||
// Load plugins, this will be removed in the v4, temporary fix until the plugin API
|
||||
// https://plugin-api-rfc.vercel.app/plugin-api/admin.html
|
||||
pluginsToLoad.forEach(plugin => {
|
||||
const bootPlugin = plugin.boot;
|
||||
|
||||
if (bootPlugin) {
|
||||
bootPlugin(strapi);
|
||||
}
|
||||
|
||||
dispatch(pluginLoaded(plugin));
|
||||
});
|
||||
|
||||
|
||||
50
packages/strapi-admin/admin/src/utils/Plugin.js
Normal file
50
packages/strapi-admin/admin/src/utils/Plugin.js
Normal file
@ -0,0 +1,50 @@
|
||||
class Plugin {
|
||||
pluginId = null;
|
||||
|
||||
decorators = {};
|
||||
|
||||
injectedComponents = {};
|
||||
|
||||
internals = {};
|
||||
|
||||
constructor(pluginConf) {
|
||||
this.pluginId = pluginConf.id;
|
||||
this.decorators = pluginConf.decorators || {};
|
||||
this.injectedComponents = pluginConf.injectedComponents || {};
|
||||
this.internals = pluginConf.internals || {};
|
||||
}
|
||||
|
||||
decorate(compoName, compo) {
|
||||
if (this.decorators && this.decorators[compoName]) {
|
||||
this.decorators[compoName] = compo;
|
||||
}
|
||||
}
|
||||
|
||||
getDecorator(compoName) {
|
||||
if (this.decorators) {
|
||||
return this.decorators[compoName] || null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
getInjectedComponents(containerName, blockName) {
|
||||
try {
|
||||
return this.injectedComponents[containerName][blockName] || {};
|
||||
} catch (err) {
|
||||
console.error('Cannot get injected component', err);
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
injectComponent(containerName, blockName, compo) {
|
||||
try {
|
||||
this.injectedComponents[containerName][blockName].push(compo);
|
||||
} catch (err) {
|
||||
console.error('Cannot inject component', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default pluginConf => new Plugin(pluginConf);
|
||||
@ -1,6 +1,7 @@
|
||||
import ComponentApi from './ComponentApi';
|
||||
import FieldApi from './FieldApi';
|
||||
import MiddlewareApi from './MiddlewareApi';
|
||||
import PluginHandler from './Plugin';
|
||||
|
||||
class Strapi {
|
||||
componentApi = ComponentApi();
|
||||
@ -8,6 +9,18 @@ class Strapi {
|
||||
fieldApi = FieldApi();
|
||||
|
||||
middlewares = MiddlewareApi();
|
||||
|
||||
plugins = {};
|
||||
|
||||
getPlugin = pluginId => {
|
||||
return this.plugins[pluginId];
|
||||
};
|
||||
|
||||
registerPlugin = pluginConf => {
|
||||
if (pluginConf.id) {
|
||||
this.plugins[pluginConf.id] = PluginHandler(pluginConf);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default () => {
|
||||
|
||||
@ -13,7 +13,8 @@ const forms = {
|
||||
attributeType,
|
||||
reservedNames,
|
||||
alreadyTakenTargetContentTypeAttributes,
|
||||
options
|
||||
options,
|
||||
extensions
|
||||
) {
|
||||
const attributes = get(currentSchema, ['schema', 'attributes'], {});
|
||||
|
||||
@ -21,22 +22,62 @@ 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 {
|
||||
return attributeTypes[attributeType](
|
||||
let shape = attributeTypes[attributeType](
|
||||
usedAttributeNames,
|
||||
reservedNames.attributes,
|
||||
alreadyTakenTargetContentTypeAttributes,
|
||||
options
|
||||
);
|
||||
|
||||
validators.forEach(validator => {
|
||||
console.log({ validator });
|
||||
shape = shape.shape(validator);
|
||||
});
|
||||
|
||||
return shape;
|
||||
} catch (err) {
|
||||
console.error('form', err);
|
||||
|
||||
return attributeTypes.default(usedAttributeNames, reservedNames.attributes);
|
||||
}
|
||||
},
|
||||
form: {
|
||||
advanced(data, type, step) {
|
||||
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 {
|
||||
return attributesForm.advanced[type](data, step);
|
||||
const baseForm = attributesForm.advanced[type](data, step).items;
|
||||
|
||||
return { items: [...baseForm, ...customForms] };
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
return { items: [] };
|
||||
}
|
||||
},
|
||||
|
||||
@ -10,6 +10,7 @@ import {
|
||||
getYupInnerErrors,
|
||||
useGlobalContext,
|
||||
useQuery,
|
||||
useStrapi,
|
||||
InputsIndex,
|
||||
} from 'strapi-helper-plugin';
|
||||
import { Button, Text, Padded } from '@buffetjs/core';
|
||||
@ -70,6 +71,12 @@ const FormModal = () => {
|
||||
const { push } = useHistory();
|
||||
const { search } = useLocation();
|
||||
const { emitEvent, formatMessage } = useGlobalContext();
|
||||
const {
|
||||
strapi: { getPlugin },
|
||||
} = useStrapi();
|
||||
const ctbPlugin = getPlugin(pluginId);
|
||||
const types = ctbPlugin.internals.forms.types;
|
||||
|
||||
const query = useQuery();
|
||||
const attributeOptionRef = useRef();
|
||||
|
||||
@ -365,8 +372,6 @@ const FormModal = () => {
|
||||
items: [],
|
||||
}));
|
||||
|
||||
console.log({ modifiedData });
|
||||
|
||||
const headers = createHeadersArray(state);
|
||||
|
||||
const isCreatingContentType = state.modalType === 'contentType';
|
||||
@ -458,7 +463,8 @@ const FormModal = () => {
|
||||
type,
|
||||
reservedNames,
|
||||
alreadyTakenTargetContentTypeAttributes,
|
||||
{ modifiedData, initialData }
|
||||
{ modifiedData, initialData },
|
||||
types
|
||||
);
|
||||
} else if (isEditingCategory) {
|
||||
schema = forms.editCategory.schema(allComponentsCategories, initialData);
|
||||
@ -1025,6 +1031,7 @@ const FormModal = () => {
|
||||
});
|
||||
} catch (err) {
|
||||
const errors = getYupInnerErrors(err);
|
||||
console.log({ err, errors });
|
||||
|
||||
dispatch({
|
||||
type: SET_ERRORS,
|
||||
@ -1199,7 +1206,8 @@ const FormModal = () => {
|
||||
state.attributeType,
|
||||
state.step,
|
||||
state.actionType,
|
||||
attributes
|
||||
attributes,
|
||||
types
|
||||
).items.map((row, index) => {
|
||||
return (
|
||||
<div className="row" key={index}>
|
||||
|
||||
@ -72,6 +72,31 @@ export default strapi => {
|
||||
},
|
||||
],
|
||||
},
|
||||
// Internal APIs exposed by the CTB for the other plugins to use
|
||||
internals: {
|
||||
forms: {
|
||||
types: {
|
||||
attribute: {
|
||||
test: [],
|
||||
},
|
||||
contentType: {},
|
||||
component: {},
|
||||
},
|
||||
extendFields(fields, extension) {
|
||||
const formType = this.types.attribute;
|
||||
|
||||
fields.forEach(field => {
|
||||
let currentField = formType[field];
|
||||
|
||||
if (currentField) {
|
||||
currentField.push(extension);
|
||||
} else {
|
||||
formType[field] = [extension];
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return strapi.registerPlugin(plugin);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import * as yup from 'yup';
|
||||
import pluginPkg from '../../package.json';
|
||||
import middlewares from './middlewares';
|
||||
import pluginId from './pluginId';
|
||||
@ -48,6 +49,27 @@ export default strapi => {
|
||||
},
|
||||
},
|
||||
trads,
|
||||
boot(app) {
|
||||
const ctbPlugin = app.getPlugin('content-type-builder');
|
||||
|
||||
if (ctbPlugin) {
|
||||
ctbPlugin.internals.forms.extendFields(['text', 'string'], {
|
||||
validator: {
|
||||
i18n: yup.string().required(),
|
||||
},
|
||||
form: {
|
||||
advanced(args) {
|
||||
console.log('advanced', args);
|
||||
|
||||
return [[{ name: 'i18n', type: 'text', label: { id: 'i18nTest' } }]];
|
||||
},
|
||||
base(args) {
|
||||
console.log('base', args);
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return strapi.registerPlugin(plugin);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user