mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 10:23:34 +00:00
Update plugin generators to add front-end files
This commit is contained in:
parent
3e7ee49154
commit
d1356fa3ea
@ -1,5 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App actions
|
||||
*
|
||||
*/
|
||||
@ -1,5 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App constants
|
||||
*
|
||||
*/
|
||||
@ -1,3 +1,44 @@
|
||||
/////////////////////////////////////////////////////
|
||||
// DISPLAY YOUR PLUGIN IN THE ADMINISTRATION PANEL //
|
||||
/////////////////////////////////////////////////////
|
||||
/*
|
||||
1. Check the installed plugin in your package.json you will need to require them manually
|
||||
2. Copy the following code in my-app/admin/src/plugins.js (don't forget to add the other installed plugins)
|
||||
|
||||
```
|
||||
const injectReducer = require('./utils/injectReducer').default;
|
||||
const useInjectReducer = require('./utils/injectReducer').useInjectReducer;
|
||||
const injectSaga = require('./utils/injectSaga').default;
|
||||
const useInjectSaga = require('./utils/injectSaga').useInjectSaga;
|
||||
const { languages } = require('./i18n');
|
||||
|
||||
window.strapi = Object.assign(window.strapi || {}, {
|
||||
node: MODE || 'host',
|
||||
env: NODE_ENV,
|
||||
backendURL: BACKEND_URL === '/' ? window.location.origin : BACKEND_URL,
|
||||
languages,
|
||||
currentLanguage:
|
||||
window.localStorage.getItem('strapi-admin-language') ||
|
||||
window.navigator.language ||
|
||||
window.navigator.userLanguage ||
|
||||
'en',
|
||||
injectReducer,
|
||||
injectSaga,
|
||||
useInjectReducer,
|
||||
useInjectSaga,
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
'strapi-plugin-users-permissions': require('../../plugins/strapi-plugin-users-permissions/admin/src')
|
||||
.default,
|
||||
// Add the other plugins here
|
||||
// ...,
|
||||
// Add your newly created plugin here (the path is different than the others)
|
||||
'my-plugin': require('../../../plugins/my-plugin/admin/src').default,
|
||||
};
|
||||
```
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* This component is the skeleton around the actual pages, and should only
|
||||
@ -6,66 +47,22 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
|
||||
import { NotFound } from 'strapi-helper-plugin';
|
||||
// Utils
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
import pluginId from '../../pluginId';
|
||||
// Containers
|
||||
import HomePage from 'containers/HomePage';
|
||||
import NotFoundPage from 'containers/NotFoundPage';
|
||||
// When you're done studying the ExamplePage container, remove the following line and delete the ExamplePage container
|
||||
import ExamplePage from 'containers/ExamplePage';
|
||||
import HomePage from '../HomePage';
|
||||
|
||||
import reducer from './reducer';
|
||||
|
||||
class App extends React.Component {
|
||||
// When you're done studying the ExamplePage container, remove the following lines and delete the ExamplePage container
|
||||
componentDidMount() {
|
||||
this.props.history.push(`/plugins/${pluginId}/example`);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={pluginId}>
|
||||
<Switch>
|
||||
<Route path={`/plugins/${pluginId}`} component={HomePage} exact />
|
||||
{/* When you're done studying the ExamplePage container, remove the following line and delete the ExamplePage container */}
|
||||
<Route path={`/plugins/${pluginId}/example`} component={ExamplePage} exact />
|
||||
<Route component={NotFoundPage} />
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
App.contextTypes = {
|
||||
plugins: PropTypes.object,
|
||||
updatePlugin: PropTypes.func,
|
||||
};
|
||||
|
||||
App.propTypes = {
|
||||
history: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators(
|
||||
{},
|
||||
dispatch,
|
||||
const App = () => {
|
||||
return (
|
||||
<div className={pluginId}>
|
||||
<Switch>
|
||||
<Route path={`/plugins/${pluginId}`} component={HomePage} exact />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const mapStateToProps = createStructuredSelector({});
|
||||
|
||||
// Wrap the component to inject dispatch and state into it
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
const withReducer = strapi.injectReducer({ key: 'global', reducer, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
withConnect,
|
||||
)(App);
|
||||
export default App;
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* App reducer
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
const initialState = fromJS({});
|
||||
|
||||
function appReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default appReducer;
|
||||
@ -1,10 +0,0 @@
|
||||
// import { createSelector } from 'reselect';
|
||||
// import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the list state domain
|
||||
*/
|
||||
|
||||
// const selectGlobalDomain = () => state => state.get(`${pluginId}_global`);
|
||||
|
||||
export {};
|
||||
@ -1,20 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* ExamplePage actions
|
||||
*
|
||||
*/
|
||||
|
||||
import { LOAD_DATA, LOADED_DATA } from './constants';
|
||||
|
||||
export function loadData() {
|
||||
return {
|
||||
type: LOAD_DATA,
|
||||
};
|
||||
}
|
||||
|
||||
export function loadedData(data) {
|
||||
return {
|
||||
type: LOADED_DATA,
|
||||
data,
|
||||
};
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* ExamplePage constants
|
||||
*
|
||||
*/
|
||||
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
export const LOAD_DATA = `${pluginId}/ExamplePage/LOAD_DATA`;
|
||||
export const LOADED_DATA = `${pluginId}/ExamplePage/LOADED_DATA`;
|
||||
@ -1,98 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* ExamplePage
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
import Button from 'components/Button';
|
||||
|
||||
import styles from './styles.scss';
|
||||
import { loadData } from './actions';
|
||||
import { makeSelectLoading, makeSelectData } from './selectors';
|
||||
import reducer from './reducer';
|
||||
import saga from './saga';
|
||||
|
||||
export class ExamplePage extends React.Component {
|
||||
generateDataBlock() {
|
||||
if (this.props.data) {
|
||||
const items = this.props.data.map((item, i) => <li key={i}>{item}</li>);
|
||||
return (
|
||||
<div>
|
||||
<p>Data:</p>
|
||||
<ul>{items}</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('Don\'t forget to delete the ExampleContainer when you\'re done studying it');
|
||||
// Generate the data block
|
||||
const dataBlock = this.generateDataBlock();
|
||||
|
||||
return (
|
||||
<div className={styles.examplePage}>
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<p>This is an example of a fake API call.</p>
|
||||
<p>Loading: {this.props.loading ? 'yes' : 'no'}.</p>
|
||||
{dataBlock}
|
||||
<Button
|
||||
label={this.props.loading ? 'Loading...' : 'Submit'}
|
||||
disabled={this.props.loading}
|
||||
onClick={this.props.loadData}
|
||||
primary
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ExamplePage.contextTypes = {
|
||||
router: PropTypes.object,
|
||||
};
|
||||
|
||||
ExamplePage.propTypes = {
|
||||
data: PropTypes.oneOfType([
|
||||
PropTypes.bool,
|
||||
PropTypes.object,
|
||||
]).isRequired,
|
||||
loadData: PropTypes.func.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators(
|
||||
{
|
||||
loadData,
|
||||
},
|
||||
dispatch,
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
loading: makeSelectLoading(),
|
||||
data: makeSelectData(),
|
||||
});
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = strapi.injectReducer({ key: 'examplePage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'examplePage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
withSaga,
|
||||
withConnect,
|
||||
)(injectIntl(ExamplePage));
|
||||
@ -1,27 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* ExamplePage reducer
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
import { LOAD_DATA, LOADED_DATA } from './constants';
|
||||
|
||||
const initialState = fromJS({
|
||||
loading: false,
|
||||
data: false,
|
||||
});
|
||||
|
||||
function examplePageReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case LOAD_DATA:
|
||||
return state.set('loading', true);
|
||||
case LOADED_DATA:
|
||||
return state.set('loading', false).set('data', fromJS(action.data));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default examplePageReducer;
|
||||
@ -1,34 +0,0 @@
|
||||
/* eslint-disable */
|
||||
import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
import { takeLatest, put, fork, take, cancel } from 'redux-saga/effects';
|
||||
|
||||
import { loadedData } from './actions';
|
||||
import { LOAD_DATA } from './constants';
|
||||
|
||||
export function* loadData() {
|
||||
// Fake API request delay
|
||||
yield new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// Generate a random array
|
||||
const data = Array(4)
|
||||
.fill(0)
|
||||
.map(() => Math.floor(Math.random() * 100));
|
||||
|
||||
yield put(loadedData(data));
|
||||
}
|
||||
|
||||
// Individual exports for testing
|
||||
export function* defaultSaga() {
|
||||
const loadDataWatcher = yield fork(takeLatest, LOAD_DATA, loadData);
|
||||
|
||||
// Suspend execution until location changes
|
||||
yield take(LOCATION_CHANGE);
|
||||
yield cancel(loadDataWatcher);
|
||||
}
|
||||
|
||||
// All sagas to be loaded
|
||||
export default defaultSaga;
|
||||
@ -1,25 +0,0 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
/**
|
||||
* Direct selector to the examplePage state domain
|
||||
*/
|
||||
const selectExamplePageDomain = () => state => state.get(`${pluginId}_examplePage`);
|
||||
|
||||
/**
|
||||
* Default selector used by HomePage
|
||||
*/
|
||||
|
||||
const makeSelectLoading = () =>
|
||||
createSelector(
|
||||
selectExamplePageDomain(),
|
||||
substate => substate.get('loading'),
|
||||
);
|
||||
|
||||
const makeSelectData = () =>
|
||||
createSelector(
|
||||
selectExamplePageDomain(),
|
||||
substate => substate.get('data'),
|
||||
);
|
||||
|
||||
export { makeSelectLoading, makeSelectData };
|
||||
@ -1,3 +0,0 @@
|
||||
.examplePage {
|
||||
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* HomePage actions
|
||||
*
|
||||
*/
|
||||
|
||||
import { DEFAULT_ACTION } from './constants';
|
||||
|
||||
export function defaultAction() {
|
||||
return {
|
||||
type: DEFAULT_ACTION,
|
||||
};
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* HomePage constants
|
||||
*
|
||||
*/
|
||||
|
||||
import pluginId from 'pluginId';
|
||||
|
||||
export const DEFAULT_ACTION = `${pluginId}/HomePage/DEFAULT_ACTION`;
|
||||
@ -4,60 +4,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { bindActionCreators, compose } from 'redux';
|
||||
import pluginId from 'pluginId';
|
||||
import React, { memo } from 'react';
|
||||
// import PropTypes from 'prop-types';
|
||||
import pluginId from '../../pluginId';
|
||||
|
||||
// Selectors
|
||||
import selectHomePage from './selectors';
|
||||
|
||||
// Styles
|
||||
import styles from './styles.scss';
|
||||
|
||||
import reducer from './reducer';
|
||||
import saga from './saga';
|
||||
|
||||
export class HomePage extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.homePage}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
HomePage.contextTypes = {
|
||||
router: PropTypes.object,
|
||||
};
|
||||
|
||||
HomePage.propTypes = {
|
||||
// homePage: PropTypes.object,
|
||||
};
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators(
|
||||
{
|
||||
// Your actions here
|
||||
},
|
||||
dispatch,
|
||||
const HomePage = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1>{pluginId}'s HomePage</h1>
|
||||
<p>Happy coding</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
homePage: selectHomePage(),
|
||||
});
|
||||
|
||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
const withReducer = strapi.injectReducer({ key: 'homePage', reducer, pluginId });
|
||||
const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
|
||||
|
||||
export default compose(
|
||||
withReducer,
|
||||
withSaga,
|
||||
withConnect,
|
||||
)(injectIntl(HomePage));
|
||||
export default memo(HomePage);
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* HomePage reducer
|
||||
*
|
||||
*/
|
||||
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
import { DEFAULT_ACTION } from './constants';
|
||||
|
||||
const initialState = fromJS({});
|
||||
|
||||
function homePageReducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case DEFAULT_ACTION:
|
||||
return state;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default homePageReducer;
|
||||
@ -1,9 +0,0 @@
|
||||
// import { LOCATION_CHANGE } from 'react-router-redux';
|
||||
// import { takeLatest, put, fork, take, cancel } from 'redux-saga/effects';
|
||||
|
||||
// Individual exports for testing
|
||||
export function* defaultSaga() {
|
||||
}
|
||||
|
||||
// All sagas to be loaded
|
||||
export default defaultSaga;
|
||||
@ -1,18 +0,0 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import pluginId from 'pluginId';
|
||||
/**
|
||||
* Direct selector to the homePage state domain
|
||||
*/
|
||||
const selectHomePageDomain = () => state => state.get(`${pluginId}_homePage`);
|
||||
|
||||
/**
|
||||
* Default selector used by HomePage
|
||||
*/
|
||||
|
||||
const selectHomePage = () =>
|
||||
createSelector(
|
||||
selectHomePageDomain(),
|
||||
substate => substate.toJS(),
|
||||
);
|
||||
|
||||
export default selectHomePage;
|
||||
@ -1,3 +0,0 @@
|
||||
.homePage {
|
||||
|
||||
}
|
||||
@ -4,21 +4,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import pluginId from '../../pluginId';
|
||||
|
||||
class Initializer extends React.PureComponent {
|
||||
// eslint-disable-line react/prefer-stateless-function
|
||||
componentDidMount() {
|
||||
// Emit the event 'pluginReady'
|
||||
this.props.updatePlugin(pluginId, 'isReady', true);
|
||||
}
|
||||
const Initializer = ({ updatePlugin }) => {
|
||||
const ref = useRef();
|
||||
ref.current = updatePlugin;
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
ref.current(pluginId, 'isReady', true);
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
Initializer.propTypes = {
|
||||
updatePlugin: PropTypes.func.isRequired,
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
// import React from 'react';
|
||||
// import { mount, shallow } from 'enzyme';
|
||||
// import pluginId from '../../pluginId';
|
||||
|
||||
// import Initializer from '../index';
|
||||
|
||||
describe('<Initializer />', () => {
|
||||
// it('Should not crash', () => {
|
||||
// const updatePlugin = jest.fn();
|
||||
// const renderedComponent = shallow(<Initializer updatePlugin={updatePlugin} />);
|
||||
|
||||
// expect(renderedComponent.children()).toHaveLength(0);
|
||||
// });
|
||||
|
||||
// it('should call the updatePlugin props when mounted', () => {
|
||||
// const updatePlugin = jest.fn();
|
||||
|
||||
// const wrapper = mount(<Initializer updatePlugin={updatePlugin} />);
|
||||
|
||||
// expect(wrapper.prop('updatePlugin')).toHaveBeenCalledWith(pluginId, 'isReady', true);
|
||||
// });
|
||||
it('should have unit tests specified', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* NotFoundPage
|
||||
*
|
||||
* This is the page we show when the user visits a url that doesn't have a route
|
||||
*
|
||||
* NOTE: while this component should technically be a stateless functional
|
||||
* component (SFC), hot reloading does not currently support SFCs. If hot
|
||||
* reloading is not a neccessity for you then you can refactor it and remove
|
||||
* the linting exception.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import NotFound from 'components/NotFound';
|
||||
|
||||
export default class NotFoundPage extends React.Component {
|
||||
render() {
|
||||
return <NotFound {...this.props} />;
|
||||
}
|
||||
}
|
||||
34
packages/strapi-generate-plugin/files/admin/src/index.js
Normal file
34
packages/strapi-generate-plugin/files/admin/src/index.js
Normal file
@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import pluginPkg from '../../package.json';
|
||||
import pluginId from './pluginId';
|
||||
import App from './containers/App';
|
||||
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,
|
||||
trads,
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
@ -1,23 +1,3 @@
|
||||
/*
|
||||
*
|
||||
* SET THE HOOKS TO ENABLE THE MAGIC OF STRAPI.
|
||||
* -------------------------------------------
|
||||
*
|
||||
* Secure, customise and enhance your project by setting
|
||||
* the hooks via this file.
|
||||
*
|
||||
*/
|
||||
function lifecycles() {}
|
||||
|
||||
module.exports = function lifecycles() {
|
||||
// Set hooks for the AdminPage container.
|
||||
// Note: we don't need to specify the first argument because we already know what "willSecure" refers to.
|
||||
this.setHooks({
|
||||
didGetSecuredData: () => console.log('do something'),
|
||||
});
|
||||
|
||||
// Set hooks for the App container of the Content Manager.
|
||||
// Note: we have to specify the first argument to select a specific container which is located in a plugin, or not.
|
||||
// this.setHooks('content-manager.App', {
|
||||
// willSomething: () => { console.log("Do Something"); }
|
||||
// });
|
||||
};
|
||||
export default lifecycles;
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
import ar from './ar.json';
|
||||
import de from './de.json';
|
||||
import en from './en.json';
|
||||
import es from './es.json';
|
||||
import fr from './fr.json';
|
||||
import it from './it.json';
|
||||
import ko from './ko.json';
|
||||
import nl from './nl.json';
|
||||
import pl from './pl.json';
|
||||
import ptBR from './pt-BR.json';
|
||||
import pt from './pt.json';
|
||||
import ru from './ru.json';
|
||||
import tr from './tr.json';
|
||||
import zhHans from './zh-Hans.json';
|
||||
import zh from './zh.json';
|
||||
|
||||
const trads = {
|
||||
ar,
|
||||
de,
|
||||
en,
|
||||
es,
|
||||
fr,
|
||||
it,
|
||||
ko,
|
||||
nl,
|
||||
pl,
|
||||
'pt-BR': ptBR,
|
||||
pt,
|
||||
ru,
|
||||
tr,
|
||||
'zh-Hans': zhHans,
|
||||
zh,
|
||||
};
|
||||
|
||||
export default trads;
|
||||
@ -0,0 +1 @@
|
||||
{}
|
||||
@ -56,6 +56,12 @@ module.exports = (scope, cb) => {
|
||||
const pluginDir = path.resolve(scope.rootPath, 'plugins');
|
||||
fs.ensureDirSync(pluginDir);
|
||||
|
||||
// Copy the admin files.
|
||||
fs.copySync(
|
||||
path.resolve(__dirname, '..', 'files'),
|
||||
path.resolve(pluginDir, scope.humanizeId)
|
||||
);
|
||||
|
||||
// Trigger callback with no error to proceed.
|
||||
return cb.success();
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user