mirror of
https://github.com/strapi/strapi.git
synced 2025-11-27 23:54:18 +00:00
Merge branch 'master' into patch-2
This commit is contained in:
commit
f28fed0e69
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,3 +1,10 @@
|
|||||||
|
> ⚠️ We have stopped merging PRs for now to the Strapi core.<br><br>
|
||||||
|
> The reason is that we are developing new architecture for the admin panel and for the plugins.<br>
|
||||||
|
> This new architecture will provide stability of the Strapi core as we approach the release of Beta.<br>
|
||||||
|
> We appreciate and welcome all your contributions, but until further notice, please do not submit a PR as it will not be merged.<br>
|
||||||
|
> Furthermore, you will have to rewrite it based on the new architecture.
|
||||||
|
|
||||||
|
|
||||||
<!-- ⚠️ Your PR title will appear in the changelogs please make it short detailed and understandable for all. -->
|
<!-- ⚠️ Your PR title will appear in the changelogs please make it short detailed and understandable for all. -->
|
||||||
|
|
||||||
<!-- Write a short description of what your PR does and link the concerned issues of your update. -->
|
<!-- Write a short description of what your PR does and link the concerned issues of your update. -->
|
||||||
|
|||||||
@ -32,10 +32,14 @@ install:
|
|||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- stage: test
|
- stage: test
|
||||||
name: 'Lint / Snyk / Unit Tests '
|
name: Snyk
|
||||||
|
script: npm run -s test:snyk
|
||||||
|
if: fork = false
|
||||||
|
|
||||||
|
- stage: test
|
||||||
|
name: 'Lint / Unit Tests '
|
||||||
script:
|
script:
|
||||||
- npm run -s lint
|
- npm run -s lint
|
||||||
- npm run -s test:snyk
|
|
||||||
- npm run -s test:unit
|
- npm run -s test:unit
|
||||||
|
|
||||||
- <<: *e2e_tests
|
- <<: *e2e_tests
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
# Contribute to Strapi
|
# Contribute to Strapi
|
||||||
|
|
||||||
|
> ⚠️ We have stopped merging PRs for now to the Strapi core.<br><br>
|
||||||
|
> The reason is that we are developing new architecture for the admin panel and for the plugins.<br>
|
||||||
|
> This new architecture will provide stability of the Strapi core as we approach the release of Beta.<br>
|
||||||
|
> We appreciate and welcome all your contributions, but until further notice, please do not submit a PR as it will not be merged.<br>
|
||||||
|
> Furthermore, you will have to rewrite it based on the new architecture.
|
||||||
|
|
||||||
First off, thanks for taking the time to contribute! 🎉👍
|
First off, thanks for taking the time to contribute! 🎉👍
|
||||||
|
|
||||||
The following is a set of guidelines for contributing to Strapi and its packages.
|
The following is a set of guidelines for contributing to Strapi and its packages.
|
||||||
@ -206,7 +212,7 @@ Then run
|
|||||||
# generate the test app
|
# generate the test app
|
||||||
$ node test/createTestApp.js
|
$ node test/createTestApp.js
|
||||||
# run the testApp in the background (️️️⚠️ be carefull to kill the process after the tests have run)
|
# run the testApp in the background (️️️⚠️ be carefull to kill the process after the tests have run)
|
||||||
$ node test/startTestApp.js &
|
$ node test/startTestApp.js &
|
||||||
# run cypress
|
# run cypress
|
||||||
$ node test/cypress
|
$ node test/cypress
|
||||||
```
|
```
|
||||||
|
|||||||
@ -121,6 +121,12 @@ Be aware that one of the content type builder won't work due to the writing file
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
> ⚠️ We have stopped merging PRs for now to the Strapi core.<br><br>
|
||||||
|
> The reason is that we are developing new architecture for the admin panel and for the plugins.<br>
|
||||||
|
> This new architecture will provide stability of the Strapi core as we approach the release of Beta.<br>
|
||||||
|
> We appreciate and welcome all your contributions, but until further notice, please do not submit a PR as it will not be merged.<br>
|
||||||
|
> Furthermore, you will have to rewrite it based on the new architecture.
|
||||||
|
|
||||||
Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull Request to the project.
|
Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull Request to the project.
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
@ -133,7 +139,7 @@ For general help using Strapi, please refer to [the official Strapi documentatio
|
|||||||
|
|
||||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/strapi)
|
- [StackOverflow](http://stackoverflow.com/questions/tagged/strapi)
|
||||||
- [Slack](http://slack.strapi.io) (highly recommended for faster support)
|
- [Slack](http://slack.strapi.io) (highly recommended for faster support)
|
||||||
- [GitHub](https://github.com/strapi/strapi)
|
- [GitHub](https://github.com/strapi/strapi) (Bug reports and Feature requests only)
|
||||||
- [Twitter](https://twitter.com/strapijs)
|
- [Twitter](https://twitter.com/strapijs)
|
||||||
- [Facebook](https://www.facebook.com/Strapi-616063331867161).
|
- [Facebook](https://www.facebook.com/Strapi-616063331867161).
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,6 @@ You are invited to get started using Strapi. You may explore Strapi by:
|
|||||||
1. A [Quick Start Guide](../getting-started/quick-start.html) for more intermediate to advanced developers.
|
1. A [Quick Start Guide](../getting-started/quick-start.html) for more intermediate to advanced developers.
|
||||||
2. A [Tutorial](../getting-started/quick-start-tutorial.html) for those who prefer a step-by-step introduction.
|
2. A [Tutorial](../getting-started/quick-start-tutorial.html) for those who prefer a step-by-step introduction.
|
||||||
|
|
||||||
When you're done getting started, we invite you to join our [community](../community.html).
|
When you're done getting started, we invite you to join our [community](https://strapi.io/community).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,14 @@ import injectReducer from 'utils/injectReducer';
|
|||||||
|
|
||||||
import OnboardingVideo from 'components/OnboardingVideo';
|
import OnboardingVideo from 'components/OnboardingVideo';
|
||||||
|
|
||||||
import { getVideos, onClick, removeVideos, setVideoDuration, setVideoEnd, updateVideoStartTime } from './actions';
|
import {
|
||||||
|
getVideos,
|
||||||
|
onClick,
|
||||||
|
removeVideos,
|
||||||
|
setVideoDuration,
|
||||||
|
setVideoEnd,
|
||||||
|
updateVideoStartTime,
|
||||||
|
} from './actions';
|
||||||
import makeSelectOnboarding from './selectors';
|
import makeSelectOnboarding from './selectors';
|
||||||
import reducer from './reducer';
|
import reducer from './reducer';
|
||||||
import saga from './saga';
|
import saga from './saga';
|
||||||
@ -43,17 +50,17 @@ export class Onboarding extends React.Component {
|
|||||||
|
|
||||||
setVideoEnd = () => {
|
setVideoEnd = () => {
|
||||||
this.setVideoEnd();
|
this.setVideoEnd();
|
||||||
}
|
};
|
||||||
|
|
||||||
didPlayVideo = (index, currTime) => {
|
didPlayVideo = (index, currTime) => {
|
||||||
const eventName = `didPlay${index}GetStartedVideo`;
|
const eventName = `didPlay${index}GetStartedVideo`;
|
||||||
this.context.emitEvent(eventName, {timestamp: currTime});
|
this.context.emitEvent(eventName, { timestamp: currTime });
|
||||||
}
|
};
|
||||||
|
|
||||||
didStopVideo = (index, currTime) => {
|
didStopVideo = (index, currTime) => {
|
||||||
const eventName = `didStop${index}Video`;
|
const eventName = `didStop${index}Video`;
|
||||||
this.context.emitEvent(eventName, {timestamp: currTime});
|
this.context.emitEvent(eventName, { timestamp: currTime });
|
||||||
}
|
};
|
||||||
|
|
||||||
handleOpenModal = () => this.setState({ showVideos: true });
|
handleOpenModal = () => this.setState({ showVideos: true });
|
||||||
|
|
||||||
@ -67,10 +74,9 @@ export class Onboarding extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
updateCurrentTime = (index, current, duration) => {
|
updateCurrentTime = (index, current, duration) => {
|
||||||
|
|
||||||
this.props.updateVideoStartTime(index, current);
|
this.props.updateVideoStartTime(index, current);
|
||||||
|
|
||||||
const percent = current * 100 / duration;
|
const percent = (current * 100) / duration;
|
||||||
const video = this.props.videos[index];
|
const video = this.props.videos[index];
|
||||||
|
|
||||||
if (percent >= 80) {
|
if (percent >= 80) {
|
||||||
@ -80,21 +86,35 @@ export class Onboarding extends React.Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
updateEnd = (index) => {
|
updateEnd = index => {
|
||||||
this.props.setVideoEnd(index, true);
|
this.props.setVideoEnd(index, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-line jsx-handler-names
|
// eslint-disable-line jsx-handler-names
|
||||||
render() {
|
render() {
|
||||||
const { videos, onClick, setVideoDuration } = this.props;
|
const { videos, onClick, setVideoDuration } = this.props;
|
||||||
|
const { showVideos } = this.state;
|
||||||
|
|
||||||
|
const style = showVideos ? {} : { maxWidth: 0 };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn(styles.videosWrapper, videos.length > 0 ? styles.visible : styles.hidden)}>
|
<div
|
||||||
<div className={cn(styles.videosContent, this.state.showVideos ? styles.shown : styles.hide)}>
|
style={style}
|
||||||
|
className={cn(styles.videosWrapper, videos.length > 0 ? styles.visible : styles.hidden)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={style}
|
||||||
|
className={cn(styles.videosContent, this.state.showVideos ? styles.shown : styles.hide)}
|
||||||
|
>
|
||||||
<div className={styles.videosHeader}>
|
<div className={styles.videosHeader}>
|
||||||
<p><FormattedMessage id="app.components.Onboarding.title" /></p>
|
<p>
|
||||||
|
<FormattedMessage id="app.components.Onboarding.title" />
|
||||||
|
</p>
|
||||||
{videos.length && (
|
{videos.length && (
|
||||||
<p>{Math.floor((videos.filter(v => v.end).length)*100/videos.length)}<FormattedMessage id="app.components.Onboarding.label.completed" /></p>
|
<p>
|
||||||
|
{Math.floor((videos.filter(v => v.end).length * 100) / videos.length)}
|
||||||
|
<FormattedMessage id="app.components.Onboarding.label.completed" />
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<ul className={styles.onboardingList}>
|
<ul className={styles.onboardingList}>
|
||||||
@ -116,10 +136,7 @@ export class Onboarding extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.openBtn}>
|
<div className={styles.openBtn}>
|
||||||
<button
|
<button onClick={this.handleVideosToggle} className={this.state.showVideos ? styles.active : ''}>
|
||||||
onClick={this.handleVideosToggle}
|
|
||||||
className={this.state.showVideos ? styles.active : ''}
|
|
||||||
>
|
|
||||||
<i className="fa fa-question" />
|
<i className="fa fa-question" />
|
||||||
<i className="fa fa-times" />
|
<i className="fa fa-times" />
|
||||||
<span />
|
<span />
|
||||||
@ -157,7 +174,10 @@ Onboarding.propTypes = {
|
|||||||
const mapStateToProps = makeSelectOnboarding();
|
const mapStateToProps = makeSelectOnboarding();
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return bindActionCreators({ getVideos, onClick, setVideoDuration, updateVideoStartTime, setVideoEnd, removeVideos }, dispatch);
|
return bindActionCreators(
|
||||||
|
{ getVideos, onClick, setVideoDuration, updateVideoStartTime, setVideoEnd, removeVideos },
|
||||||
|
dispatch,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const withConnect = connect(
|
const withConnect = connect(
|
||||||
|
|||||||
@ -113,4 +113,4 @@
|
|||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
/* global <%= globalID %> */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <%= filename %> service
|
* <%= filename %> service
|
||||||
*
|
*
|
||||||
|
|||||||
@ -5,6 +5,6 @@
|
|||||||
* Direct selector to the list state domain
|
* Direct selector to the list state domain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// const selectGlobalDomain = () => state => state.get(`${pluginId}-global`);
|
// const selectGlobalDomain = () => state => state.get(`${pluginId}_global`);
|
||||||
|
|
||||||
export {};
|
export {};
|
||||||
|
|||||||
@ -4,16 +4,22 @@ import pluginId from 'pluginId';
|
|||||||
/**
|
/**
|
||||||
* Direct selector to the examplePage state domain
|
* Direct selector to the examplePage state domain
|
||||||
*/
|
*/
|
||||||
const selectExamplePageDomain = () => state => state.get(`${pluginId}-examplePage`);
|
const selectExamplePageDomain = () => state => state.get(`${pluginId}_examplePage`);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default selector used by HomePage
|
* Default selector used by HomePage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const makeSelectLoading = () =>
|
const makeSelectLoading = () =>
|
||||||
createSelector(selectExamplePageDomain(), substate => substate.get('loading'));
|
createSelector(
|
||||||
|
selectExamplePageDomain(),
|
||||||
|
substate => substate.get('loading'),
|
||||||
|
);
|
||||||
|
|
||||||
const makeSelectData = () =>
|
const makeSelectData = () =>
|
||||||
createSelector(selectExamplePageDomain(), substate => substate.get('data'));
|
createSelector(
|
||||||
|
selectExamplePageDomain(),
|
||||||
|
substate => substate.get('data'),
|
||||||
|
);
|
||||||
|
|
||||||
export { makeSelectLoading, makeSelectData };
|
export { makeSelectLoading, makeSelectData };
|
||||||
|
|||||||
@ -3,15 +3,16 @@ import pluginId from 'pluginId';
|
|||||||
/**
|
/**
|
||||||
* Direct selector to the homePage state domain
|
* Direct selector to the homePage state domain
|
||||||
*/
|
*/
|
||||||
const selectHomePageDomain = () => state => state.get(`${pluginId}-homePage`);
|
const selectHomePageDomain = () => state => state.get(`${pluginId}_homePage`);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default selector used by HomePage
|
* Default selector used by HomePage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const selectHomePage = () => createSelector(
|
const selectHomePage = () =>
|
||||||
selectHomePageDomain(),
|
createSelector(
|
||||||
(substate) => substate.toJS(),
|
selectHomePageDomain(),
|
||||||
);
|
substate => substate.toJS(),
|
||||||
|
);
|
||||||
|
|
||||||
export default selectHomePage;
|
export default selectHomePage;
|
||||||
|
|||||||
@ -39,10 +39,22 @@ function InputSelect(props) {
|
|||||||
>
|
>
|
||||||
{map(props.selectOptions, (option, key) => {
|
{map(props.selectOptions, (option, key) => {
|
||||||
if (isObject(option)) {
|
if (isObject(option)) {
|
||||||
return <SelectOption key={key} {...option} />;
|
if (option.label) {
|
||||||
|
return (
|
||||||
|
<option key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <SelectOption key={key} {...option} />;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <option key={key} value={option}>{option}</option>;
|
return (
|
||||||
|
<option key={key} value={option}>
|
||||||
|
{option}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</select>
|
</select>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -77,16 +77,16 @@ module.exports = {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(modelFilePath, JSON.stringify(modelJSON, null, 2), 'utf8');
|
fs.writeFileSync(modelFilePath, JSON.stringify(modelJSON, null, 2), 'utf8');
|
||||||
|
|
||||||
if (_.isEmpty(strapi.api)) {
|
if (_.isEmpty(strapi.api)) {
|
||||||
strapi.emit('didCreateFirstContentType');
|
strapi.emit('didCreateFirstContentType');
|
||||||
} else {
|
} else {
|
||||||
strapi.emit('didCreateContentType');
|
strapi.emit('didCreateContentType');
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.send({ ok: true });
|
ctx.send({ ok: true });
|
||||||
|
|
||||||
strapi.reload();
|
setImmediate(() => strapi.reload());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
strapi.emit('didNotCreateContentType', e);
|
strapi.emit('didNotCreateContentType', e);
|
||||||
return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.write' }] }]);
|
return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.write' }] }]);
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* SelectOption
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import getFlag, { formatLanguageLocale } from '../../utils/getFlag';
|
|
||||||
import styles from './styles.scss';
|
|
||||||
|
|
||||||
/* eslint-disable react/require-default-props */
|
|
||||||
class SelectOptionLanguage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
||||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
||||||
handleSelect = (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
this.props.onSelect(this.props.option, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMouseEnter = (event) => {
|
|
||||||
this.props.onFocus(this.props.option, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMouseMove = (event) => {
|
|
||||||
if (this.props.isFocused) return;
|
|
||||||
this.props.onFocus(this.props.option, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const flagName = formatLanguageLocale(this.props.option.value);
|
|
||||||
const flag = getFlag(flagName);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.selectOption} onMouseEnter={this.handleMouseEnter} onMouseMove={this.handleMouseMove} onFocus={this.props.onFocus} onClick={this.handleSelect} id={this.props.option.value}>
|
|
||||||
<span className={`${styles.flagContainer} flag-icon flag-icon-${flag}`} />
|
|
||||||
<span className={styles.optionLabel}>{this.props.option.label}</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectOptionLanguage.propTypes = {
|
|
||||||
isFocused: PropTypes.bool,
|
|
||||||
onFocus: PropTypes.func,
|
|
||||||
onSelect: PropTypes.func,
|
|
||||||
option: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SelectOptionLanguage;
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
.selectOption { /* stylelint-disable */
|
|
||||||
margin: 1rem;
|
|
||||||
background-image: url('assets/images/unknow_flag.png');
|
|
||||||
background-size: 1.3333em auto;
|
|
||||||
background-position: left center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flagContainer {
|
|
||||||
// margin-left: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.optionLabel {
|
|
||||||
margin-left: 1rem;
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
@ -11,7 +11,6 @@ import { connect } from 'react-redux';
|
|||||||
import { createStructuredSelector } from 'reselect';
|
import { createStructuredSelector } from 'reselect';
|
||||||
import { bindActionCreators, compose } from 'redux';
|
import { bindActionCreators, compose } from 'redux';
|
||||||
import 'flag-icon-css/css/flag-icon.css';
|
import 'flag-icon-css/css/flag-icon.css';
|
||||||
import 'react-select/dist/react-select.css';
|
|
||||||
import { Switch, Route } from 'react-router-dom';
|
import { Switch, Route } from 'react-router-dom';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
|
|
||||||
@ -83,7 +82,7 @@ export function mapDispatchToProps(dispatch) {
|
|||||||
menuFetch,
|
menuFetch,
|
||||||
environmentsFetch,
|
environmentsFetch,
|
||||||
},
|
},
|
||||||
dispatch
|
dispatch,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +92,10 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Wrap the component to inject dispatch and state into it
|
// Wrap the component to inject dispatch and state into it
|
||||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
const withConnect = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
);
|
||||||
|
|
||||||
const withReducer = strapi.injectReducer({ key: 'global', reducer, pluginId });
|
const withReducer = strapi.injectReducer({ key: 'global', reducer, pluginId });
|
||||||
const withSaga = strapi.injectSaga({ key: 'global', saga, pluginId });
|
const withSaga = strapi.injectSaga({ key: 'global', saga, pluginId });
|
||||||
|
|||||||
@ -26,9 +26,10 @@ import {
|
|||||||
} from 'lodash';
|
} from 'lodash';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
import Select from 'react-select';
|
|
||||||
import { router } from 'app';
|
import { router } from 'app';
|
||||||
|
|
||||||
|
import InputSelect from 'strapi-helper-plugin/lib/src/components/InputSelect';
|
||||||
|
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
// design
|
// design
|
||||||
import ContentHeader from '../../components/ContentHeader';
|
import ContentHeader from '../../components/ContentHeader';
|
||||||
@ -36,15 +37,11 @@ import EditForm from '../../components/EditForm';
|
|||||||
import HeaderNav from '../../components/HeaderNav';
|
import HeaderNav from '../../components/HeaderNav';
|
||||||
import List from '../../components/List';
|
import List from '../../components/List';
|
||||||
import RowDatabase from '../../components/RowDatabase';
|
import RowDatabase from '../../components/RowDatabase';
|
||||||
import SelectOptionLanguage from '../../components/SelectOptionLanguage';
|
|
||||||
import RowLanguage from '../../components/RowLanguage';
|
import RowLanguage from '../../components/RowLanguage';
|
||||||
import PluginLeftMenu from '../../components/PluginLeftMenu';
|
import PluginLeftMenu from '../../components/PluginLeftMenu';
|
||||||
|
|
||||||
// utils
|
|
||||||
import unknowFlag from 'assets/images/unknow_flag.png';
|
|
||||||
import supportedFlags from 'utils/supportedFlags.json';
|
|
||||||
import { checkFormValidity, getRequiredInputsDb } from '../../utils/inputValidations';
|
import { checkFormValidity, getRequiredInputsDb } from '../../utils/inputValidations';
|
||||||
import getFlag, { formatLanguageLocale } from '../../utils/getFlag';
|
import { formatLanguageLocale } from '../../utils/getFlag';
|
||||||
import sendUpdatedParams from '../../utils/sendUpdatedParams';
|
import sendUpdatedParams from '../../utils/sendUpdatedParams';
|
||||||
// App selectors
|
// App selectors
|
||||||
import { makeSelectSections, makeSelectEnvironments } from '../App/selectors';
|
import { makeSelectSections, makeSelectEnvironments } from '../App/selectors';
|
||||||
@ -74,7 +71,8 @@ import styles from './styles.scss';
|
|||||||
import config from './config.json';
|
import config from './config.json';
|
||||||
|
|
||||||
/* eslint-disable react/require-default-props */
|
/* eslint-disable react/require-default-props */
|
||||||
export class HomePage extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
export class HomePage extends React.Component {
|
||||||
|
// eslint-disable-line react/prefer-stateless-function
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.customComponents = config.customComponents;
|
this.customComponents = config.customComponents;
|
||||||
@ -98,7 +96,10 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
if (this.props.match.params.slug) {
|
if (this.props.match.params.slug) {
|
||||||
this.handleFetch(this.props);
|
this.handleFetch(this.props);
|
||||||
} else {
|
} else {
|
||||||
router.push(`/plugins/settings-manager/${get(this.props.menuSections, ['0', 'items', '0', 'slug']) || 'application'}`);
|
router.push(
|
||||||
|
`/plugins/settings-manager/${get(this.props.menuSections, ['0', 'items', '0', 'slug']) ||
|
||||||
|
'application'}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +113,11 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
// redirect user if no params slug provided
|
// redirect user if no params slug provided
|
||||||
router.push(`/plugins/settings-manager/${get(this.props.menuSections, ['0', 'items', '0', 'slug'])}`);
|
router.push(`/plugins/settings-manager/${get(this.props.menuSections, ['0', 'items', '0', 'slug'])}`);
|
||||||
}
|
}
|
||||||
} else if (this.props.match.params.env !== nextProps.match.params.env && nextProps.match.params.env && this.props.match.params.env) {
|
} else if (
|
||||||
|
this.props.match.params.env !== nextProps.match.params.env &&
|
||||||
|
nextProps.match.params.env &&
|
||||||
|
this.props.match.params.env
|
||||||
|
) {
|
||||||
// get data if params env updated
|
// get data if params env updated
|
||||||
this.handleFetch(nextProps);
|
this.handleFetch(nextProps);
|
||||||
}
|
}
|
||||||
@ -130,7 +135,7 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
|
|
||||||
/* eslint-disable react/sort-comp */
|
/* eslint-disable react/sort-comp */
|
||||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||||
addConnection = (e) => {
|
addConnection = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const newData = {};
|
const newData = {};
|
||||||
/* eslint-disable no-template-curly-in-string */
|
/* eslint-disable no-template-curly-in-string */
|
||||||
@ -151,18 +156,18 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
} else {
|
} else {
|
||||||
this.props.setErrors(formErrors);
|
this.props.setErrors(formErrors);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
emptyDbModifiedData = () => {
|
emptyDbModifiedData = () => {
|
||||||
this.setState({ toggleDefaultConnection: false });
|
this.setState({ toggleDefaultConnection: false });
|
||||||
this.props.emptyDbModifiedData();
|
this.props.emptyDbModifiedData();
|
||||||
}
|
};
|
||||||
|
|
||||||
getDatabase = (databaseName) => {
|
getDatabase = databaseName => {
|
||||||
// allow state here just for modal purpose
|
// allow state here just for modal purpose
|
||||||
this.props.specificDatabaseFetch(databaseName, this.props.match.params.env);
|
this.props.specificDatabaseFetch(databaseName, this.props.match.params.env);
|
||||||
// this.setState({ modal: !this.state.modal });
|
// this.setState({ modal: !this.state.modal });
|
||||||
}
|
};
|
||||||
|
|
||||||
handleDefaultLanguageChange = ({ target }) => {
|
handleDefaultLanguageChange = ({ target }) => {
|
||||||
// create new object configsDisplay based on store property configsDisplay
|
// create new object configsDisplay based on store property configsDisplay
|
||||||
@ -192,13 +197,19 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
const defaultLanguageArray = formatLanguageLocale(target.id);
|
const defaultLanguageArray = formatLanguageLocale(target.id);
|
||||||
|
|
||||||
// Edit the new config
|
// Edit the new config
|
||||||
this.props.editSettings({ 'language.defaultLocale': join(defaultLanguageArray, '_') }, 'i18n', this.context);
|
this.props.editSettings(
|
||||||
}
|
{ 'language.defaultLocale': join(defaultLanguageArray, '_') },
|
||||||
|
'i18n',
|
||||||
|
this.context,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
handleFetch(props) {
|
handleFetch(props) {
|
||||||
const apiUrl = props.match.params.env ? `${props.match.params.slug}/${props.match.params.env}` : props.match.params.slug;
|
const apiUrl = props.match.params.env
|
||||||
|
? `${props.match.params.slug}/${props.match.params.env}`
|
||||||
|
: props.match.params.slug;
|
||||||
|
|
||||||
switch(props.match.params.slug) {
|
switch (props.match.params.slug) {
|
||||||
case 'languages':
|
case 'languages':
|
||||||
return this.props.languagesFetch();
|
return this.props.languagesFetch();
|
||||||
case 'databases':
|
case 'databases':
|
||||||
@ -222,21 +233,30 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
|
|
||||||
if (this.props.match.params.slug === 'databases') {
|
if (this.props.match.params.slug === 'databases') {
|
||||||
if (name === this.props.home.dbNameTarget) {
|
if (name === this.props.home.dbNameTarget) {
|
||||||
const formErrors = value === this.props.home.addDatabaseSection.sections[1].items[0].value ?
|
const formErrors =
|
||||||
[{ target: name, errors: [{ id: 'settings-manager.request.error.database.exist' }] }] : [];
|
value === this.props.home.addDatabaseSection.sections[1].items[0].value
|
||||||
|
? [{ target: name, errors: [{ id: 'settings-manager.request.error.database.exist' }] }]
|
||||||
|
: [];
|
||||||
this.props.setErrors(formErrors);
|
this.props.setErrors(formErrors);
|
||||||
} else if (endsWith(name, '.settings.client')) {
|
} else if (endsWith(name, '.settings.client')) {
|
||||||
const item = find(this.props.home.addDatabaseSection.sections[0].items[1].items, { value });
|
const item = find(this.props.home.addDatabaseSection.sections[0].items[1].items, { value });
|
||||||
this.props.changeInput('database.connections.${name}.settings.port', item.port);
|
this.props.changeInput('database.connections.${name}.settings.port', item.port);
|
||||||
this.props.changeInput(`database.connections.${this.props.home.addDatabaseSection.sections[1].items[0].value}.settings.port`, item.port);
|
this.props.changeInput(
|
||||||
|
`database.connections.${
|
||||||
|
this.props.home.addDatabaseSection.sections[1].items[0].value
|
||||||
|
}.settings.port`,
|
||||||
|
item.port,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.props.setErrors([]);
|
this.props.setErrors([]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.props.changeInput(name, value);
|
this.props.changeInput(name, value);
|
||||||
}
|
};
|
||||||
|
|
||||||
handleChangeLanguage = (value) => this.props.changeInput('language.defaultLocale', value.value);
|
handleChangeLanguage = ({ target: { value } }) => {
|
||||||
|
this.props.changeInput('language.defaultLocale', value);
|
||||||
|
};
|
||||||
|
|
||||||
handleCancel = () => this.props.cancelChanges();
|
handleCancel = () => this.props.cancelChanges();
|
||||||
|
|
||||||
@ -245,28 +265,33 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
? this.props.home.addDatabaseSection.sections[1].items[0].value
|
? this.props.home.addDatabaseSection.sections[1].items[0].value
|
||||||
: this.props.home.modifiedData[this.props.home.dbNameTarget];
|
: this.props.home.modifiedData[this.props.home.dbNameTarget];
|
||||||
const target = { name: 'database.defaultConnection', value };
|
const target = { name: 'database.defaultConnection', value };
|
||||||
this.handleChange({target});
|
this.handleChange({ target });
|
||||||
this.setState({ toggleDefaultConnection: !this.state.toggleDefaultConnection });
|
this.setState({ toggleDefaultConnection: !this.state.toggleDefaultConnection });
|
||||||
}
|
};
|
||||||
|
|
||||||
handleSubmit = (e) => { // eslint-disable-line consistent-return
|
handleSubmit = e => {
|
||||||
|
// eslint-disable-line consistent-return
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const apiUrl = this.props.match.params.env ? `${this.props.match.params.slug}/${this.props.match.params.env}` : this.props.match.params.slug;
|
const apiUrl = this.props.match.params.env
|
||||||
|
? `${this.props.match.params.slug}/${this.props.match.params.env}`
|
||||||
|
: this.props.match.params.slug;
|
||||||
|
|
||||||
const isCreatingNewFields = this.props.match.params.slug === 'security';
|
const isCreatingNewFields = this.props.match.params.slug === 'security';
|
||||||
// send only updated settings
|
// send only updated settings
|
||||||
const body = this.sendUpdatedParams(isCreatingNewFields);
|
const body = this.sendUpdatedParams(isCreatingNewFields);
|
||||||
const formErrors = checkFormValidity(body, this.props.home.formValidations);
|
const formErrors = checkFormValidity(body, this.props.home.formValidations);
|
||||||
|
|
||||||
if (isEmpty(body)) return strapi.notification.info('settings-manager.strapi.notification.info.settingsEqual');
|
if (isEmpty(body))
|
||||||
|
return strapi.notification.info('settings-manager.strapi.notification.info.settingsEqual');
|
||||||
if (isEmpty(formErrors)) {
|
if (isEmpty(formErrors)) {
|
||||||
this.props.editSettings(body, apiUrl, this.context);
|
this.props.editSettings(body, apiUrl, this.context);
|
||||||
} else {
|
} else {
|
||||||
this.props.setErrors(formErrors);
|
this.props.setErrors(formErrors);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
handleSubmitEditDatabase = (databaseName) => { // eslint-disable-line consistent-return
|
handleSubmitEditDatabase = databaseName => {
|
||||||
|
// eslint-disable-line consistent-return
|
||||||
const body = this.sendUpdatedParams();
|
const body = this.sendUpdatedParams();
|
||||||
const apiUrl = `${databaseName}/${this.props.match.params.env}`;
|
const apiUrl = `${databaseName}/${this.props.match.params.env}`;
|
||||||
const formErrors = checkFormValidity(body, this.props.home.formValidations, this.props.home.formErrors);
|
const formErrors = checkFormValidity(body, this.props.home.formValidations, this.props.home.formErrors);
|
||||||
@ -276,25 +301,21 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
return strapi.notification.info('settings-manager.strapi.notification.info.settingsEqual');
|
return strapi.notification.info('settings-manager.strapi.notification.info.settingsEqual');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isEmpty(formErrors)) {
|
if (isEmpty(formErrors)) {
|
||||||
this.props.databaseEdit(body, apiUrl, this.context);
|
this.props.databaseEdit(body, apiUrl, this.context);
|
||||||
} else {
|
} else {
|
||||||
this.props.setErrors(formErrors);
|
this.props.setErrors(formErrors);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// retrieve the language to delete using the target id
|
// retrieve the language to delete using the target id
|
||||||
handleLanguageDelete = (languaToDelete) => this.props.languageDelete(languaToDelete);
|
handleLanguageDelete = languaToDelete => this.props.languageDelete(languaToDelete);
|
||||||
|
|
||||||
handleDatabaseDelete = (dbName) => {
|
handleDatabaseDelete = dbName => {
|
||||||
this.context.enableGlobalOverlayBlocker();
|
this.context.enableGlobalOverlayBlocker();
|
||||||
strapi.notification.success('settings-manager.strapi.notification.success.databaseDelete');
|
strapi.notification.success('settings-manager.strapi.notification.success.databaseDelete');
|
||||||
this.props.databaseDelete(dbName, this.props.match.params.env, this.context);
|
this.props.databaseDelete(dbName, this.props.match.params.env, this.context);
|
||||||
}
|
};
|
||||||
|
|
||||||
// function used for react-select option
|
|
||||||
optionComponent = (props) => <SelectOptionLanguage {...props} />;
|
|
||||||
|
|
||||||
// custom Row rendering for the component List with params slug === languages
|
// custom Row rendering for the component List with params slug === languages
|
||||||
renderRowLanguage = (props, key, liStyles) => (
|
renderRowLanguage = (props, key, liStyles) => (
|
||||||
@ -306,22 +327,36 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
listLanguages={this.props.home.listLanguages}
|
listLanguages={this.props.home.listLanguages}
|
||||||
onDefaultLanguageChange={this.handleDefaultLanguageChange}
|
onDefaultLanguageChange={this.handleDefaultLanguageChange}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
|
|
||||||
renderListTitle = () => {
|
renderListTitle = () => {
|
||||||
const availableContentNumber = size(this.props.home.configsDisplay.sections);
|
const availableContentNumber = size(this.props.home.configsDisplay.sections);
|
||||||
const title = availableContentNumber > 1 ? `list.${this.props.match.params.slug}.title.plural` : `list.${this.props.match.params.slug}.title.singular`;
|
const title =
|
||||||
|
availableContentNumber > 1
|
||||||
|
? `list.${this.props.match.params.slug}.title.plural`
|
||||||
|
: `list.${this.props.match.params.slug}.title.singular`;
|
||||||
const titleDisplay = title ? <FormattedMessage id={`settings-manager.${title}`} /> : '';
|
const titleDisplay = title ? <FormattedMessage id={`settings-manager.${title}`} /> : '';
|
||||||
|
|
||||||
return <span>{availableContentNumber} {titleDisplay}</span>;
|
return (
|
||||||
}
|
<span>
|
||||||
|
{availableContentNumber} {titleDisplay}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
renderListButtonLabel = () => `list.${this.props.match.params.slug}.button.label`;
|
renderListButtonLabel = () => `list.${this.props.match.params.slug}.button.label`;
|
||||||
|
|
||||||
renderPopUpFormDatabase = (section, props, popUpStyles) => (
|
renderPopUpFormDatabase = (section, props, popUpStyles) =>
|
||||||
map(section.items, (item, key) => {
|
map(section.items, (item, key) => {
|
||||||
const isActive = props.values[this.props.home.dbNameTarget] === this.props.home.modifiedData['database.defaultConnection'] ?
|
const isActive =
|
||||||
<div className={popUpStyles.rounded}><i className="fa fa-check" /></div> : '';
|
props.values[this.props.home.dbNameTarget] ===
|
||||||
|
this.props.home.modifiedData['database.defaultConnection'] ? (
|
||||||
|
<div className={popUpStyles.rounded}>
|
||||||
|
<i className="fa fa-check" />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
);
|
||||||
|
|
||||||
if (item.name === 'form.database.item.default') {
|
if (item.name === 'form.database.item.default') {
|
||||||
return (
|
return (
|
||||||
@ -331,39 +366,35 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
id={item.target}
|
id={item.target}
|
||||||
onClick={this.handleSetDefaultConnectionDb}
|
onClick={this.handleSetDefaultConnectionDb}
|
||||||
>
|
>
|
||||||
<FormattedMessage id={`settings-manager.${item.name}`} />{isActive}
|
<FormattedMessage id={`settings-manager.${item.name}`} />
|
||||||
|
{isActive}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return props.renderInput(item, key);
|
||||||
props.renderInput(item, key)
|
});
|
||||||
);
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
renderPopUpFormLanguage = (section) => (
|
renderPopUpFormLanguage = section =>
|
||||||
map(section.items, (item) => {
|
map(section.items, item => {
|
||||||
const value = this.props.home.modifiedData[item.target] || this.props.home.selectOptions.options[0].value;
|
const value =
|
||||||
|
this.props.home.modifiedData[item.target] || this.props.home.selectOptions.options[0].value;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`col-md-6`} key={item.name}>
|
<div className={`col-md-6`} key={item.name}>
|
||||||
<div className={styles.modalLanguageLabel}>
|
<div className={styles.modalLanguageLabel}>
|
||||||
<FormattedMessage id={`settings-manager.${item.name}`} />
|
<FormattedMessage id={`settings-manager.${item.name}`} />
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<InputSelect
|
||||||
name={item.target}
|
name={item.target}
|
||||||
value={value}
|
value={value}
|
||||||
options={this.props.home.selectOptions.options}
|
selectOptions={this.props.home.selectOptions.options}
|
||||||
onChange={this.handleChangeLanguage}
|
onChange={this.handleChangeLanguage}
|
||||||
valueComponent={this.valueComponent}
|
validations={{}}
|
||||||
optionComponent={this.optionComponent}
|
|
||||||
clearable={false}
|
|
||||||
/>
|
/>
|
||||||
<div className={styles.popUpSpacer} />
|
<div className={styles.popUpSpacer} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
});
|
||||||
)
|
|
||||||
|
|
||||||
renderRowDatabase = (props, key) => (
|
renderRowDatabase = (props, key) => (
|
||||||
<RowDatabase
|
<RowDatabase
|
||||||
@ -380,22 +411,30 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
error={this.props.home.error}
|
error={this.props.home.error}
|
||||||
resetToggleDefaultConnection={this.resetToggleDefaultConnection}
|
resetToggleDefaultConnection={this.resetToggleDefaultConnection}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
|
|
||||||
renderComponent = () => {
|
renderComponent = () => {
|
||||||
// check if settingName (params.slug) has a custom view display
|
// check if settingName (params.slug) has a custom view display
|
||||||
let specificComponent = findKey(this.customComponents, (value) => includes(value, this.props.match.params.slug));
|
let specificComponent = findKey(this.customComponents, value =>
|
||||||
|
includes(value, this.props.match.params.slug),
|
||||||
|
);
|
||||||
|
|
||||||
if (!specificComponent) {
|
if (!specificComponent) {
|
||||||
// Check if params env : render HeaderNav component
|
// Check if params env : render HeaderNav component
|
||||||
specificComponent = !this.props.match.params.env ? 'defaultComponent' : 'defaultComponentWithEnvironments';
|
specificComponent = !this.props.match.params.env
|
||||||
|
? 'defaultComponent'
|
||||||
|
: 'defaultComponentWithEnvironments';
|
||||||
}
|
}
|
||||||
|
|
||||||
// if custom view display render specificComponent
|
// if custom view display render specificComponent
|
||||||
const Component = this.components[specificComponent];
|
const Component = this.components[specificComponent];
|
||||||
const addRequiredInputDesign = this.props.match.params.slug === 'databases';
|
const addRequiredInputDesign = this.props.match.params.slug === 'databases';
|
||||||
const listTitle = ['languages', 'databases'].includes(this.props.match.params.slug) ? this.renderListTitle() : '';
|
const listTitle = ['languages', 'databases'].includes(this.props.match.params.slug)
|
||||||
const listButtonLabel = ['languages', 'databases'].includes(this.props.match.params.slug) ? this.renderListButtonLabel() : '';
|
? this.renderListTitle()
|
||||||
|
: '';
|
||||||
|
const listButtonLabel = ['languages', 'databases'].includes(this.props.match.params.slug)
|
||||||
|
? this.renderListButtonLabel()
|
||||||
|
: '';
|
||||||
|
|
||||||
// check if HeaderNav component needs to render a form or a list
|
// check if HeaderNav component needs to render a form or a list
|
||||||
const renderListComponent = this.props.match.params.slug === 'databases';
|
const renderListComponent = this.props.match.params.slug === 'databases';
|
||||||
@ -459,7 +498,7 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
showLoader={this.props.home.showLoader}
|
showLoader={this.props.home.showLoader}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Set the toggleDefaultConnection to false
|
// Set the toggleDefaultConnection to false
|
||||||
resetToggleDefaultConnection = () => this.setState({ toggleDefaultConnection: false });
|
resetToggleDefaultConnection = () => this.setState({ toggleDefaultConnection: false });
|
||||||
@ -467,30 +506,19 @@ export class HomePage extends React.Component { // eslint-disable-line react/pre
|
|||||||
// Hide database modal
|
// Hide database modal
|
||||||
toggle = () => this.setState({ modal: !this.state.modal });
|
toggle = () => this.setState({ modal: !this.state.modal });
|
||||||
|
|
||||||
// function used for react-select
|
|
||||||
valueComponent = (props) => {
|
|
||||||
const flagName = formatLanguageLocale(props.value.value);
|
|
||||||
const flag = getFlag(flagName);
|
|
||||||
const spanStyle = includes(supportedFlags.flags, flag) ? {} : { backgroundImage: `url(${unknowFlag})` };
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span className={`${styles.flagContainer} flag-icon-background flag-icon-${flag}`} style={spanStyle}>
|
|
||||||
<FormattedMessage id="settings-manager.selectValue" defaultMessage='{language}' values={{ language: props.value.label}} className={styles.marginLeft} />
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<PluginLeftMenu sections={this.props.menuSections} environments={this.props.environments} envParams={this.props.match.params.env} />
|
<PluginLeftMenu
|
||||||
|
sections={this.props.menuSections}
|
||||||
|
environments={this.props.environments}
|
||||||
|
envParams={this.props.match.params.env}
|
||||||
|
/>
|
||||||
<div className={`${styles.home} col-md-9`}>
|
<div className={`${styles.home} col-md-9`}>
|
||||||
<Helmet
|
<Helmet
|
||||||
title="Settings Manager"
|
title="Settings Manager"
|
||||||
meta={[
|
meta={[{ name: 'Settings Manager Plugin', content: 'Modify your app settings' }]}
|
||||||
{ name: 'Settings Manager Plugin', content: 'Modify your app settings' },
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
<ContentHeader
|
<ContentHeader
|
||||||
name={this.props.home.configsDisplay.name}
|
name={this.props.home.configsDisplay.name}
|
||||||
@ -531,7 +559,7 @@ function mapDispatchToProps(dispatch) {
|
|||||||
setErrors,
|
setErrors,
|
||||||
specificDatabaseFetch,
|
specificDatabaseFetch,
|
||||||
},
|
},
|
||||||
dispatch
|
dispatch,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +591,10 @@ HomePage.propTypes = {
|
|||||||
specificDatabaseFetch: PropTypes.func.isRequired,
|
specificDatabaseFetch: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
const withConnect = connect(mapStateToProps, mapDispatchToProps);
|
const withConnect = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
);
|
||||||
|
|
||||||
const withReducer = strapi.injectReducer({ key: 'homePage', reducer, pluginId });
|
const withReducer = strapi.injectReducer({ key: 'homePage', reducer, pluginId });
|
||||||
const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
|
const withSaga = strapi.injectSaga({ key: 'homePage', saga, pluginId });
|
||||||
|
|||||||
@ -25,7 +25,6 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"flag-icon-css": "^2.8.0",
|
"flag-icon-css": "^2.8.0",
|
||||||
"react-select": "^1.0.0-rc.5",
|
|
||||||
"rimraf": "^2.6.3",
|
"rimraf": "^2.6.3",
|
||||||
"strapi-helper-plugin": "3.0.0-alpha.25.2"
|
"strapi-helper-plugin": "3.0.0-alpha.25.2"
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user