From 81e1fb2de9eff21c02e9b0176de7057ef61d99eb Mon Sep 17 00:00:00 2001 From: Vincent <89356961+vincentbpro@users.noreply.github.com> Date: Wed, 5 Jan 2022 17:45:43 +0100 Subject: [PATCH] Guided tour/stepper (#12082) * feat: added guided tour context, hook and provider to helper-plugin * feat(guided-tour): using helpers in the admin + init reducer Co-authored-by: ronronscelestes * feedback fixes * created data structure for guided tour state and content Co-authored-by: Vincent * removed closed leaf key from initialState * init guided tour home component * feedback fix fontWeight prop * Stepper, StepNumber, StepLine, Step * wip adding Stepper to homepage * WIP: homepage stepper Co-authored-by: ronronscelestes * fixed grid aligment StepHomepage * feat: added homepage stepper Co-authored-by: ronronscelestes * changed StepLine color if isNotDone + added useGuidedTour mock and updated snapshort for homepage tests * removed guided tour component from homepage until we add local storage and user role detection in the next PR * removed changed from homepage snapshots Co-authored-by: ronronscelestes Co-authored-by: ronronscelestes Co-authored-by: Vincent --- .../GuidedTour/GuidedTourHomepage/index.js | 33 +++++---- .../Stepper/Homepage/StepHomepage.js | 58 +++++++++++++++ .../Stepper/Homepage/StepperHomepage.js | 64 +++++++++++++++++ .../components/GuidedTour/Stepper/StepLine.js | 26 +++++++ .../GuidedTour/Stepper/StepNumber.js | 70 +++++++++++++++++++ .../src/pages/HomePage/tests/index.test.js | 20 ++++++ 6 files changed, 257 insertions(+), 14 deletions(-) create mode 100644 packages/core/admin/admin/src/components/GuidedTour/Stepper/Homepage/StepHomepage.js create mode 100644 packages/core/admin/admin/src/components/GuidedTour/Stepper/Homepage/StepperHomepage.js create mode 100644 packages/core/admin/admin/src/components/GuidedTour/Stepper/StepLine.js create mode 100644 packages/core/admin/admin/src/components/GuidedTour/Stepper/StepNumber.js diff --git a/packages/core/admin/admin/src/components/GuidedTour/GuidedTourHomepage/index.js b/packages/core/admin/admin/src/components/GuidedTour/GuidedTourHomepage/index.js index a55d52a297..7298af03e0 100644 --- a/packages/core/admin/admin/src/components/GuidedTour/GuidedTourHomepage/index.js +++ b/packages/core/admin/admin/src/components/GuidedTour/GuidedTourHomepage/index.js @@ -1,35 +1,40 @@ import React from 'react'; -import { useIntl } from 'react-intl'; import { useGuidedTour } from '@strapi/helper-plugin'; -import { Box } from '@strapi/design-system/Box'; +import { useIntl } from 'react-intl'; import { Stack } from '@strapi/design-system/Stack'; import { Typography } from '@strapi/design-system/Typography'; import { LinkButton } from '@strapi/design-system/LinkButton'; +import ArrowRight from '@strapi/icons/ArrowRight'; +import StepperHomepage from '../Stepper/Homepage/StepperHomepage'; import layout from '../layout'; const GuidedTourHomepage = () => { - const { formatMessage } = useIntl(); const { guidedTourState } = useGuidedTour(); + const { formatMessage } = useIntl(); - const sections = Object.entries(layout).map(([key, val]) => ({ key, ...val.home })); + const sections = Object.entries(layout).map(([key, val]) => ({ + key, + title: val.home.title, + content: ( + }> + {formatMessage(val.home.cta.title)} + + ), + })); const enrichedSections = sections.map(section => ({ isDone: Object.entries(guidedTourState[section.key]).every(([, value]) => value), ...section, })); - const activeSection = enrichedSections.find(section => !section.isDone).key; + const activeSection = enrichedSections.find(section => !section.isDone)?.key; return ( - - {enrichedSections.map(section => ( - - {formatMessage(section.title)} - {section.key === activeSection && ( - {formatMessage(section.cta.title)} - )} - - ))} + + + Guided tour + + ); }; diff --git a/packages/core/admin/admin/src/components/GuidedTour/Stepper/Homepage/StepHomepage.js b/packages/core/admin/admin/src/components/GuidedTour/Stepper/Homepage/StepHomepage.js new file mode 100644 index 0000000000..5f99ecba9a --- /dev/null +++ b/packages/core/admin/admin/src/components/GuidedTour/Stepper/Homepage/StepHomepage.js @@ -0,0 +1,58 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; +import styled from 'styled-components'; +import PropTypes from 'prop-types'; +import { pxToRem } from '@strapi/helper-plugin'; +import { Typography } from '@strapi/design-system/Typography'; +import { Box } from '@strapi/design-system/Box'; +import StepNumber from '../StepNumber'; +import StepLine from '../StepLine'; + +const GridItemAlignCenter = styled(Box)` + align-self: center; +`; + +const GridItemJustifyCenter = styled(Box)` + justify-self: center; +`; + +const StepHomepage = ({ type, title, number, content, hasLine }) => { + const { formatMessage } = useIntl(); + + return ( + <> + + + + + + {formatMessage(title)} + + + + {hasLine && } + + {type === 'isActive' && content} + + ); +}; + +StepHomepage.defaultProps = { + content: undefined, + number: undefined, + type: 'isNotDone', + hasLine: true, +}; + +StepHomepage.propTypes = { + content: PropTypes.node, + number: PropTypes.number, + title: PropTypes.shape({ + id: PropTypes.string, + defaultMessage: PropTypes.string, + }).isRequired, + type: PropTypes.oneOf(['isActive', 'isDone', 'isNotDone']), + hasLine: PropTypes.bool, +}; + +export default StepHomepage; diff --git a/packages/core/admin/admin/src/components/GuidedTour/Stepper/Homepage/StepperHomepage.js b/packages/core/admin/admin/src/components/GuidedTour/Stepper/Homepage/StepperHomepage.js new file mode 100644 index 0000000000..44a26c7301 --- /dev/null +++ b/packages/core/admin/admin/src/components/GuidedTour/Stepper/Homepage/StepperHomepage.js @@ -0,0 +1,64 @@ +import React from 'react'; +import styled from 'styled-components'; +import PropTypes from 'prop-types'; +import { pxToRem } from '@strapi/helper-plugin'; +import { Grid } from '@strapi/design-system/Grid'; +import StepHomepage from './StepHomepage'; + +const GridCustom = styled(Grid)` + gap: ${({ theme }) => `${theme.spaces[3]} ${theme.spaces[4]}`}; + grid-template-columns: ${pxToRem(30)} 1fr; +`; + +const getType = (activeSectionIndex, index) => { + if (activeSectionIndex === -1) { + return 'isDone'; + } + if (index < activeSectionIndex) { + return 'isDone'; + } + if (index > activeSectionIndex) { + return 'isNotDone'; + } + + return 'isActive'; +} + +const StepperHomepage = ({ sections, currentSectionKey }) => { + const activeSectionIndex = sections.findIndex(section => section.key === currentSectionKey); + + return ( + + {sections.map((section, index) => ( + + ))} + + ); +}; + +StepperHomepage.defaultProps = { + currentSectionKey: undefined, +}; + +StepperHomepage.propTypes = { + sections: PropTypes.arrayOf( + PropTypes.shape({ + key: PropTypes.string.isRequired, + title: PropTypes.shape({ + id: PropTypes.string, + defaultMessage: PropTypes.string, + }).isRequired, + content: PropTypes.node, + }) + ).isRequired, + currentSectionKey: PropTypes.string, +}; + +export default StepperHomepage; diff --git a/packages/core/admin/admin/src/components/GuidedTour/Stepper/StepLine.js b/packages/core/admin/admin/src/components/GuidedTour/Stepper/StepLine.js new file mode 100644 index 0000000000..ba288e49e1 --- /dev/null +++ b/packages/core/admin/admin/src/components/GuidedTour/Stepper/StepLine.js @@ -0,0 +1,26 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { pxToRem } from '@strapi/helper-plugin'; +import { Box } from '@strapi/design-system/Box'; + +const StepLine = ({ type, ...props }) => { + return ( + + ); +}; + +StepLine.defaultProps = { + type: 'isNotDone', +}; + +StepLine.propTypes = { + type: PropTypes.oneOf(['isActive', 'isDone', 'isNotDone']), +}; + +export default StepLine; diff --git a/packages/core/admin/admin/src/components/GuidedTour/Stepper/StepNumber.js b/packages/core/admin/admin/src/components/GuidedTour/Stepper/StepNumber.js new file mode 100644 index 0000000000..89d58f53f7 --- /dev/null +++ b/packages/core/admin/admin/src/components/GuidedTour/Stepper/StepNumber.js @@ -0,0 +1,70 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { pxToRem } from '@strapi/helper-plugin'; +import { Flex } from '@strapi/design-system/Flex'; +import { Typography } from '@strapi/design-system/Typography'; +import { Icon } from '@strapi/design-system/Icon'; +import Check from '@strapi/icons/Check'; + +const StepNumber = ({ type, number }) => { + if (type === 'isDone') { + return ( + + + + ); + } + + if (type === 'isActive') { + return ( + + + {number} + + + ); + } + + return ( + + + {number} + + + ); +}; + +StepNumber.defaultProps = { + number: undefined, + type: 'isNotDone', +}; + +StepNumber.propTypes = { + number: PropTypes.number, + type: PropTypes.oneOf(['isActive', 'isDone', 'isNotDone']), +}; + +export default StepNumber; diff --git a/packages/core/admin/admin/src/pages/HomePage/tests/index.test.js b/packages/core/admin/admin/src/pages/HomePage/tests/index.test.js index b8528b41ac..bb095111f5 100644 --- a/packages/core/admin/admin/src/pages/HomePage/tests/index.test.js +++ b/packages/core/admin/admin/src/pages/HomePage/tests/index.test.js @@ -7,6 +7,26 @@ import { ThemeProvider, lightTheme } from '@strapi/design-system'; import HomePage from '../index'; import { useModels } from '../../../hooks'; +jest.mock('@strapi/helper-plugin', () => ({ + ...jest.requireActual('@strapi/helper-plugin'), + useGuidedTour: jest.fn(() => ({ + guidedTourState: { + apiTokens: { + create: false, + success: false, + }, + contentManager: { + create: false, + success: false, + }, + contentTypeBuilder: { + create: false, + success: false, + }, + }, + })), +})); + jest.mock('../../../hooks', () => ({ useModels: jest.fn(), }));