From 5b9b5fc3a7960c5872fcad047759745e1dcadd42 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 14 Oct 2020 17:49:27 +0200 Subject: [PATCH] feat: setup congrats page. --- .../Organization/withOrganization.js | 3 + .../Organization/withOrganizationActions.js | 2 + .../Setup/EnsureOrganizationIsNotReady.js | 11 +- .../src/containers/Setup/SetupCongratsPage.js | 50 ++++++++ .../containers/Setup/SetupOrganizationForm.js | 4 + .../src/containers/Setup/SetupRightSection.js | 10 +- client/src/containers/Setup/WorkflowIcon.js | 120 ++++++++++++++++++ .../organizations/organizations.actions.js | 18 ++- .../organizations/organizations.reducers.js | 10 ++ .../organizations/organizations.selectors.js | 7 + .../organizations/organizations.types.js | 2 + .../src/style/pages/register-wizard-page.scss | 42 +++++- 12 files changed, 267 insertions(+), 12 deletions(-) create mode 100644 client/src/containers/Setup/SetupCongratsPage.js create mode 100644 client/src/containers/Setup/WorkflowIcon.js diff --git a/client/src/containers/Organization/withOrganization.js b/client/src/containers/Organization/withOrganization.js index af467dffa..8c4b94769 100644 --- a/client/src/containers/Organization/withOrganization.js +++ b/client/src/containers/Organization/withOrganization.js @@ -7,6 +7,7 @@ import { isOrganizationSeedingFactory, isOrganizationInitializingFactory, isOrganizationSubscribedFactory, + isOrganizationCongratsFactory, } from 'store/organizations/organizations.selectors'; export default (mapState) => { @@ -20,6 +21,7 @@ export default (mapState) => { const isOrganizationSeeding = isOrganizationSeedingFactory(); const isOrganizationSubscribed = isOrganizationSubscribedFactory(); + const isOrganizationCongrats = isOrganizationCongratsFactory(); const mapStateToProps = (state, props) => { const mapped = { @@ -30,6 +32,7 @@ export default (mapState) => { isOrganizationSeeding: isOrganizationInitializing(state, props), isOrganizationInitializing: isOrganizationSeeding(state, props), isOrganizationSubscribed: isOrganizationSubscribed(state, props), + isOrganizationSetupCompleted: isOrganizationCongrats(state, props), }; return (mapState) ? mapState(mapped, state, props) : mapped; }; diff --git a/client/src/containers/Organization/withOrganizationActions.js b/client/src/containers/Organization/withOrganizationActions.js index e44284b3b..7d7f4c075 100644 --- a/client/src/containers/Organization/withOrganizationActions.js +++ b/client/src/containers/Organization/withOrganizationActions.js @@ -3,12 +3,14 @@ import { fetchOrganizations, buildTenant, seedTenant, + setOrganizationSetupCompleted, } from 'store/organizations/organizations.actions'; const mapDispatchToProps = (dispatch) => ({ requestOrganizationBuild: () => dispatch(buildTenant()), requestOrganizationSeed: () => dispatch(seedTenant()), requestAllOrganizations: () => dispatch(fetchOrganizations()), + setOrganizationSetupCompleted: (congrats) => dispatch(setOrganizationSetupCompleted(congrats)), }); export default connect(null, mapDispatchToProps); \ No newline at end of file diff --git a/client/src/containers/Setup/EnsureOrganizationIsNotReady.js b/client/src/containers/Setup/EnsureOrganizationIsNotReady.js index a559b0f07..33bfa6b53 100644 --- a/client/src/containers/Setup/EnsureOrganizationIsNotReady.js +++ b/client/src/containers/Setup/EnsureOrganizationIsNotReady.js @@ -10,8 +10,9 @@ function EnsureOrganizationIsNotReady({ // #withOrganization isOrganizationReady, + isOrganizationSetupCompleted }) { - return (isOrganizationReady) ? ( + return (isOrganizationReady && !isOrganizationSetupCompleted) ? ( ) : children; } @@ -23,5 +24,11 @@ export default compose( connect((state, props) => ({ organizationId: props.currentOrganizationId, })), - withOrganization(({ isOrganizationReady }) => ({ isOrganizationReady })), + withOrganization(({ + isOrganizationReady, + isOrganizationSetupCompleted + }) => ({ + isOrganizationReady, + isOrganizationSetupCompleted + })), )(EnsureOrganizationIsNotReady); \ No newline at end of file diff --git a/client/src/containers/Setup/SetupCongratsPage.js b/client/src/containers/Setup/SetupCongratsPage.js new file mode 100644 index 000000000..51343733b --- /dev/null +++ b/client/src/containers/Setup/SetupCongratsPage.js @@ -0,0 +1,50 @@ +import React, { useCallback } from 'react'; +import { Button, Intent } from '@blueprintjs/core'; +import { FormattedMessage as T } from 'react-intl'; +import { useHistory } from "react-router-dom"; +import WorkflowIcon from './WorkflowIcon'; +import withOrganizationActions from 'containers/Organization/withOrganizationActions'; + +import { compose } from 'utils'; + +function SetupCongratsPage({ + setOrganizationSetupCompleted, +}) { + const history = useHistory(); + + const handleBtnClick = useCallback(() => { + setOrganizationSetupCompleted(false); + history.push('/'); + }, [ + setOrganizationSetupCompleted, + history, + ]); + + return ( +
+
+ +
+ +
+

Congrats! You are ready to go

+ +

+ It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. +

+ + +
+
+ ); +} + +export default compose( + withOrganizationActions, +)(SetupCongratsPage); \ No newline at end of file diff --git a/client/src/containers/Setup/SetupOrganizationForm.js b/client/src/containers/Setup/SetupOrganizationForm.js index be3b4e117..a60f39c4e 100644 --- a/client/src/containers/Setup/SetupOrganizationForm.js +++ b/client/src/containers/Setup/SetupOrganizationForm.js @@ -29,6 +29,7 @@ function SetupOrganizationForm({ requestSubmitOptions, requestOrganizationSeed, wizard, + setOrganizationSetupCompleted }) { const { formatMessage } = useIntl(); const [selected, setSelected] = useState(); @@ -183,6 +184,9 @@ function SetupOrganizationForm({ .then(() => { return requestOrganizationSeed(); }) + .then(() => { + return setOrganizationSetupCompleted(true); + }) .then((response) => { wizard.next(); setSubmitting(false); diff --git a/client/src/containers/Setup/SetupRightSection.js b/client/src/containers/Setup/SetupRightSection.js index d8b1360fb..3913fbaba 100644 --- a/client/src/containers/Setup/SetupRightSection.js +++ b/client/src/containers/Setup/SetupRightSection.js @@ -10,6 +10,7 @@ import withSubscriptions from 'containers/Subscriptions/withSubscriptions'; import SetupSubscriptionForm from './SetupSubscriptionForm'; import SetupOrganizationForm from './SetupOrganizationForm'; import SetupInitializingForm from './SetupInitializingForm'; +import SetupCongratsPage from './SetupCongratsPage'; import withAuthentication from 'containers/Authentication/withAuthentication'; import withOrganization from 'containers/Organization/withOrganization' @@ -25,6 +26,7 @@ function SetupRightSection ({ // #withOrganization isOrganizationInitialized, isOrganizationSeeded, + isOrganizationSetupCompleted, // #withSubscriptions isSubscriptionActive @@ -33,6 +35,7 @@ function SetupRightSection ({ const handleSkip = useCallback(({ step, push }) => { const scenarios = [ + { condition: isOrganizationSetupCompleted, redirectTo: 'congrats' }, { condition: !isSubscriptionActive, redirectTo: 'subscription' }, { condition: isSubscriptionActive && !isOrganizationInitialized, redirectTo: 'initializing' }, { condition: isSubscriptionActive && !isOrganizationSeeded, redirectTo: 'organization' }, @@ -46,6 +49,7 @@ function SetupRightSection ({ isSubscriptionActive, isOrganizationInitialized, isOrganizationSeeded, + isOrganizationSetupCompleted ]); return ( @@ -74,8 +78,8 @@ function SetupRightSection ({ - -

Ice King

+ + @@ -96,10 +100,12 @@ export default compose( organization, isOrganizationInitialized, isOrganizationSeeded, + isOrganizationSetupCompleted }) => ({ organization, isOrganizationInitialized, isOrganizationSeeded, + isOrganizationSetupCompleted })), withSubscriptions(({ isSubscriptionActive, diff --git a/client/src/containers/Setup/WorkflowIcon.js b/client/src/containers/Setup/WorkflowIcon.js new file mode 100644 index 000000000..88eb709aa --- /dev/null +++ b/client/src/containers/Setup/WorkflowIcon.js @@ -0,0 +1,120 @@ +import React from 'react'; + +export default function WorkflowIcon({ + width = '309.566', + height = '356.982', +}) { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/client/src/store/organizations/organizations.actions.js b/client/src/store/organizations/organizations.actions.js index 3cbb39f22..d3db2ba7f 100644 --- a/client/src/store/organizations/organizations.actions.js +++ b/client/src/store/organizations/organizations.actions.js @@ -36,17 +36,29 @@ export const seedTenant = () => (dispatch, getState) => new Promise((resolve, re const organizationId = getState().authentication.organizationId; dispatch({ - type: t.SET_ORGANIZATION_INITIALIZING, + type: t.SET_ORGANIZATION_SEEDING, payload: { organizationId } }); ApiService.post(`organization/seed/`).then((response) => { resolve(response); dispatch({ - type: t.SET_ORGANIZATION_INITIALIZED, + type: t.SET_ORGANIZATION_SEEDED, payload: { organizationId } }); }) .catch((error) => { reject(error.response.data.errors || []); }); -}); \ No newline at end of file +}); + +export const setOrganizationSetupCompleted = (congrats) => (dispatch, getState) => { + const organizationId = getState().authentication.organizationId; + + dispatch({ + type: t.SET_ORGANIZATION_CONGRATS, + payload: { + organizationId, + congrats + }, + }); +}; \ No newline at end of file diff --git a/client/src/store/organizations/organizations.reducers.js b/client/src/store/organizations/organizations.reducers.js index 5f1d1f848..6fa8a44e0 100644 --- a/client/src/store/organizations/organizations.reducers.js +++ b/client/src/store/organizations/organizations.reducers.js @@ -37,6 +37,7 @@ const reducer = createReducer(initialState, { ...(state.data[organizationId] || {}), is_seeding: false, seeded_at: new Date().toISOString(), + is_ready: true, }; }, @@ -58,6 +59,15 @@ const reducer = createReducer(initialState, { initialized_at: new Date().toISOString(), }; }, + + [t.SET_ORGANIZATION_CONGRATS]: (state, action) => { + const { organizationId, congrats } = action.payload; + + state.data[organizationId] = { + ...(state.data[organizationId] || {}), + is_congrats: !!congrats, + }; + } }) export default reducer; \ No newline at end of file diff --git a/client/src/store/organizations/organizations.selectors.js b/client/src/store/organizations/organizations.selectors.js index a8b751a8e..197ca0254 100644 --- a/client/src/store/organizations/organizations.selectors.js +++ b/client/src/store/organizations/organizations.selectors.js @@ -47,4 +47,11 @@ export const isOrganizationSubscribedFactory = () => createSelector( (organization) => { return organization?.subscriptions?.length > 0; } +); + +export const isOrganizationCongratsFactory = () => createSelector( + organizationSelector, + (organization) => { + return !!organization?.is_congrats; + } ) \ No newline at end of file diff --git a/client/src/store/organizations/organizations.types.js b/client/src/store/organizations/organizations.types.js index 924ea7238..25f43f0de 100644 --- a/client/src/store/organizations/organizations.types.js +++ b/client/src/store/organizations/organizations.types.js @@ -7,4 +7,6 @@ export default { SET_ORGANIZATION_INITIALIZED: 'SET_ORGANIZATION_INITIALIZED', SET_ORGANIZATION_INITIALIZING: 'SET_ORGANIZATION_INITIALIZING', + + SET_ORGANIZATION_CONGRATS: 'SET_ORGANIZATION_CONGRATS' }; \ No newline at end of file diff --git a/client/src/style/pages/register-wizard-page.scss b/client/src/style/pages/register-wizard-page.scss index 74e6c8475..1af53e8ea 100644 --- a/client/src/style/pages/register-wizard-page.scss +++ b/client/src/style/pages/register-wizard-page.scss @@ -59,7 +59,7 @@ &__title { font-size: 26px; - font-weight: 600; + font-weight: 700; line-height: normal; margin-bottom: 20px; margin-top: 14px; @@ -145,8 +145,8 @@ font-size: 16px; &::before { - width: 13px; - height: 13px; + width: 11px; + height: 11px; content: ''; line-height: 30px; display: block; @@ -162,7 +162,7 @@ content: ''; position: absolute; background-color: #75859c; - top: 6px; + top: 5px; left: -50%; z-index: -1; } @@ -245,7 +245,7 @@ } } -// setup initializing form +// Setup initializing form .setup-initializing-form { width: 95%; margin: 0 auto; @@ -284,4 +284,36 @@ color: #2e4266; } } +} + +.setup-congrats{ + width: 600px; + margin: 0 auto; + text-align: center; + padding-top: 80px; + + &__page{ + + } + + &__text{ + margin-top: 30px; + + h1{ + color: #2D2B43; + margin-bottom: 12px; + } + .paragraph{ + font-size: 15px; + opacity: 0.85; + margin-bottom: 14px; + } + .bp3-button{ + height: 38px; + padding-left: 25px; + padding-right: 25px; + font-size: 15px; + margin-top: 12px; + } + } } \ No newline at end of file