Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save derrickmehaffy/10d7d6598358a3f155ed200b6d2bb466 to your computer and use it in GitHub Desktop.

Select an option

Save derrickmehaffy/10d7d6598358a3f155ed200b6d2bb466 to your computer and use it in GitHub Desktop.
Hacky way to use custom plugins in admin for Strapi beta from soupette
// First make sure your plugin has the following
1 - A pluginId file path my-plugin/admin/src/pluginId.js
```
import pluginPkg from '../../package.json';
const pluginId = pluginPkg.name.replace(/^strapi-plugin-/i, '');
export default pluginId;
```
2 - An Initializer container filer containers/Initializer
```
class Initializer extends React.PureComponent {
// eslint-disable-line react/prefer-stateless-function
componentDidMount() {
// Emit the event 'pluginReady'
this.props.updatePlugin(pluginId, 'isReady', true);
}
render() {
return null;
}
}
```
3- An index.js file src/index.js
```
import React from 'react';
import pluginPkg from '../../package.json';
import pluginId from './pluginId';
import App from './containers/Main';
import Initializer from './containers/Initializer';
// import lifecycles from './lifecycles';
import trads from './translations';
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
function Comp(props) {
return <App {...props} />;
}
const plugin = {
blockerComponent: null,
blockerComponentProps: {},
description: pluginDescription,
icon: pluginPkg.strapi.icon,
id: pluginId,
initializer: Initializer,
injectedComponents: [],
isReady: false,
layout: null,
lifecycles: () => {},
leftMenuLinks: [],
leftMenuSections: [],
mainComponent: Comp,
name: pluginPkg.strapi.name,
preventComponentRendering: false,
suffixUrl: '/ctm-configurations/models',
trads,
};
export default plugin;
```
// Once you have met the requirements
1- Create the admin folder
path: my-app/admin
2- Create an app.js file
path: my-app/admin/src/app.js
3 - Apply the following modifications
```
// /**
// *
// * app.js
// *
// * Entry point of the application
// */
import '@babel/polyfill';
import 'sanitize.css/sanitize.css';
// Third party css library needed
// Currently unable to bundle them
import 'react-select/dist/react-select.css';
import 'react-datetime/css/react-datetime.css';
import './styles/main.scss';
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import { merge, set } from 'lodash';
import {
freezeApp,
pluginLoaded,
unfreezeApp,
updatePlugin,
getAppPluginsSucceeded,
} from './containers/App/actions';
import { showNotification } from './containers/NotificationProvider/actions';
import basename from './utils/basename';
import injectReducer from './utils/injectReducer';
import injectSaga from './utils/injectSaga';
// Import root component
import App from './containers/App';
// Import Language provider
import LanguageProvider from './containers/LanguageProvider';
import configureStore from './configureStore';
// Import i18n messages
import { translationMessages, languages } from './i18n';
// Create redux store with history
import history from './utils/history';
import plugins from './plugins';
const customPlugins = ['my-plugin1', 'my-plugin2'];
customPlugins.forEach(plugin => {
set(plugins, plugin, require(`../../../plugins/${plugin}/admin/src`).default);
});
const initialState = {};
const store = configureStore(initialState, history);
const { dispatch } = store;
const MOUNT_NODE =
document.getElementById('app') || document.createElement('div');
dispatch(getAppPluginsSucceeded(Object.keys(plugins)));
Object.keys(plugins).forEach(plugin => {
const currentPlugin = plugins[plugin];
const pluginTradsPrefixed = languages.reduce((acc, lang) => {
const currentLocale = currentPlugin.trads[lang];
if (currentLocale) {
const localeprefixedWithPluginId = Object.keys(currentLocale).reduce(
(acc2, current) => {
acc2[`${plugins[plugin].id}.${current}`] = currentLocale[current];
return acc2;
},
{},
);
acc[lang] = localeprefixedWithPluginId;
}
return acc;
}, {});
try {
merge(translationMessages, pluginTradsPrefixed);
dispatch(pluginLoaded(currentPlugin));
} catch (err) {
console.log({ err });
}
});
// TODO
const remoteURL = (() => {
// Relative URL (ex: /dashboard)
if (REMOTE_URL[0] === '/') {
return (window.location.origin + REMOTE_URL).replace(/\/$/, '');
}
return REMOTE_URL.replace(/\/$/, '');
})();
const displayNotification = (message, status) => {
dispatch(showNotification(message, status));
};
const lockApp = data => {
dispatch(freezeApp(data));
};
const unlockApp = () => {
dispatch(unfreezeApp());
};
window.strapi = Object.assign(window.strapi || {}, {
node: MODE || 'host',
remoteURL,
backendURL: BACKEND_URL === '/' ? window.location.origin : BACKEND_URL,
notification: {
success: message => {
displayNotification(message, 'success');
},
warning: message => {
displayNotification(message, 'warning');
},
error: message => {
displayNotification(message, 'error');
},
info: message => {
displayNotification(message, 'info');
},
},
refresh: pluginId => ({
translationMessages: translationMessagesUpdated => {
render(merge({}, translationMessages, translationMessagesUpdated));
},
leftMenuSections: leftMenuSectionsUpdated => {
store.dispatch(
updatePlugin(pluginId, 'leftMenuSections', leftMenuSectionsUpdated),
);
},
}),
router: history,
languages,
currentLanguage:
window.localStorage.getItem('strapi-admin-language') ||
window.navigator.language ||
window.navigator.userLanguage ||
'en',
lockApp,
unlockApp,
injectReducer,
injectSaga,
store,
});
const render = messages => {
ReactDOM.render(
<Provider store={store}>
<LanguageProvider messages={messages}>
<BrowserRouter basename={basename}>
<App store={store} />
</BrowserRouter>
</LanguageProvider>
</Provider>,
MOUNT_NODE,
);
};
if (module.hot) {
module.hot.accept(['./i18n', './containers/App'], () => {
ReactDOM.unmountComponentAtNode(MOUNT_NODE);
render(translationMessages);
});
}
if (NODE_ENV !== 'test') {
// Chunked polyfill for browsers without Intl support
if (!window.Intl) {
new Promise(resolve => {
resolve(import('intl'));
})
.then(() =>
Promise.all([
import('intl/locale-data/jsonp/en.js'),
import('intl/locale-data/jsonp/de.js'),
]),
) // eslint-disable-line prettier/prettier
.then(() => render(translationMessages))
.catch(err => {
throw err;
});
} else {
render(translationMessages);
}
}
// @Pierre Burgy exporting dispatch for the notifications...
export { dispatch };
// TODO remove this for the new Cypress tests
if (window.Cypress) {
window.__store__ = Object.assign(window.__store__ || {}, { store });
}
```
// run `yarn build` and hope it's working
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment