From 163ca8c31744a60d9083d6063264af17af7c6321 Mon Sep 17 00:00:00 2001 From: Ky Date: Thu, 14 Feb 2019 10:36:20 +0100 Subject: [PATCH 1/3] Init video container --- .../src/components/OnboardingList/index.js | 125 ++++++++++++++ .../src/components/OnboardingList/styles.scss | 93 +++++++++++ .../OnboardingList/tests/index.test.js | 11 ++ .../src/components/OnboardingVideos/index.js | 145 +++++++++++++++++ .../components/OnboardingVideos/styles.scss | 152 ++++++++++++++++++ .../admin/src/components/PopupVideo/index.js | 67 ++++++++ .../src/components/PopupVideo/styles.scss | 0 .../admin/src/containers/AdminPage/index.js | 140 +++++++++++----- .../admin/src/containers/HomePage/index.js | 50 ++++-- .../admin/src/containers/HomePage/saga.js | 36 ++--- .../src/containers/Onboarding/actions.js | 26 +++ .../src/containers/Onboarding/constants.js | 10 ++ .../admin/src/containers/Onboarding/index.js | 123 ++++++++++++++ .../src/containers/Onboarding/reducer.js | 33 ++++ .../admin/src/containers/Onboarding/saga.js | 35 ++++ .../src/containers/Onboarding/selectors.js | 25 +++ .../src/containers/Onboarding/styles.scss | 77 +++++++++ .../Onboarding/tests/actions.test.js | 18 +++ .../containers/Onboarding/tests/index.test.js | 10 ++ .../Onboarding/tests/reducer.test.js | 9 ++ .../containers/Onboarding/tests/saga.test.js | 15 ++ .../Onboarding/tests/selectors.test.js | 10 ++ packages/strapi-admin/package.json | 8 +- .../server/middlewares/frontendMiddleware.js | 2 +- .../lib/src/utils/auth.js | 5 +- .../lib/src/utils/request.js | 65 +++++--- .../package.json | 2 +- .../package.json | 2 +- packages/strapi-plugin-email/package.json | 2 +- .../package.json | 2 +- packages/strapi-plugin-upload/package.json | 2 +- .../package.json | 2 +- 32 files changed, 1196 insertions(+), 106 deletions(-) create mode 100644 packages/strapi-admin/admin/src/components/OnboardingList/index.js create mode 100644 packages/strapi-admin/admin/src/components/OnboardingList/styles.scss create mode 100644 packages/strapi-admin/admin/src/components/OnboardingList/tests/index.test.js create mode 100644 packages/strapi-admin/admin/src/components/OnboardingVideos/index.js create mode 100644 packages/strapi-admin/admin/src/components/OnboardingVideos/styles.scss create mode 100644 packages/strapi-admin/admin/src/components/PopupVideo/index.js create mode 100644 packages/strapi-admin/admin/src/components/PopupVideo/styles.scss create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/actions.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/constants.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/index.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/reducer.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/saga.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/selectors.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/styles.scss create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/tests/actions.test.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/tests/index.test.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/tests/reducer.test.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/tests/saga.test.js create mode 100644 packages/strapi-admin/admin/src/containers/Onboarding/tests/selectors.test.js diff --git a/packages/strapi-admin/admin/src/components/OnboardingList/index.js b/packages/strapi-admin/admin/src/components/OnboardingList/index.js new file mode 100644 index 0000000000..0a2b5599b4 --- /dev/null +++ b/packages/strapi-admin/admin/src/components/OnboardingList/index.js @@ -0,0 +1,125 @@ +/** + * + * OnboardingList + * + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; + +import { Modal, ModalHeader, ModalBody } from 'reactstrap'; +import { FormattedMessage } from 'react-intl'; +import PopUpVideo from 'components/PopUpVideo'; +import { Player } from 'video-react'; +import '../../../../node_modules/video-react/dist/video-react.css'; + +import styles from './styles.scss'; +import auth from 'utils/auth'; + +class OnboardingList extends React.Component { + player = React.createRef(); + + componentDidMount() { + //console.log(this.player.current); + this.player.current.subscribeToStateChange( + this.handleChangeState.bind(this), + ); + } + + handleChangeState = (state, prevState) => { + //console.log({ state, prevState }); + + const { duration } = state; + const { id } = this.props; + + if (duration !== prevState.duration) { + this.props.setVideoDuration(id, duration); + } + }; + + afterOpenModal = () => { + // references are now sync'd and can be accessed. + console.log('YOYO'); + + this.player.current.play(); + }; + + render() { + const content = this.props.video.isOpen ? 'yo' : 'ya'; + const { video } = this.props; + + //getVideoDuration = e => {}; + + return ( +
  • +
    + +
    +
    +
    +

    {video.title}

    +

    {this.props.video.duration}

    +
    + + {/* */} + + + + + + +
    + {/* */} +
    +
    +
    + +
    + +
    +
  • + ); + } +} + +OnboardingList.defaultProps = { + video: {}, + setVideoDuration: () => {}, +}; + +OnboardingList.propTypes = { + videos: PropTypes.object, +}; + +export default OnboardingList; diff --git a/packages/strapi-admin/admin/src/components/OnboardingList/styles.scss b/packages/strapi-admin/admin/src/components/OnboardingList/styles.scss new file mode 100644 index 0000000000..4902ca1668 --- /dev/null +++ b/packages/strapi-admin/admin/src/components/OnboardingList/styles.scss @@ -0,0 +1,93 @@ +li.listItem { + display: block; + padding: 10px 15px; + cursor: pointer; + &.finished { + .title { + color: #919bae; + } + .thumbWrapper { + .play { + background-color: #5a9e06; + &::before { + content: '\f00c'; + font-size: 11px; + } + } + } + } + &:hover { + background-color: #f7f8f8; + .title { + color: #0e7de7; + } + } + .txtWrapper, + .thumbWrapper { + display: inline-block; + vertical-align: middle; + } + .thumbWrapper { + width: 55px; + height: 38px; + background-color: #d8d8d8; + border-radius: 2px; + overflow: hidden; + position: relative; + img { + width: 100%; + height: 100%; + } + .play { + width: 20px; + height: 20px; + line-height: 20px; + border-radius: 50%; + background-color: #0e7de7; + position: absolute; + top: 50%; + margin-top: -10px; + left: 50%; + margin-left: -10px; + text-align: center; + &::before { + content: '\f04b'; + font-family: 'FontAwesome'; + font-size: 9px; + color: white; + display: inline-block; + vertical-align: middle; + } + } + } + .txtWrapper { + padding: 0 15px; + p { + font-size: 14px; + font-family: Lato-SemiBold; + } + .time { + font-size: 11px; + color: #919bae; + font-family: Lato-Bold; + } + } +} + +.playerWrapper { + background: red; + width: 100%; + height: 100%; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1051; + display: none; + max-width: 74.5rem; + margin: 16rem auto 3rem calc(50% - 24rem); + &.visible { + display: block; + } +} diff --git a/packages/strapi-admin/admin/src/components/OnboardingList/tests/index.test.js b/packages/strapi-admin/admin/src/components/OnboardingList/tests/index.test.js new file mode 100644 index 0000000000..44d46a6263 --- /dev/null +++ b/packages/strapi-admin/admin/src/components/OnboardingList/tests/index.test.js @@ -0,0 +1,11 @@ +// import OnboardingList from '../index'; + +import expect from 'expect'; +// import { shallow } from 'enzyme'; +// import React from 'react'; + +describe('', () => { + it('Expect to have unit tests specified', () => { + expect(true).toEqual(false); + }); +}); diff --git a/packages/strapi-admin/admin/src/components/OnboardingVideos/index.js b/packages/strapi-admin/admin/src/components/OnboardingVideos/index.js new file mode 100644 index 0000000000..59967e5e55 --- /dev/null +++ b/packages/strapi-admin/admin/src/components/OnboardingVideos/index.js @@ -0,0 +1,145 @@ +/* + * + * Row + * + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import PopUpVideo from 'components/PopUpVideo'; + +import styles from './styles.scss'; +const videos = [ + { + title: 'Create your first content-type', + id: 0, + url: + 'https://s3.amazonaws.com/codecademy-content/courses/React/react_video-cute.mp4', + thumb: + 'https://www.santevet.com/upload/admin/images/article/Chat%202/chaton_seul/santevet_chats_en_location.jpg', + time: '1:32min', + end: true, + }, + { + title: 'Fill your content with data', + id: 1, + url: + 'https://s3.amazonaws.com/codecademy-content/courses/React/react_video-eek.mp4', + thumb: + 'data:image/jpeg;base64,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', + time: '1:32min', + end: false, + }, + { + title: 'Manage the API access', + id: 2, + url: + 'https://s3.amazonaws.com/codecademy-content/courses/React/react_video-slow.mp4', + thumb: + 'https://www.santevet.com/upload/admin/images/article/Chat%202/chaton_seul/santevet_chats_en_location.jpg', + time: '1:32min', + end: false, + }, + { + title: 'Fetch data through the API', + id: 3, + url: + 'https://s3.amazonaws.com/codecademy-content/courses/React/react_video-fast.mp4', + thumb: + 'https://www.santevet.com/upload/admin/images/article/Chat%202/chaton_seul/santevet_chats_en_location.jpg', + time: '1:15min', + end: false, + }, +]; + +class OnboardingVideos extends React.Component { + state = { showVideos: false, showModal: false, video: '' }; + + // componentWillReceiveProps(nextProps) { + // //if (nextProps.pluginActionSucceeded !== this.props.pluginActionSucceeded) { + // this.setState({ showModal: false }); + // //} + // } + componentDidMount() { + this.setState({ showVideos: true }); + } + toggleVideos = e => { + this.setState({ showVideos: !this.state.showVideos }); + }; + + displayModal = e => { + e.preventDefault(); + let video = videos[e.currentTarget.parentNode.key]; + console.log(e.currentTarget.parentNode); + console.log(video); + this.setState({ showModal: !this.state.showModal }); + }; + + render() { + return ( +
    +
    +
    +

    Get started video

    +

    25% completed

    +
    + +
    + +
    + +
    + + + this.setState({ showModal: !this.state.showModal }) + } + popUpWarningType="danger" + onConfirm={this.props.onDeleteConfirm} + src="https://s3.amazonaws.com/codecademy-content/courses/React/react_video-cute.mp4" + /> +
    + ); + } +} + +OnboardingVideos.contextTypes = {}; + +OnboardingVideos.propTypes = {}; + +export default OnboardingVideos; diff --git a/packages/strapi-admin/admin/src/components/OnboardingVideos/styles.scss b/packages/strapi-admin/admin/src/components/OnboardingVideos/styles.scss new file mode 100644 index 0000000000..069e7baaf5 --- /dev/null +++ b/packages/strapi-admin/admin/src/components/OnboardingVideos/styles.scss @@ -0,0 +1,152 @@ +.videosWrapper { + position: fixed; + right: 15px; + bottom: 15px; + button, + button:focus, + a { + cursor: pointer; + outline: 0; + } + p { + margin-bottom: 0; + } + .videosHeader { + padding: 15px 15px 0 15px; + p { + font-family: Lato-Bold; + font-size: 11px; + text-transform: uppercase; + display: inline-block; + width: 50%; + vertical-align: top; + color: #5c5f66; + &:last-of-type { + text-align: right; + color: #5a9e06; + } + } + } + .videosContent { + background-color: white; + margin-bottom: 10px; + margin-right: 15px; + box-shadow: 0 2px 4px 0 #e3e9f3; + border-radius: 3px; + transition: all 0.3s linear; + &.shown { + visibility: visible; + opacity: 1; + } + &.hide { + opacity: 0; + visibility: hidden; + } + ul { + list-style: none; + padding: 10px 0; + li { + &.finished { + .title { + color: #919bae; + } + .thumbWrapper { + .play { + background-color: #5a9e06; + &::before { + content: '\f00c'; + font-size: 11px; + } + } + } + } + a { + display: block; + padding: 10px 15px; + &:hover { + background-color: #f7f8f8; + .title { + color: #0e7de7; + } + } + } + .txtWrapper, + .thumbWrapper { + display: inline-block; + vertical-align: middle; + } + .thumbWrapper { + width: 55px; + height: 38px; + background-color: #d8d8d8; + border-radius: 2px; + overflow: hidden; + position: relative; + img { + width: 100%; + height: 100%; + } + .play { + width: 20px; + height: 20px; + line-height: 20px; + border-radius: 50%; + background-color: #0e7de7; + position: absolute; + top: 50%; + margin-top: -10px; + left: 50%; + margin-left: -10px; + text-align: center; + &::before { + content: '\f04b'; + font-family: 'FontAwesome'; + font-size: 9px; + color: white; + display: inline-block; + vertical-align: middle; + } + } + } + .txtWrapper { + padding: 0 15px; + p { + font-size: 14px; + font-family: Lato-SemiBold; + } + .time { + font-size: 11px; + color: #919bae; + font-family: Lato-Bold; + } + } + } + } + } + .openBtn { + width: 38px; + height: 38px; + float: right; + button { + width: 100%; + height: 100%; + border-radius: 50%; + color: white; + background: #0e7de7; + -webkit-box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1); + -moz-box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1); + box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1); + i:last-of-type { + display: none; + } + &.active { + i:first-of-type { + display: none; + } + i:last-of-type { + display: block; + } + } + } + } +} diff --git a/packages/strapi-admin/admin/src/components/PopupVideo/index.js b/packages/strapi-admin/admin/src/components/PopupVideo/index.js new file mode 100644 index 0000000000..7e1f1c3573 --- /dev/null +++ b/packages/strapi-admin/admin/src/components/PopupVideo/index.js @@ -0,0 +1,67 @@ +/** + * + * PopUpWarning + * + */ + +import React from 'react'; +import PropTypes from 'prop-types'; + +// modal +import { Button, Modal, ModalHeader, ModalBody } from 'reactstrap'; +import { Player } from 'video-react'; +import { FormattedMessage } from 'react-intl'; +import styles from './styles.scss'; + +function PopUpVideo({ + content, + isOpen, + onConfirm, + onlyConfirmButton, + popUpWarningType, + toggleModal, + video, +}) { + return ( +
    + + + {/* + + + + +
    +
    +
    +
    */} +
    + ); +} + +PopUpVideo.propTypes = { + content: PropTypes.shape({ + cancel: PropTypes.string, + confirm: PropTypes.string, + message: PropTypes.string, + title: PropTypes.string, + }), +}; + +PopUpVideo.defaultProps = { + content: { + cancel: 'components.popUpWarning.button.cancel', + confirm: 'components.popUpWarning.button.confirm', + message: 'components.popUpWarning.message', + title: 'components.popUpWarning.title', + }, +}; + +export default PopUpVideo; diff --git a/packages/strapi-admin/admin/src/components/PopupVideo/styles.scss b/packages/strapi-admin/admin/src/components/PopupVideo/styles.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/index.js b/packages/strapi-admin/admin/src/containers/AdminPage/index.js index b92865fe93..c00cb18bff 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/index.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/index.js @@ -18,7 +18,10 @@ import { Switch, Route } from 'react-router-dom'; import { get, includes, isFunction, map, omit } from 'lodash'; import { bindActionCreators, compose } from 'redux'; // Actions required for disabling and enabling the OverlayBlocker -import { disableGlobalOverlayBlocker, enableGlobalOverlayBlocker } from 'actions/overlayBlocker'; +import { + disableGlobalOverlayBlocker, + enableGlobalOverlayBlocker, +} from 'actions/overlayBlocker'; import { pluginLoaded, updatePlugin } from 'containers/App/actions'; import { makeSelectAppPlugins, @@ -35,6 +38,7 @@ import Content from 'containers/Content'; import LocaleToggle from 'containers/LocaleToggle'; import CTAWrapper from 'components/CtaWrapper'; import Header from 'components/Header/index'; +import Onboarding from 'containers/Onboarding'; import HomePage from 'containers/HomePage/Loadable'; import Marketplace from 'containers/Marketplace/Loadable'; import LeftMenu from 'containers/LeftMenu'; @@ -55,7 +59,10 @@ import saga from './saga'; import selectAdminPage from './selectors'; import styles from './styles.scss'; -const PLUGINS_TO_BLOCK_PRODUCTION = ['content-type-builder', 'settings-manager']; +const PLUGINS_TO_BLOCK_PRODUCTION = [ + 'content-type-builder', + 'settings-manager', +]; export class AdminPage extends React.Component { // eslint-disable-line react/prefer-stateless-function @@ -75,7 +82,11 @@ export class AdminPage extends React.Component { } componentDidUpdate(prevProps) { - const { adminPage: { uuid }, location: { pathname }, plugins } = this.props; + const { + adminPage: { uuid }, + location: { pathname }, + plugins, + } = this.props; if (prevProps.location.pathname !== pathname) { this.checkLogin(this.props); @@ -87,11 +98,17 @@ export class AdminPage extends React.Component { const hasAdminPath = ['users-permissions', 'hasAdminUser']; - if (get(prevProps.plugins.toJS(), hasAdminPath) !== get(plugins.toJS(), hasAdminPath)) { + if ( + get(prevProps.plugins.toJS(), hasAdminPath) !== + get(plugins.toJS(), hasAdminPath) + ) { this.checkLogin(this.props, true); } - if (!this.hasUserPluginLoaded(prevProps) && this.hasUserPluginLoaded(this.props)) { + if ( + !this.hasUserPluginLoaded(prevProps) && + this.hasUserPluginLoaded(this.props) + ) { this.checkLogin(this.props); } } @@ -124,26 +141,37 @@ export class AdminPage extends React.Component { this.props.history.push('/plugins/users-permissions/auth/register'); } - if (!props.hasUserPlugin || (auth.getToken() && !this.state.hasAlreadyRegistereOtherPlugins)) { - map(omit(this.props.plugins.toJS(), ['users-permissions', 'email']), plugin => { - switch (true) { - case isFunction(plugin.bootstrap) && isFunction(plugin.pluginRequirements): - plugin - .pluginRequirements(plugin) - .then(plugin => { - return plugin.bootstrap(plugin); - }) - .then(plugin => this.props.pluginLoaded(plugin)); - break; - case isFunction(plugin.pluginRequirements): - plugin.pluginRequirements(plugin).then(plugin => this.props.pluginLoaded(plugin)); - break; - case isFunction(plugin.bootstrap): - plugin.bootstrap(plugin).then(plugin => this.props.pluginLoaded(plugin)); - break; - default: - } - }); + if ( + !props.hasUserPlugin || + (auth.getToken() && !this.state.hasAlreadyRegistereOtherPlugins) + ) { + map( + omit(this.props.plugins.toJS(), ['users-permissions', 'email']), + plugin => { + switch (true) { + case isFunction(plugin.bootstrap) && + isFunction(plugin.pluginRequirements): + plugin + .pluginRequirements(plugin) + .then(plugin => { + return plugin.bootstrap(plugin); + }) + .then(plugin => this.props.pluginLoaded(plugin)); + break; + case isFunction(plugin.pluginRequirements): + plugin + .pluginRequirements(plugin) + .then(plugin => this.props.pluginLoaded(plugin)); + break; + case isFunction(plugin.bootstrap): + plugin + .bootstrap(plugin) + .then(plugin => this.props.pluginLoaded(plugin)); + break; + default: + } + }, + ); this.setState({ hasAlreadyRegistereOtherPlugins: true }); } @@ -153,25 +181,41 @@ export class AdminPage extends React.Component { const { appPlugins } = this.props; return appPlugins.indexOf('users-permissions') !== -1; - } + }; hasUserPluginLoaded = props => - typeof get(props.plugins.toJS(), ['users-permissions', 'hasAdminUser']) !== 'undefined'; + typeof get(props.plugins.toJS(), ['users-permissions', 'hasAdminUser']) !== + 'undefined'; - hasAdminUser = props => get(props.plugins.toJS(), ['users-permissions', 'hasAdminUser']); + hasAdminUser = props => + get(props.plugins.toJS(), ['users-permissions', 'hasAdminUser']); isUrlProtected = props => - !includes(props.location.pathname, get(props.plugins.toJS(), ['users-permissions', 'nonProtectedUrl'])); + !includes( + props.location.pathname, + get(props.plugins.toJS(), ['users-permissions', 'nonProtectedUrl']), + ); - shouldDisplayLogout = () => auth.getToken() && this.props.hasUserPlugin && this.isUrlProtected(this.props); + shouldDisplayLogout = () => + auth.getToken() && + this.props.hasUserPlugin && + this.isUrlProtected(this.props); - showLeftMenu = () => !includes(this.props.location.pathname, 'users-permissions/auth/'); + showLeftMenu = () => + !includes(this.props.location.pathname, 'users-permissions/auth/'); showLoading = () => { - const { isAppLoading, adminPage: { isLoading } } = this.props; + const { + isAppLoading, + adminPage: { isLoading }, + } = this.props; - return isAppLoading || isLoading || (this.hasUserPluginInstalled() && !this.hasUserPluginLoaded(this.props)); - } + return ( + isAppLoading || + isLoading || + (this.hasUserPluginInstalled() && !this.hasUserPluginLoaded(this.props)) + ); + }; retrievePlugins = () => { const { @@ -181,7 +225,9 @@ export class AdminPage extends React.Component { if (currentEnvironment === 'production') { let pluginsToDisplay = plugins; - PLUGINS_TO_BLOCK_PRODUCTION.map(plugin => (pluginsToDisplay = pluginsToDisplay.delete(plugin))); + PLUGINS_TO_BLOCK_PRODUCTION.map( + plugin => (pluginsToDisplay = pluginsToDisplay.delete(plugin)), + ); return pluginsToDisplay; } @@ -222,7 +268,11 @@ export class AdminPage extends React.Component { - + @@ -233,6 +283,8 @@ export class AdminPage extends React.Component { isOpen={this.props.blockApp && this.props.showGlobalAppBlocker} {...this.props.overlayBlockerData} /> + + ); } @@ -268,10 +320,7 @@ AdminPage.propTypes = { history: PropTypes.object.isRequired, isAppLoading: PropTypes.bool, location: PropTypes.object.isRequired, - overlayBlockerData: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.object, - ]), + overlayBlockerData: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), pluginLoaded: PropTypes.func.isRequired, plugins: PropTypes.object.isRequired, showGlobalAppBlocker: PropTypes.bool.isRequired, @@ -302,8 +351,15 @@ function mapDispatchToProps(dispatch) { ); } -const withConnect = connect(mapStateToProps, mapDispatchToProps); +const withConnect = connect( + mapStateToProps, + mapDispatchToProps, +); const withReducer = injectReducer({ key: 'adminPage', reducer }); const withSaga = injectSaga({ key: 'adminPage', saga }); -export default compose(withReducer, withSaga, withConnect)(AdminPage); +export default compose( + withReducer, + withSaga, + withConnect, +)(AdminPage); diff --git a/packages/strapi-admin/admin/src/containers/HomePage/index.js b/packages/strapi-admin/admin/src/containers/HomePage/index.js index 4838c87835..6f95b9b7ed 100644 --- a/packages/strapi-admin/admin/src/containers/HomePage/index.js +++ b/packages/strapi-admin/admin/src/containers/HomePage/index.js @@ -122,7 +122,11 @@ export class HomePage extends React.PureComponent { handleSubmit = e => { e.preventDefault(); - const errors = validateInput(this.props.homePage.body.email, { required: true }, 'email'); + const errors = validateInput( + this.props.homePage.body.email, + { required: true }, + 'email', + ); this.setState({ errors }); if (isEmpty(errors)) { @@ -131,13 +135,18 @@ export class HomePage extends React.PureComponent { }; showFirstBlock = () => - get(this.props.plugins.toJS(), 'content-manager.leftMenuSections.0.links', []).length === 0; + get( + this.props.plugins.toJS(), + 'content-manager.leftMenuSections.0.links', + [], + ).length === 0; renderButton = () => { const data = this.showFirstBlock() ? { className: styles.homePageTutorialButton, - href: 'https://strapi.io/documentation/3.x.x/getting-started/quick-start.html#_3-create-a-content-type', + href: + 'https://strapi.io/documentation/3.x.x/getting-started/quick-start.html#_3-create-a-content-type', id: 'app.components.HomePage.button.quickStart', primary: true, } @@ -158,7 +167,9 @@ export class HomePage extends React.PureComponent { }; render() { - const { homePage: { articles, body } } = this.props; + const { + homePage: { articles, body }, + } = this.props; const WELCOME_AGAIN_BLOCK = [ { title: { @@ -177,7 +188,12 @@ export class HomePage extends React.PureComponent { {this.showFirstBlock() && FIRST_BLOCK.map((value, key) => ( - + ))} {!this.showFirstBlock() && WELCOME_AGAIN_BLOCK.concat(articles).map((value, key) => ( @@ -191,14 +207,21 @@ export class HomePage extends React.PureComponent { ))} {this.renderButton()}
    - {FIRST_BLOCK_LINKS.map((value, key) => )} + {FIRST_BLOCK_LINKS.map((value, key) => ( + + ))}
    -
    - {SOCIAL_LINKS.map((value, key) => )} +
    + {SOCIAL_LINKS.map((value, key) => ( + + ))}
    @@ -265,10 +288,17 @@ function mapDispatchToProps(dispatch) { ); } -const withConnect = connect(mapStateToProps, mapDispatchToProps); +const withConnect = connect( + mapStateToProps, + mapDispatchToProps, +); const withReducer = injectReducer({ key: 'homePage', reducer }); const withSaga = injectSaga({ key: 'homePage', saga }); // export default connect(mapDispatchToProps)(HomePage); -export default compose(withReducer, withSaga, withConnect)(HomePage); +export default compose( + withReducer, + withSaga, + withConnect, +)(HomePage); diff --git a/packages/strapi-admin/admin/src/containers/HomePage/saga.js b/packages/strapi-admin/admin/src/containers/HomePage/saga.js index 881ecb72e3..90fd9ea455 100644 --- a/packages/strapi-admin/admin/src/containers/HomePage/saga.js +++ b/packages/strapi-admin/admin/src/containers/HomePage/saga.js @@ -1,14 +1,7 @@ import 'whatwg-fetch'; import { dropRight, take } from 'lodash'; import removeMd from 'remove-markdown'; -import { - all, - call, - fork, - put, - select, - takeLatest, -} from 'redux-saga/effects'; +import { all, call, fork, put, select, takeLatest } from 'redux-saga/effects'; import request from 'utils/request'; import { getArticlesSucceeded, submitSucceeded } from './actions'; import { GET_ARTICLES, SUBMIT } from './constants'; @@ -19,7 +12,11 @@ function* getArticles() { const articles = yield call(fetchArticles); const posts = articles.posts.reduce((acc, curr) => { // Limit to 200 characters and remove last word. - const content = dropRight(take(removeMd(curr.markdown), 250).join('').split(' ')).join(' '); + const content = dropRight( + take(removeMd(curr.markdown), 250) + .join('') + .split(' '), + ).join(' '); acc.push({ title: curr.title, @@ -31,17 +28,19 @@ function* getArticles() { }, []); yield put(getArticlesSucceeded(posts)); - } catch(err) { + } catch (err) { // Silent } } - function* submit() { try { const body = yield select(makeSelectBody()); - yield call(request, 'https://analytics.strapi.io/register', { method: 'POST', body }); - } catch(err) { + yield call(request, 'https://analytics.strapi.io/register', { + method: 'POST', + body, + }); + } catch (err) { // silent } finally { strapi.notification.success('HomePage.notification.newsLetter.success'); @@ -56,11 +55,12 @@ function* defaultSaga() { ]); } - function fetchArticles() { - return fetch('https://blog.strapi.io/ghost/api/v0.1/posts/?client_id=ghost-frontend&client_secret=1f260788b4ec&limit=2', {}) - .then(resp => { - return resp.json ? resp.json() : resp; - }); + return fetch( + 'https://blog.strapi.io/ghost/api/v0.1/posts/?client_id=ghost-frontend&client_secret=1f260788b4ec&limit=2', + {}, + ).then(resp => { + return resp.json ? resp.json() : resp; + }); } export default defaultSaga; diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/actions.js b/packages/strapi-admin/admin/src/containers/Onboarding/actions.js new file mode 100644 index 0000000000..119c106643 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/actions.js @@ -0,0 +1,26 @@ +/* + * + * Onboarding actions + * + */ + +import { GET_VIDEOS, GET_VIDEOS_SUCCEEDED, ON_CLICK } from './constants'; + +export function getVideos() { + return { + type: GET_VIDEOS, + }; +} + +export function getVideosSucceeded(videos) { + return { + type: GET_VIDEOS_SUCCEEDED, + videos, + }; +} +export function onClick(e) { + return { + type: ON_CLICK, + index: parseInt(e.currentTarget.id, 10), + }; +} diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/constants.js b/packages/strapi-admin/admin/src/containers/Onboarding/constants.js new file mode 100644 index 0000000000..ee8cc7f0e2 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/constants.js @@ -0,0 +1,10 @@ +/* + * + * Onboarding constants + * + */ + +export const GET_VIDEOS = 'StrapiAdmin/Onboarding/GET_VIDEOS'; +export const GET_VIDEOS_SUCCEEDED = + 'StrapiAdmin/Onboarding/GET_VIDEOS_SUCCEEDED'; +export const ON_CLICK = 'StrapiAdmin/Onboarding/ON_CLICK'; diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/index.js b/packages/strapi-admin/admin/src/containers/Onboarding/index.js new file mode 100644 index 0000000000..5bb23e670a --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/index.js @@ -0,0 +1,123 @@ +/** + * + * Onboarding + * + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import cn from 'classnames'; +import { connect } from 'react-redux'; +import { bindActionCreators, compose } from 'redux'; +import { getVideos, onClick } from './actions'; + +import injectSaga from 'utils/injectSaga'; +import injectReducer from 'utils/injectReducer'; +import makeSelectOnboarding from './selectors'; +import reducer from './reducer'; +import saga from './saga'; + +import OnboardingVideo from 'components/OnboardingList'; + +import styles from './styles.scss'; +import auth from 'utils/auth'; + +export class Onboarding extends React.Component { + state = { showVideos: false }; + + componentWillMount() { + this.setState({ showVideos: true }); + this.props.getVideos(); + + localStorage.setItem('videos', JSON.stringify(['video0', 'video1'])); + console.log(localStorage.getItem('videos')); + + if (auth.get('videos')) { + console.log('localStorageExist'); + console.log(auth.get('videos')); + } else { + console.log('localStorageNoooo'); + auth.set('videos', JSON.stringify(['video0', 'video1']), true); + //localStorage.setItem('videos', stringify(['video0', 'video1'])); + } + } + + toggleVideos = e => { + this.setState({ showVideos: !this.state.showVideos }); + }; + + // eslint-disable-line react/prefer-stateless-function + render() { + const { videos, onClick } = this.props; + return ( +
    +
    +
    +

    Get started video

    +

    25% completed

    +
    + +
      + {videos.map((video, i) => { + return ( + + ); + })} +
    +
    + +
    + +
    +
    + ); + } +} + +Onboarding.propTypes = { + getVideos: PropTypes.func.isRequired, +}; + +const mapStateToProps = makeSelectOnboarding(); + +function mapDispatchToProps(dispatch) { + return bindActionCreators({ getVideos, onClick }, dispatch); +} + +const withConnect = connect( + mapStateToProps, + mapDispatchToProps, +); + +/* Remove this line if the container doesn't have a route and + * check the documentation to see how to create the container's store + */ +const withReducer = injectReducer({ key: 'onboarding', reducer }); + +/* Remove the line below the container doesn't have a route and + * check the documentation to see how to create the container's store + */ +const withSaga = injectSaga({ key: 'onboarding', saga }); + +export default compose( + withReducer, + withSaga, + withConnect, +)(Onboarding); diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js b/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js new file mode 100644 index 0000000000..c444b0e633 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js @@ -0,0 +1,33 @@ +/* + * + * Onboarding reducer + * + */ + +import { fromJS } from 'immutable'; +import { GET_VIDEOS_SUCCEEDED, ON_CLICK } from './constants'; + +const initialState = fromJS({ + videos: fromJS([]), +}); + +function onboardingReducer(state = initialState, action) { + switch (action.type) { + case GET_VIDEOS_SUCCEEDED: + return state.update('videos', () => fromJS(action.videos)); + case ON_CLICK: + return state.updateIn(['videos'], list => { + return list.reduce((acc, current, index) => { + if (index === action.index) { + return acc.updateIn([index, 'isOpen'], v => !v); + } + + return acc.updateIn([index, 'isOpen'], () => false); + }, list); + }); + default: + return state; + } +} + +export default onboardingReducer; diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/saga.js b/packages/strapi-admin/admin/src/containers/Onboarding/saga.js new file mode 100644 index 0000000000..8a25679067 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/saga.js @@ -0,0 +1,35 @@ +import { GET_VIDEOS } from './constants'; +import { getVideosSucceeded } from './actions'; +import request from 'utils/request'; + +import { all, call, fork, takeLatest, put } from 'redux-saga/effects'; + +function* getVideos() { + try { + const videos = yield call(request, 'https://strapi.io/videos', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + yield put( + getVideosSucceeded( + videos.map(video => { + video.isOpen = false; + video.duration = null; + + return video; + }), + ), + ); + } catch (err) { + console.log({ err }); + } +} + +function* defaultSaga() { + yield all([fork(takeLatest, GET_VIDEOS, getVideos)]); +} + +export default defaultSaga; diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/selectors.js b/packages/strapi-admin/admin/src/containers/Onboarding/selectors.js new file mode 100644 index 0000000000..2f5dd23c08 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/selectors.js @@ -0,0 +1,25 @@ +import { createSelector } from 'reselect'; + +/** + * Direct selector to the onboarding state domain + */ +const selectOnboardingDomain = () => (state) => state.get('onboarding'); + +/** + * Other specific selectors + */ + + +/** + * Default selector used by Onboarding + */ + +const makeSelectOnboarding = () => createSelector( + selectOnboardingDomain(), + (substate) => substate.toJS() +); + +export default makeSelectOnboarding; +export { + selectOnboardingDomain, +}; diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/styles.scss b/packages/strapi-admin/admin/src/containers/Onboarding/styles.scss new file mode 100644 index 0000000000..cd57c0c77e --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/styles.scss @@ -0,0 +1,77 @@ +.videosWrapper { + position: fixed; + right: 15px; + bottom: 15px; + button, + button:focus, + a { + cursor: pointer; + outline: 0; + } + p { + margin-bottom: 0; + } + .videosHeader { + padding: 15px 15px 0 15px; + p { + font-family: Lato-Bold; + font-size: 11px; + text-transform: uppercase; + display: inline-block; + width: 50%; + vertical-align: top; + color: #5c5f66; + &:last-of-type { + text-align: right; + color: #5a9e06; + } + } + } + .videosContent { + background-color: white; + margin-bottom: 10px; + margin-right: 15px; + box-shadow: 0 2px 4px 0 #e3e9f3; + border-radius: 3px; + transition: all 0.3s linear; + &.shown { + visibility: visible; + opacity: 1; + } + &.hide { + opacity: 0; + visibility: hidden; + } + + ul { + list-style: none; + padding: 10px 0; + } + } + .openBtn { + width: 38px; + height: 38px; + float: right; + button { + width: 100%; + height: 100%; + border-radius: 50%; + color: white; + background: #0e7de7; + -webkit-box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1); + -moz-box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1); + box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1); + i:last-of-type { + display: none; + } + &.active { + i:first-of-type { + display: none; + } + i:last-of-type { + display: block; + } + } + } + } +} diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/tests/actions.test.js b/packages/strapi-admin/admin/src/containers/Onboarding/tests/actions.test.js new file mode 100644 index 0000000000..336c014b91 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/tests/actions.test.js @@ -0,0 +1,18 @@ + +import { + defaultAction, +} from '../actions'; +import { + DEFAULT_ACTION, +} from '../constants'; + +describe('Onboarding actions', () => { + describe('Default Action', () => { + it('has a type of DEFAULT_ACTION', () => { + const expected = { + type: DEFAULT_ACTION, + }; + expect(defaultAction()).toEqual(expected); + }); + }); +}); diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/tests/index.test.js b/packages/strapi-admin/admin/src/containers/Onboarding/tests/index.test.js new file mode 100644 index 0000000000..74a5139bcc --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/tests/index.test.js @@ -0,0 +1,10 @@ +// import React from 'react'; +// import { shallow } from 'enzyme'; + +// import { Onboarding } from '../index'; + +describe('', () => { + it('Expect to have unit tests specified', () => { + expect(true).toEqual(false); + }); +}); diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/tests/reducer.test.js b/packages/strapi-admin/admin/src/containers/Onboarding/tests/reducer.test.js new file mode 100644 index 0000000000..4c16235c3a --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/tests/reducer.test.js @@ -0,0 +1,9 @@ + +import { fromJS } from 'immutable'; +import onboardingReducer from '../reducer'; + +describe('onboardingReducer', () => { + it('returns the initial state', () => { + expect(onboardingReducer(undefined, {})).toEqual(fromJS({})); + }); +}); diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/tests/saga.test.js b/packages/strapi-admin/admin/src/containers/Onboarding/tests/saga.test.js new file mode 100644 index 0000000000..9047074182 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/tests/saga.test.js @@ -0,0 +1,15 @@ +/** + * Test sagas + */ + +/* eslint-disable redux-saga/yield-effects */ +// import { take, call, put, select } from 'redux-saga/effects'; +// import { defaultSaga } from '../saga'; + +// const generator = defaultSaga(); + +describe('defaultSaga Saga', () => { + it('Expect to have unit tests specified', () => { + expect(true).toEqual(false); + }); +}); diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/tests/selectors.test.js b/packages/strapi-admin/admin/src/containers/Onboarding/tests/selectors.test.js new file mode 100644 index 0000000000..999875df75 --- /dev/null +++ b/packages/strapi-admin/admin/src/containers/Onboarding/tests/selectors.test.js @@ -0,0 +1,10 @@ +// import { fromJS } from 'immutable'; +// import { makeSelectOnboardingDomain } from '../selectors'; + +// const selector = makeSelectOnboardingDomain(); + +describe('makeSelectOnboardingDomain', () => { + it('Expect to have unit tests specified', () => { + expect(true).toEqual(false); + }); +}); diff --git a/packages/strapi-admin/package.json b/packages/strapi-admin/package.json index b26f087a28..d84e878e86 100644 --- a/packages/strapi-admin/package.json +++ b/packages/strapi-admin/package.json @@ -25,9 +25,13 @@ "presetup": "node ./scripts/preSetup.js" }, "dependencies": { + "react": "^16.8.1", + "react-dom": "^16.8.1", "react-ga": "^2.4.1", + "redux": "^4.0.1", "remove-markdown": "^0.2.2", - "shelljs": "^0.7.8" + "shelljs": "^0.7.8", + "video-react": "^0.13.2" }, "devDependencies": { "sanitize.css": "^4.1.0", @@ -51,4 +55,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/packages/strapi-helper-plugin/lib/server/middlewares/frontendMiddleware.js b/packages/strapi-helper-plugin/lib/server/middlewares/frontendMiddleware.js index 19b6228af6..3d9db23d93 100644 --- a/packages/strapi-helper-plugin/lib/server/middlewares/frontendMiddleware.js +++ b/packages/strapi-helper-plugin/lib/server/middlewares/frontendMiddleware.js @@ -47,7 +47,7 @@ const addDevMiddlewares = (app, webpackConfig) => { /** * Front-end middleware */ -module.exports = (app) => { +module.exports = app => { const webpackConfig = require('../../internals/webpack/webpack.dev.babel'); // const webpackConfig = require(path.resolve(process.cwd(), 'node_modules', 'strapi-helper-plugin', 'internals', 'webpack', 'webpack.dev.babel')); diff --git a/packages/strapi-helper-plugin/lib/src/utils/auth.js b/packages/strapi-helper-plugin/lib/src/utils/auth.js index e2316c2cb0..809f1cdc80 100644 --- a/packages/strapi-helper-plugin/lib/src/utils/auth.js +++ b/packages/strapi-helper-plugin/lib/src/utils/auth.js @@ -58,11 +58,15 @@ const auth = { }, set(value, key, isLocalStorage) { + console.log(value); + console.log(key); + console.log(isLocalStorage); if (isEmpty(value)) { return null; } if (isLocalStorage && localStorage) { + console.log('Hey'); return localStorage.setItem(key, stringify(value)); } @@ -73,7 +77,6 @@ const auth = { return null; }, - setToken(value = '', isLocalStorage = false, tokenKey = TOKEN_KEY) { return auth.set(value, tokenKey, isLocalStorage); }, diff --git a/packages/strapi-helper-plugin/lib/src/utils/request.js b/packages/strapi-helper-plugin/lib/src/utils/request.js index a83b1606e5..189b1e58fb 100644 --- a/packages/strapi-helper-plugin/lib/src/utils/request.js +++ b/packages/strapi-helper-plugin/lib/src/utils/request.js @@ -9,6 +9,7 @@ import auth from 'utils/auth'; * @return {object} The parsed JSON from the request */ function parseJSON(response) { + // return response; return response.json ? response.json() : response; } @@ -41,21 +42,22 @@ function checkTokenValidity(response) { method: 'GET', headers: { 'Content-Type': 'application/json', - 'Authorization': `Bearer ${auth.getToken()}`, + Authorization: `Bearer ${auth.getToken()}`, }, }; if (auth.getToken()) { - return fetch(`${strapi.backendURL}/user/me`, options) - .then(() => { - if (response.status === 401) { - window.location = `${strapi.remoteURL}/plugins/users-permissions/auth/login`; + return fetch(`${strapi.backendURL}/user/me`, options).then(() => { + if (response.status === 401) { + window.location = `${ + strapi.remoteURL + }/plugins/users-permissions/auth/login`; - auth.clearAppStorage(); - } + auth.clearAppStorage(); + } - return checkStatus(response, false); - }); + return checkStatus(response, false); + }); } } @@ -72,12 +74,12 @@ function formatQueryParams(params) { } /** -* Server restart watcher -* @param response -* @returns {object} the response data -*/ + * Server restart watcher + * @param response + * @returns {object} the response data + */ function serverRestartWatcher(response) { - return new Promise((resolve) => { + return new Promise(resolve => { fetch(`${strapi.backendURL}/_health`, { method: 'HEAD', mode: 'no-cors', @@ -93,8 +95,7 @@ function serverRestartWatcher(response) { }) .catch(() => { setTimeout(() => { - return serverRestartWatcher(response) - .then(resolve); + return serverRestartWatcher(response).then(resolve); }, 100); }); }); @@ -108,22 +109,34 @@ function serverRestartWatcher(response) { * * @return {object} The response data */ -export default function request(url, options = {}, shouldWatchServerRestart = false, stringify = true ) { +export default function request( + url, + options = {}, + shouldWatchServerRestart = false, + stringify = true, +) { // Set headers if (!options.headers) { - options.headers = Object.assign({ - 'Content-Type': 'application/json', - }, options.headers, { - 'X-Forwarded-Host': 'strapi', - }); + options.headers = Object.assign( + { + 'Content-Type': 'application/json', + }, + options.headers, + { + 'X-Forwarded-Host': 'strapi', + }, + ); } const token = auth.getToken(); if (token) { - options.headers = Object.assign({ - 'Authorization': `Bearer ${token}`, - }, options.headers); + options.headers = Object.assign( + { + Authorization: `Bearer ${token}`, + }, + options.headers, + ); } // Add parameters to url @@ -142,7 +155,7 @@ export default function request(url, options = {}, shouldWatchServerRestart = fa return fetch(url, options) .then(checkStatus) .then(parseJSON) - .then((response) => { + .then(response => { if (shouldWatchServerRestart) { // Display the global OverlayBlocker strapi.lockApp(shouldWatchServerRestart); diff --git a/packages/strapi-plugin-content-manager/package.json b/packages/strapi-plugin-content-manager/package.json index 227edb829f..9af6a28629 100644 --- a/packages/strapi-plugin-content-manager/package.json +++ b/packages/strapi-plugin-content-manager/package.json @@ -52,4 +52,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-content-type-builder/package.json b/packages/strapi-plugin-content-type-builder/package.json index 2ea35ec0b5..5020bcb611 100644 --- a/packages/strapi-plugin-content-type-builder/package.json +++ b/packages/strapi-plugin-content-type-builder/package.json @@ -51,4 +51,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-email/package.json b/packages/strapi-plugin-email/package.json index e78a046bff..d711fe6e69 100644 --- a/packages/strapi-plugin-email/package.json +++ b/packages/strapi-plugin-email/package.json @@ -49,4 +49,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-settings-manager/package.json b/packages/strapi-plugin-settings-manager/package.json index bf994342d9..f9b62b5598 100644 --- a/packages/strapi-plugin-settings-manager/package.json +++ b/packages/strapi-plugin-settings-manager/package.json @@ -48,4 +48,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-upload/package.json b/packages/strapi-plugin-upload/package.json index 74bb062789..1e14df5921 100644 --- a/packages/strapi-plugin-upload/package.json +++ b/packages/strapi-plugin-upload/package.json @@ -46,4 +46,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/packages/strapi-plugin-users-permissions/package.json b/packages/strapi-plugin-users-permissions/package.json index 8977fcdd68..2ee82acdd7 100644 --- a/packages/strapi-plugin-users-permissions/package.json +++ b/packages/strapi-plugin-users-permissions/package.json @@ -56,4 +56,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} \ No newline at end of file +} From a2bc9ab609bc5eb9dcc0374239f013b8348201db Mon Sep 17 00:00:00 2001 From: Ky Date: Thu, 14 Feb 2019 19:03:17 +0100 Subject: [PATCH 2/3] retrieve videos from API and update redux store and UI --- .../index.js | 77 ++++++++++--------- .../styles.scss | 38 +++++---- .../tests/index.test.js | 0 .../admin/src/containers/AdminPage/index.js | 3 +- .../src/containers/Onboarding/actions.js | 11 ++- .../src/containers/Onboarding/constants.js | 3 +- .../admin/src/containers/Onboarding/index.js | 27 +++---- .../src/containers/Onboarding/reducer.js | 4 +- .../admin/src/containers/Onboarding/saga.js | 7 +- packages/strapi-admin/package.json | 2 +- .../lib/src/utils/auth.js | 4 - .../package.json | 2 +- .../package.json | 2 +- packages/strapi-plugin-email/package.json | 2 +- .../package.json | 2 +- packages/strapi-plugin-upload/package.json | 2 +- .../package.json | 2 +- 17 files changed, 101 insertions(+), 87 deletions(-) rename packages/strapi-admin/admin/src/components/{OnboardingList => OnboardingVideo}/index.js (61%) rename packages/strapi-admin/admin/src/components/{OnboardingList => OnboardingVideo}/styles.scss (80%) rename packages/strapi-admin/admin/src/components/{OnboardingList => OnboardingVideo}/tests/index.test.js (100%) diff --git a/packages/strapi-admin/admin/src/components/OnboardingList/index.js b/packages/strapi-admin/admin/src/components/OnboardingVideo/index.js similarity index 61% rename from packages/strapi-admin/admin/src/components/OnboardingList/index.js rename to packages/strapi-admin/admin/src/components/OnboardingVideo/index.js index 0a2b5599b4..2000a1f554 100644 --- a/packages/strapi-admin/admin/src/components/OnboardingList/index.js +++ b/packages/strapi-admin/admin/src/components/OnboardingVideo/index.js @@ -10,25 +10,22 @@ import cn from 'classnames'; import { Modal, ModalHeader, ModalBody } from 'reactstrap'; import { FormattedMessage } from 'react-intl'; -import PopUpVideo from 'components/PopUpVideo'; import { Player } from 'video-react'; import '../../../../node_modules/video-react/dist/video-react.css'; import styles from './styles.scss'; -import auth from 'utils/auth'; -class OnboardingList extends React.Component { +class OnboardingVideo extends React.Component { + hiddenPlayer = React.createRef(); player = React.createRef(); componentDidMount() { - //console.log(this.player.current); - this.player.current.subscribeToStateChange( + this.hiddenPlayer.current.subscribeToStateChange( this.handleChangeState.bind(this), ); } handleChangeState = (state, prevState) => { - //console.log({ state, prevState }); const { duration } = state; const { id } = this.props; @@ -45,11 +42,18 @@ class OnboardingList extends React.Component { this.player.current.play(); }; - render() { - const content = this.props.video.isOpen ? 'yo' : 'ya'; - const { video } = this.props; + /*onModalClose = () => { + console.log('CLOSE'); - //getVideoDuration = e => {}; + const { player } = this.player.current.getState(); + const currTime = player.currentTime; + + console.log(currTime); + + };*/ + + render() { + const { video } = this.props; return (
  • {video.title}

    -

    {this.props.video.duration}

    +

    {isNaN(video.duration) ? ' ' : `${Math.floor(video.duration / 60)}:${Math.floor(video.duration)%60}`}

    - {/* */} -
    - {/* */} + preload="auto" + />
    - -
    - -
    + {!video.duration ? ( +
    + +
    + ) : ( +
    + )}
  • ); } } -OnboardingList.defaultProps = { +OnboardingVideo.defaultProps = { video: {}, setVideoDuration: () => {}, }; -OnboardingList.propTypes = { +OnboardingVideo.propTypes = { videos: PropTypes.object, + setVideoDuration: PropTypes.func, }; -export default OnboardingList; +export default OnboardingVideo; diff --git a/packages/strapi-admin/admin/src/components/OnboardingList/styles.scss b/packages/strapi-admin/admin/src/components/OnboardingVideo/styles.scss similarity index 80% rename from packages/strapi-admin/admin/src/components/OnboardingList/styles.scss rename to packages/strapi-admin/admin/src/components/OnboardingVideo/styles.scss index 4902ca1668..0dd4e39b37 100644 --- a/packages/strapi-admin/admin/src/components/OnboardingList/styles.scss +++ b/packages/strapi-admin/admin/src/components/OnboardingVideo/styles.scss @@ -73,21 +73,27 @@ li.listItem { } } } - -.playerWrapper { +.modal .modal-dialog { background: red; - width: 100%; - height: 100%; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1051; - display: none; - max-width: 74.5rem; - margin: 16rem auto 3rem calc(50% - 24rem); - &.visible { - display: block; - } } + +.hiddenPlayerWrapper { + display: none; +} + +.videoModal { + margin-right: auto !important; + margin-left: auto !important; + .videoModalHeader { + border-bottom: 0; + > h5 { + font-family: Lato; + font-weight: bold!important; + font-size: 1.8rem!important; + } + > button { + margin-top: 0; + margin-right: 0; + } + } +} \ No newline at end of file diff --git a/packages/strapi-admin/admin/src/components/OnboardingList/tests/index.test.js b/packages/strapi-admin/admin/src/components/OnboardingVideo/tests/index.test.js similarity index 100% rename from packages/strapi-admin/admin/src/components/OnboardingList/tests/index.test.js rename to packages/strapi-admin/admin/src/components/OnboardingVideo/tests/index.test.js diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/index.js b/packages/strapi-admin/admin/src/containers/AdminPage/index.js index c00cb18bff..d97353e7b0 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/index.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/index.js @@ -283,8 +283,7 @@ export class AdminPage extends React.Component { isOpen={this.props.blockApp && this.props.showGlobalAppBlocker} {...this.props.overlayBlockerData} /> - - +
    ); } diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/actions.js b/packages/strapi-admin/admin/src/containers/Onboarding/actions.js index 119c106643..d635eedf65 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/actions.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/actions.js @@ -4,7 +4,7 @@ * */ -import { GET_VIDEOS, GET_VIDEOS_SUCCEEDED, ON_CLICK } from './constants'; +import { GET_VIDEOS, GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION } from './constants'; export function getVideos() { return { @@ -18,9 +18,18 @@ export function getVideosSucceeded(videos) { videos, }; } + export function onClick(e) { return { type: ON_CLICK, index: parseInt(e.currentTarget.id, 10), }; } + +export function setVideoDuration(id, duration) { + return { + type: SET_VIDEOS_DURATION, + index: parseInt(id, 10), + duration: parseFloat(duration, 10), + }; +} diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/constants.js b/packages/strapi-admin/admin/src/containers/Onboarding/constants.js index ee8cc7f0e2..cc762c36db 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/constants.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/constants.js @@ -7,4 +7,5 @@ export const GET_VIDEOS = 'StrapiAdmin/Onboarding/GET_VIDEOS'; export const GET_VIDEOS_SUCCEEDED = 'StrapiAdmin/Onboarding/GET_VIDEOS_SUCCEEDED'; -export const ON_CLICK = 'StrapiAdmin/Onboarding/ON_CLICK'; + export const ON_CLICK = 'StrapiAdmin/Onboarding/ON_CLICK'; + export const SET_VIDEOS_DURATION = 'StrapiAdmin/Onboarding/SET_VIDEOS_DURATION'; diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/index.js b/packages/strapi-admin/admin/src/containers/Onboarding/index.js index 5bb23e670a..627d783bc2 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/index.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/index.js @@ -9,7 +9,7 @@ import PropTypes from 'prop-types'; import cn from 'classnames'; import { connect } from 'react-redux'; import { bindActionCreators, compose } from 'redux'; -import { getVideos, onClick } from './actions'; +import { getVideos, onClick, setVideoDuration } from './actions'; import injectSaga from 'utils/injectSaga'; import injectReducer from 'utils/injectReducer'; @@ -17,29 +17,21 @@ import makeSelectOnboarding from './selectors'; import reducer from './reducer'; import saga from './saga'; -import OnboardingVideo from 'components/OnboardingList'; +import OnboardingVideo from 'components/OnboardingVideo'; import styles from './styles.scss'; -import auth from 'utils/auth'; export class Onboarding extends React.Component { - state = { showVideos: false }; + state = { showVideos: false, videosTime: [] }; componentWillMount() { this.setState({ showVideos: true }); - this.props.getVideos(); - localStorage.setItem('videos', JSON.stringify(['video0', 'video1'])); - console.log(localStorage.getItem('videos')); - - if (auth.get('videos')) { - console.log('localStorageExist'); - console.log(auth.get('videos')); - } else { - console.log('localStorageNoooo'); - auth.set('videos', JSON.stringify(['video0', 'video1']), true); - //localStorage.setItem('videos', stringify(['video0', 'video1'])); + if (!localStorage.getItem('videos')) { + localStorage.setItem('videos', JSON.stringify([0,0,0,0])); } + + this.props.getVideos(); } toggleVideos = e => { @@ -48,7 +40,7 @@ export class Onboarding extends React.Component { // eslint-disable-line react/prefer-stateless-function render() { - const { videos, onClick } = this.props; + const { videos, onClick, setVideoDuration } = this.props; return (
    ); })} @@ -98,7 +91,7 @@ Onboarding.propTypes = { const mapStateToProps = makeSelectOnboarding(); function mapDispatchToProps(dispatch) { - return bindActionCreators({ getVideos, onClick }, dispatch); + return bindActionCreators({ getVideos, onClick, setVideoDuration }, dispatch); } const withConnect = connect( diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js b/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js index c444b0e633..7cb902e53c 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js @@ -5,7 +5,7 @@ */ import { fromJS } from 'immutable'; -import { GET_VIDEOS_SUCCEEDED, ON_CLICK } from './constants'; +import { GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION } from './constants'; const initialState = fromJS({ videos: fromJS([]), @@ -25,6 +25,8 @@ function onboardingReducer(state = initialState, action) { return acc.updateIn([index, 'isOpen'], () => false); }, list); }); + case SET_VIDEOS_DURATION: + return state.updateIn(['videos', action.index, 'duration'], () => action.duration); default: return state; } diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/saga.js b/packages/strapi-admin/admin/src/containers/Onboarding/saga.js index 8a25679067..99e7db9bbe 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/saga.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/saga.js @@ -15,9 +15,14 @@ function* getVideos() { yield put( getVideosSucceeded( - videos.map(video => { + videos.map((video, index) => { + video.isOpen = false; + /*if (index === 0) { + video.isOpen = true; + }*/ video.duration = null; + video.startTime = localStorage.getItem("videos"); return video; }), diff --git a/packages/strapi-admin/package.json b/packages/strapi-admin/package.json index d84e878e86..8dfb834271 100644 --- a/packages/strapi-admin/package.json +++ b/packages/strapi-admin/package.json @@ -55,4 +55,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/strapi-helper-plugin/lib/src/utils/auth.js b/packages/strapi-helper-plugin/lib/src/utils/auth.js index 809f1cdc80..9212f9d7bf 100644 --- a/packages/strapi-helper-plugin/lib/src/utils/auth.js +++ b/packages/strapi-helper-plugin/lib/src/utils/auth.js @@ -58,15 +58,11 @@ const auth = { }, set(value, key, isLocalStorage) { - console.log(value); - console.log(key); - console.log(isLocalStorage); if (isEmpty(value)) { return null; } if (isLocalStorage && localStorage) { - console.log('Hey'); return localStorage.setItem(key, stringify(value)); } diff --git a/packages/strapi-plugin-content-manager/package.json b/packages/strapi-plugin-content-manager/package.json index 9af6a28629..227edb829f 100644 --- a/packages/strapi-plugin-content-manager/package.json +++ b/packages/strapi-plugin-content-manager/package.json @@ -52,4 +52,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/strapi-plugin-content-type-builder/package.json b/packages/strapi-plugin-content-type-builder/package.json index 5020bcb611..2ea35ec0b5 100644 --- a/packages/strapi-plugin-content-type-builder/package.json +++ b/packages/strapi-plugin-content-type-builder/package.json @@ -51,4 +51,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/strapi-plugin-email/package.json b/packages/strapi-plugin-email/package.json index d711fe6e69..e78a046bff 100644 --- a/packages/strapi-plugin-email/package.json +++ b/packages/strapi-plugin-email/package.json @@ -49,4 +49,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/strapi-plugin-settings-manager/package.json b/packages/strapi-plugin-settings-manager/package.json index f9b62b5598..bf994342d9 100644 --- a/packages/strapi-plugin-settings-manager/package.json +++ b/packages/strapi-plugin-settings-manager/package.json @@ -48,4 +48,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/strapi-plugin-upload/package.json b/packages/strapi-plugin-upload/package.json index 1e14df5921..74bb062789 100644 --- a/packages/strapi-plugin-upload/package.json +++ b/packages/strapi-plugin-upload/package.json @@ -46,4 +46,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/strapi-plugin-users-permissions/package.json b/packages/strapi-plugin-users-permissions/package.json index 2ee82acdd7..8977fcdd68 100644 --- a/packages/strapi-plugin-users-permissions/package.json +++ b/packages/strapi-plugin-users-permissions/package.json @@ -56,4 +56,4 @@ "npm": ">= 6.0.0" }, "license": "MIT" -} +} \ No newline at end of file From 19b6f3ce1e97e087a68df847d8d45ce3b7af235d Mon Sep 17 00:00:00 2001 From: Ky Date: Fri, 15 Feb 2019 18:55:28 +0100 Subject: [PATCH 3/3] Onboarding videos UI and storage - event emit in progress --- .../src/components/OnboardingVideo/index.js | 36 +++++++++--------- .../components/OnboardingVideo/styles.scss | 1 + .../admin/src/containers/AdminPage/actions.js | 8 ++++ .../src/containers/AdminPage/constants.js | 3 +- .../admin/src/containers/AdminPage/index.js | 5 ++- .../admin/src/containers/AdminPage/reducer.js | 4 +- .../admin/src/containers/AdminPage/saga.js | 31 +++++++++++++++- .../src/containers/AdminPage/selectors.js | 6 +++ .../src/containers/Onboarding/actions.js | 14 +++++-- .../src/containers/Onboarding/constants.js | 1 + .../admin/src/containers/Onboarding/index.js | 37 ++++++++++++++----- .../src/containers/Onboarding/reducer.js | 14 ++++++- .../admin/src/containers/Onboarding/saga.js | 28 +++++++++----- .../lib/src/utils/request.js | 18 +++++---- 14 files changed, 153 insertions(+), 53 deletions(-) diff --git a/packages/strapi-admin/admin/src/components/OnboardingVideo/index.js b/packages/strapi-admin/admin/src/components/OnboardingVideo/index.js index 2000a1f554..d6637a2623 100644 --- a/packages/strapi-admin/admin/src/components/OnboardingVideo/index.js +++ b/packages/strapi-admin/admin/src/components/OnboardingVideo/index.js @@ -9,7 +9,6 @@ import PropTypes from 'prop-types'; import cn from 'classnames'; import { Modal, ModalHeader, ModalBody } from 'reactstrap'; -import { FormattedMessage } from 'react-intl'; import { Player } from 'video-react'; import '../../../../node_modules/video-react/dist/video-react.css'; @@ -21,12 +20,11 @@ class OnboardingVideo extends React.Component { componentDidMount() { this.hiddenPlayer.current.subscribeToStateChange( - this.handleChangeState.bind(this), + this.handleChangeState, ); } handleChangeState = (state, prevState) => { - const { duration } = state; const { id } = this.props; @@ -35,22 +33,21 @@ class OnboardingVideo extends React.Component { } }; - afterOpenModal = () => { - // references are now sync'd and can be accessed. - console.log('YOYO'); + handleCurrentTimeChange = (curr) => { + this.props.getVideoCurrentTime(this.props.id, curr); + } + + afterOpenModal = () => { this.player.current.play(); }; - /*onModalClose = () => { - console.log('CLOSE'); + onModalClose = () => { const { player } = this.player.current.getState(); const currTime = player.currentTime; - - console.log(currTime); - - };*/ + this.handleCurrentTimeChange(currTime); + }; render() { const { video } = this.props; @@ -76,39 +73,36 @@ class OnboardingVideo extends React.Component { toggle={this.props.onClick} className={styles.videoModal} onOpened={this.afterOpenModal} - // onClosed={this.onModalClose} + onClosed={this.onModalClose} > - + {video.title}
    - {!video.duration ? ( + {!video.duration && (
    - ) : ( -
    )} ); @@ -116,13 +110,17 @@ class OnboardingVideo extends React.Component { } OnboardingVideo.defaultProps = { + currTime: 0, video: {}, setVideoDuration: () => {}, + getVideoCurrentTime: () => {}, }; OnboardingVideo.propTypes = { + currTime: PropTypes.number, videos: PropTypes.object, setVideoDuration: PropTypes.func, + getVideoCurrentTime: PropTypes.func, }; export default OnboardingVideo; diff --git a/packages/strapi-admin/admin/src/components/OnboardingVideo/styles.scss b/packages/strapi-admin/admin/src/components/OnboardingVideo/styles.scss index 0dd4e39b37..de4583f82e 100644 --- a/packages/strapi-admin/admin/src/components/OnboardingVideo/styles.scss +++ b/packages/strapi-admin/admin/src/components/OnboardingVideo/styles.scss @@ -86,6 +86,7 @@ li.listItem { margin-left: auto !important; .videoModalHeader { border-bottom: 0; + padding-bottom: 0; > h5 { font-family: Lato; font-weight: bold!important; diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/actions.js b/packages/strapi-admin/admin/src/containers/AdminPage/actions.js index c4e04c7f0c..1f96c098bc 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/actions.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/actions.js @@ -6,6 +6,7 @@ import { GET_ADMIN_DATA, GET_ADMIN_DATA_SUCCEEDED, + EMIT_EVENT, } from './constants'; export function getAdminData() { @@ -19,4 +20,11 @@ export function getAdminDataSucceeded(data) { type: GET_ADMIN_DATA_SUCCEEDED, data, }; +} + +export function emitEvent(event) { + return { + type: EMIT_EVENT, + event, + }; } \ No newline at end of file diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/constants.js b/packages/strapi-admin/admin/src/containers/AdminPage/constants.js index f39d32f359..219cb70738 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/constants.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/constants.js @@ -5,4 +5,5 @@ */ export const GET_ADMIN_DATA = 'app/Admin/GET_ADMIN_DATA'; -export const GET_ADMIN_DATA_SUCCEEDED = 'app/Admin/GET_ADMIN_DATA_SUCCEEDED'; \ No newline at end of file +export const GET_ADMIN_DATA_SUCCEEDED = 'app/Admin/GET_ADMIN_DATA_SUCCEEDED'; +export const EMIT_EVENT = 'app/Admin/EMIT_EVENT'; \ No newline at end of file diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/index.js b/packages/strapi-admin/admin/src/containers/AdminPage/index.js index d97353e7b0..0af388b929 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/index.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/index.js @@ -53,7 +53,7 @@ import FullStory from 'components/FullStory'; import auth from 'utils/auth'; import injectReducer from 'utils/injectReducer'; import injectSaga from 'utils/injectSaga'; -import { getAdminData } from './actions'; +import { emitEvent, getAdminData } from './actions'; import reducer from './reducer'; import saga from './saga'; import selectAdminPage from './selectors'; @@ -70,6 +70,7 @@ export class AdminPage extends React.Component { getChildContext = () => ({ disableGlobalOverlayBlocker: this.props.disableGlobalOverlayBlocker, + emitEvent: this.props.emitEvent, enableGlobalOverlayBlocker: this.props.enableGlobalOverlayBlocker, plugins: this.props.plugins, updatePlugin: this.props.updatePlugin, @@ -290,6 +291,7 @@ export class AdminPage extends React.Component { } AdminPage.childContextTypes = { + emitEvent: PropTypes.func, disableGlobalOverlayBlocker: PropTypes.func, enableGlobalOverlayBlocker: PropTypes.func, plugins: PropTypes.object, @@ -341,6 +343,7 @@ function mapDispatchToProps(dispatch) { return bindActionCreators( { disableGlobalOverlayBlocker, + emitEvent, enableGlobalOverlayBlocker, getAdminData, pluginLoaded, diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/reducer.js b/packages/strapi-admin/admin/src/containers/AdminPage/reducer.js index 8f4136e005..70aba13a2d 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/reducer.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/reducer.js @@ -11,11 +11,13 @@ import { } from './constants'; const initialState = fromJS({ - uuid: false, + uuid: true, currentEnvironment: 'development', isLoading: true, layout: Map({}), strapiVersion: '3', + eventName: '', + shouldEmit: true, }); function adminPageReducer(state = initialState, action) { diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/saga.js b/packages/strapi-admin/admin/src/containers/AdminPage/saga.js index f06d28125e..3ebb8b25bf 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/saga.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/saga.js @@ -5,7 +5,35 @@ import { makeSelectAppPlugins } from 'containers/App/selectors'; import { getAdminDataSucceeded, } from './actions'; -import { GET_ADMIN_DATA } from './constants'; +import { makeSelectUuid } from './selectors'; +import { EMIT_EVENT, GET_ADMIN_DATA } from './constants'; + +function* emitter(action) { + try { + const requestURL = 'https://analytics.strapi.io/track'; + const uuid = yield select(makeSelectUuid()); + const { event } = action; + + if (uuid) { + yield call( + fetch, + requestURL, + { + method: 'POST', + body: JSON.stringify({ event, uuid }), + headers: { + 'Content-Type': 'application/json', + }, + }, + false, + true, + { noAuth: true }, + ); + } + } catch(err) { + console.log(err); // eslint-disable-line no-console + } +} function* getData() { try { @@ -32,6 +60,7 @@ function* getData() { function* defaultSaga() { yield all([ fork(takeLatest, GET_ADMIN_DATA, getData), + fork(takeLatest, EMIT_EVENT, emitter), ]); } diff --git a/packages/strapi-admin/admin/src/containers/AdminPage/selectors.js b/packages/strapi-admin/admin/src/containers/AdminPage/selectors.js index 19e863a995..eb267ca369 100644 --- a/packages/strapi-admin/admin/src/containers/AdminPage/selectors.js +++ b/packages/strapi-admin/admin/src/containers/AdminPage/selectors.js @@ -14,9 +14,15 @@ const selectAdminPageDomain = () => state => state.get('adminPage'); * Default selector used by HomePage */ +const makeSelectUuid = () => createSelector( + selectAdminPageDomain(), + substate => substate.get('uuid'), +); + const selectAdminPage = () => createSelector( selectAdminPageDomain(), (substate) => substate.toJS(), ); export default selectAdminPage; +export { makeSelectUuid }; diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/actions.js b/packages/strapi-admin/admin/src/containers/Onboarding/actions.js index d635eedf65..869700caff 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/actions.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/actions.js @@ -4,7 +4,7 @@ * */ -import { GET_VIDEOS, GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION } from './constants'; +import { GET_VIDEOS, GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION, UPDATE_VIDEO_START_TIME } from './constants'; export function getVideos() { return { @@ -26,10 +26,18 @@ export function onClick(e) { }; } -export function setVideoDuration(id, duration) { +export function setVideoDuration(index, duration) { return { type: SET_VIDEOS_DURATION, - index: parseInt(id, 10), + index: parseInt(index, 10), duration: parseFloat(duration, 10), }; } + +export function updateVideoStartTime(index, startTime) { + return { + type: UPDATE_VIDEO_START_TIME, + index: parseInt(index, 10), + startTime: parseFloat(startTime, 10), + }; +} diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/constants.js b/packages/strapi-admin/admin/src/containers/Onboarding/constants.js index cc762c36db..7e3a0fe6c5 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/constants.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/constants.js @@ -9,3 +9,4 @@ export const GET_VIDEOS_SUCCEEDED = 'StrapiAdmin/Onboarding/GET_VIDEOS_SUCCEEDED'; export const ON_CLICK = 'StrapiAdmin/Onboarding/ON_CLICK'; export const SET_VIDEOS_DURATION = 'StrapiAdmin/Onboarding/SET_VIDEOS_DURATION'; + export const UPDATE_VIDEO_START_TIME = 'StrapiAdmin/Onboarding/UPDATE_VIDEO_START_TIME'; diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/index.js b/packages/strapi-admin/admin/src/containers/Onboarding/index.js index 627d783bc2..438edffcdb 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/index.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/index.js @@ -9,7 +9,7 @@ import PropTypes from 'prop-types'; import cn from 'classnames'; import { connect } from 'react-redux'; import { bindActionCreators, compose } from 'redux'; -import { getVideos, onClick, setVideoDuration } from './actions'; +import { getVideos, onClick, setVideoDuration, updateVideoStartTime } from './actions'; import injectSaga from 'utils/injectSaga'; import injectReducer from 'utils/injectReducer'; @@ -22,25 +22,38 @@ import OnboardingVideo from 'components/OnboardingVideo'; import styles from './styles.scss'; export class Onboarding extends React.Component { - state = { showVideos: false, videosTime: [] }; + state = { showVideos: false }; componentWillMount() { this.setState({ showVideos: true }); - - if (!localStorage.getItem('videos')) { - localStorage.setItem('videos', JSON.stringify([0,0,0,0])); - } - this.props.getVideos(); } + + toggleVideos = () => { + // Display videos card + this.setState(prevState => ({ showVideos: !prevState.showVideos })); - toggleVideos = e => { - this.setState({ showVideos: !this.state.showVideos }); + // EmitEvent + const { showVideos } = this.state; + const eventName = showVideos ? 'didOpenGetStartedVideoContainer' : 'didCloseGetStartedVideoContainer'; + this.context.emitEvent(eventName); + }; + + updateLocalStorage = (index, current) => { + // Update store + this.props.updateVideoStartTime(index, current); + + // Update localStorage + let videosTime = JSON.parse(localStorage.getItem('videos')); + videosTime.fill(0); + videosTime[index] = current; + localStorage.setItem('videos', JSON.stringify(videosTime)); }; // eslint-disable-line react/prefer-stateless-function render() { const { videos, onClick, setVideoDuration } = this.props; + return (
    ); })} @@ -83,6 +97,9 @@ export class Onboarding extends React.Component { ); } } +Onboarding.contextTypes = { + emitEvent: PropTypes.func, +}; Onboarding.propTypes = { getVideos: PropTypes.func.isRequired, @@ -91,7 +108,7 @@ Onboarding.propTypes = { const mapStateToProps = makeSelectOnboarding(); function mapDispatchToProps(dispatch) { - return bindActionCreators({ getVideos, onClick, setVideoDuration }, dispatch); + return bindActionCreators({ getVideos, onClick, setVideoDuration, updateVideoStartTime }, dispatch); } const withConnect = connect( diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js b/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js index 7cb902e53c..92b9509aab 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/reducer.js @@ -5,7 +5,7 @@ */ import { fromJS } from 'immutable'; -import { GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION } from './constants'; +import { GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION, UPDATE_VIDEO_START_TIME } from './constants'; const initialState = fromJS({ videos: fromJS([]), @@ -18,6 +18,7 @@ function onboardingReducer(state = initialState, action) { case ON_CLICK: return state.updateIn(['videos'], list => { return list.reduce((acc, current, index) => { + if (index === action.index) { return acc.updateIn([index, 'isOpen'], v => !v); } @@ -27,6 +28,17 @@ function onboardingReducer(state = initialState, action) { }); case SET_VIDEOS_DURATION: return state.updateIn(['videos', action.index, 'duration'], () => action.duration); + case UPDATE_VIDEO_START_TIME: + return state.updateIn(['videos'], list => { + return list.reduce((acc, current, index) => { + + if (index === action.index) { + return acc.updateIn([index, 'startTime'], () => action.startTime); + } + + return acc.updateIn([index, 'startTime'], () => 0); + }, list); + }); default: return state; } diff --git a/packages/strapi-admin/admin/src/containers/Onboarding/saga.js b/packages/strapi-admin/admin/src/containers/Onboarding/saga.js index 99e7db9bbe..e1eb49a052 100644 --- a/packages/strapi-admin/admin/src/containers/Onboarding/saga.js +++ b/packages/strapi-admin/admin/src/containers/Onboarding/saga.js @@ -7,28 +7,38 @@ import { all, call, fork, takeLatest, put } from 'redux-saga/effects'; function* getVideos() { try { const videos = yield call(request, 'https://strapi.io/videos', { - method: 'GET', - headers: { - 'Content-Type': 'application/json', + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, }, - }); + false, + true, + { noAuth: true }, + ); + + let currTimes = Array.apply(null, Array(videos.length)).map(Number.prototype.valueOf,0); + + // Retrieve start time if enable in localStorage + if (localStorage.getItem('videos')) { + currTimes.splice(0, currTimes.length, ...JSON.parse(localStorage.getItem('videos'))); + } else { + localStorage.setItem('videos', JSON.stringify(currTimes)); + } yield put( getVideosSucceeded( videos.map((video, index) => { - video.isOpen = false; - /*if (index === 0) { - video.isOpen = true; - }*/ video.duration = null; - video.startTime = localStorage.getItem("videos"); + video.startTime = currTimes[index]; return video; }), ), ); } catch (err) { + console.log('err'); console.log({ err }); } } diff --git a/packages/strapi-helper-plugin/lib/src/utils/request.js b/packages/strapi-helper-plugin/lib/src/utils/request.js index 189b1e58fb..8e25d72e6e 100644 --- a/packages/strapi-helper-plugin/lib/src/utils/request.js +++ b/packages/strapi-helper-plugin/lib/src/utils/request.js @@ -109,12 +109,16 @@ function serverRestartWatcher(response) { * * @return {object} The response data */ -export default function request( - url, - options = {}, - shouldWatchServerRestart = false, - stringify = true, -) { +export default function request(...args) { + let [url, options = {}, shouldWatchServerRestart, stringify = true, ...rest] = args; + let noAuth; + + try { + [{ noAuth }] = rest; + } catch(err) { + noAuth = false; + } + // Set headers if (!options.headers) { options.headers = Object.assign( @@ -130,7 +134,7 @@ export default function request( const token = auth.getToken(); - if (token) { + if (token && !noAuth) { options.headers = Object.assign( { Authorization: `Bearer ${token}`,