From 7660724ab7950226c2d9d63abd10e9003abb946e Mon Sep 17 00:00:00 2001 From: Timon Rey Turak <31767369+timonrey@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:11:51 +0200 Subject: [PATCH] Adjust avatar component according to Zoe's design (#1615) * refactor: adjust avatar according to Zoes design * chore: add changeset * refactor: use parameters for signup * refactor: use designsystem props * fix: tests * refactor: use correct spacing between signup button and search box * fix: tests * refactor: remove unused dependencies * Toggle login/logout buttons over the `hideLogin` flag in the sso plugin config (#1622) * feat: hide login buttons in the top bar with a flag in the config * chore: add changeset * chore: remove changeset for this PR * chore: fix tests * chore: adjust tests * chore: toggle login buttons via new plugin config parameter * feat: enhance quiz login button + restructure buttons * refactor: rename override components + move hideLogin evaluation to top lvl * chore: change data-test-id in e2e test * chore: add gatsby-ssr.js to sso plugin * refactor: use right test id to identify login button * fix: lint test * chore: adjust e2e common steps * fix: last e2e test * refactor: logout e2e test * chore: add appState/returnTo parameter to signup button --- .changeset/good-vans-prove.md | 5 + .../docs-smoke-test/learn-api/e2e.const.ts | 4 +- .../e2e/docs-smoke-test/learn-api/login.ts | 2 +- .../docs-smoke-test/learn-api/logout.feature | 4 +- .../support/step_definitions/common.steps.ts | 13 +- .../src/layouts/internals/layout-header.js | 4 +- .../{avatar.js => topbar-login-info.js} | 4 +- packages/gatsby-theme-learning/package.json | 1 - .../src/components/quiz.tsx | 6 +- packages/gatsby-theme-sso-ui-kit/README.md | 5 +- .../gatsby-theme-sso-ui-kit/gatsby-browser.js | 1 + .../gatsby-theme-sso-ui-kit/gatsby-node.mjs | 3 + .../gatsby-theme-sso-ui-kit/gatsby-ssr.js | 21 ++ packages/gatsby-theme-sso-ui-kit/package.json | 2 - .../gatsby-theme-docs/overrides/avatar.js | 228 ------------------ .../overrides/topbar-login-info.js | 11 + .../src/components/avatar.js | 131 ++++++++++ .../src/components/config-context.ts | 2 + .../src/components/login-button.tsx | 36 ++- .../src/components/login-component.spec.tsx | 26 +- .../src/components/logout-button.tsx | 20 +- .../src/components/logout-component.spec.tsx | 27 +-- .../src/components/primary-button.tsx | 25 ++ .../src/components/secondary-button.tsx | 18 ++ websites/docs-smoke-test/package.json | 2 +- websites/documentation/gatsby-config.mjs | 1 + .../src/content/configuration/sso.mdx | 5 +- yarn.lock | 54 +---- 28 files changed, 277 insertions(+), 384 deletions(-) create mode 100644 .changeset/good-vans-prove.md rename packages/gatsby-theme-docs/src/overrides/{avatar.js => topbar-login-info.js} (60%) create mode 100644 packages/gatsby-theme-sso-ui-kit/gatsby-ssr.js delete mode 100644 packages/gatsby-theme-sso-ui-kit/src/@commercetools-docs/gatsby-theme-docs/overrides/avatar.js create mode 100644 packages/gatsby-theme-sso-ui-kit/src/@commercetools-docs/gatsby-theme-docs/overrides/topbar-login-info.js create mode 100644 packages/gatsby-theme-sso-ui-kit/src/components/avatar.js create mode 100644 packages/gatsby-theme-sso-ui-kit/src/components/primary-button.tsx create mode 100644 packages/gatsby-theme-sso-ui-kit/src/components/secondary-button.tsx diff --git a/.changeset/good-vans-prove.md b/.changeset/good-vans-prove.md new file mode 100644 index 0000000000..067300507e --- /dev/null +++ b/.changeset/good-vans-prove.md @@ -0,0 +1,5 @@ +--- +'@commercetools-docs/gatsby-theme-sso-ui-kit': minor +--- + +The avatar component was reimplemented and a signup button was introduced. The design of the buttons have changed as well. diff --git a/cypress/e2e/docs-smoke-test/learn-api/e2e.const.ts b/cypress/e2e/docs-smoke-test/learn-api/e2e.const.ts index f2ac3803d2..e5aa27b02b 100644 --- a/cypress/e2e/docs-smoke-test/learn-api/e2e.const.ts +++ b/cypress/e2e/docs-smoke-test/learn-api/e2e.const.ts @@ -2,12 +2,12 @@ export enum ETestId { avatarContainer = 'avatar-container', quizWrapper = 'quiz-wrapper', - loginButton = 'login-button', + loginButton = 'login-quiz-button', + logoutButton = 'logout-button', quizLoading = 'quiz-loading', quizForm = 'quiz-form', quizFormSubmit = 'quiz-form-submit', avatarMenu = 'avatar-menu', - avatarMenuLogout = 'avatar-menu-logout', quizFeedback = 'quiz-feedback', quizQuestionFeedback = 'quiz-question-feedback', tryAgainButton = 'try-again-button', diff --git a/cypress/e2e/docs-smoke-test/learn-api/login.ts b/cypress/e2e/docs-smoke-test/learn-api/login.ts index a778ed2383..12a0d69cb4 100644 --- a/cypress/e2e/docs-smoke-test/learn-api/login.ts +++ b/cypress/e2e/docs-smoke-test/learn-api/login.ts @@ -40,7 +40,7 @@ When(`The user scrolls to the quiz area`, () => { }); Then('The user sees a login button', () => { - cy.get(`button[data-test-id="${ETestId.loginButton}"]`).should('exist'); + cy.get(`div[data-test-id="${ETestId.loginButton}"]`).should('exist'); }); When('The user submits valid auth0 credentials', () => { diff --git a/cypress/e2e/docs-smoke-test/learn-api/logout.feature b/cypress/e2e/docs-smoke-test/learn-api/logout.feature index 4e82a6307b..80d11433af 100644 --- a/cypress/e2e/docs-smoke-test/learn-api/logout.feature +++ b/cypress/e2e/docs-smoke-test/learn-api/logout.feature @@ -3,7 +3,5 @@ Feature: Logout @full @smoke Scenario: User logs out from the quiz page Given The "user" is logged in - And The user clicks the "avatar icon" - And The avatar menu is displayed - And The user clicks the "avatar menu logout button" + And The user clicks the "logout button" Then The user is redirected to "home page" diff --git a/cypress/support/step_definitions/common.steps.ts b/cypress/support/step_definitions/common.steps.ts index 74f782f0d4..fe43f62184 100644 --- a/cypress/support/step_definitions/common.steps.ts +++ b/cypress/support/step_definitions/common.steps.ts @@ -28,13 +28,13 @@ const redirectionStep = (page) => { const clickStep = (clickArea) => { if (clickArea === 'avatar icon') { - cy.get(`[data-test-id="${ETestId.avatarContainer}"]`).click(); + cy.get(`div[data-test-id="${ETestId.avatarContainer}"]`).click(); } - if (clickArea === 'avatar menu logout button') { - cy.get(`[data-test-id="${ETestId.avatarMenuLogout}"]`).click(); + if (clickArea === 'logout button') { + cy.get(`[data-testid="${ETestId.logoutButton}"]`).click(); } if (clickArea === 'login button') { - cy.get(`button[data-test-id="${ETestId.loginButton}"]`).click({ + cy.get(`div[data-test-id="${ETestId.loginButton}"]`).click({ force: true, }); } @@ -75,7 +75,7 @@ const loginToQuizStep = (user: string, isNewAttempt: boolean) => { ).as('fetchAttempt'); } cy.get(`div[data-test-id="${ETestId.quizWrapper}"]`).scrollIntoView(); - cy.get(`button[data-test-id="${ETestId.loginButton}"]`).click({ + cy.get(`div[data-test-id="${ETestId.loginButton}"]`).click({ force: true, }); cy.origin( @@ -107,8 +107,7 @@ Given(`The {string} is logged in with new attempt`, (user: string) => ); Given(`The user logs out`, () => { - cy.get(`[data-test-id="${ETestId.avatarContainer}"]`).click(); - cy.get(`[data-test-id="${ETestId.avatarMenuLogout}"]`).click(); + cy.get(`[data-testid="${ETestId.logoutButton}"]`).click(); }); Given('The avatar menu is displayed', () => { diff --git a/packages/gatsby-theme-docs/src/layouts/internals/layout-header.js b/packages/gatsby-theme-docs/src/layouts/internals/layout-header.js index d6892b5938..ed959bab20 100644 --- a/packages/gatsby-theme-docs/src/layouts/internals/layout-header.js +++ b/packages/gatsby-theme-docs/src/layouts/internals/layout-header.js @@ -12,7 +12,7 @@ import { Icons, } from '@commercetools-docs/ui-kit'; import { SearchDialog, SearchInput, Overlay } from '../../components'; -import PlaceholderAvatarArea from '../../overrides/avatar'; +import PlaceholderLoginInfoArea from '../../overrides/topbar-login-info'; import { useSiteData } from '../../hooks/use-site-data'; import useTopMenuItems from '../../hooks/use-top-menu-items'; import getSiteContextTitleByPath from '../../utils/get-site-context-title'; @@ -304,7 +304,7 @@ const LayoutHeader = forwardRef((props, ref) => { - + diff --git a/packages/gatsby-theme-docs/src/overrides/avatar.js b/packages/gatsby-theme-docs/src/overrides/topbar-login-info.js similarity index 60% rename from packages/gatsby-theme-docs/src/overrides/avatar.js rename to packages/gatsby-theme-docs/src/overrides/topbar-login-info.js index a8914a25c1..66351a4ed5 100644 --- a/packages/gatsby-theme-docs/src/overrides/avatar.js +++ b/packages/gatsby-theme-docs/src/overrides/topbar-login-info.js @@ -1,3 +1,3 @@ // A React component to be rendered in the top bar next to the top menu toggle button -const Avatar = () => null; -export default Avatar; +const LoginInfo = () => null; +export default LoginInfo; diff --git a/packages/gatsby-theme-learning/package.json b/packages/gatsby-theme-learning/package.json index 75addee41c..2b37b6a0be 100644 --- a/packages/gatsby-theme-learning/package.json +++ b/packages/gatsby-theme-learning/package.json @@ -16,7 +16,6 @@ "@auth0/auth0-react": "2.0.1", "@commercetools-docs/gatsby-theme-sso-ui-kit": "21.3.1", "@commercetools-docs/ui-kit": "21.3.1", - "@commercetools-uikit/avatar": "16.0.0", "@commercetools-uikit/checkbox-input": "16.0.0", "@commercetools-uikit/design-system": "16.0.0", "@commercetools-uikit/icons": "16.0.0", diff --git a/packages/gatsby-theme-learning/src/components/quiz.tsx b/packages/gatsby-theme-learning/src/components/quiz.tsx index 211611cf12..7df7995a66 100644 --- a/packages/gatsby-theme-learning/src/components/quiz.tsx +++ b/packages/gatsby-theme-learning/src/components/quiz.tsx @@ -224,11 +224,7 @@ const Quiz = (props: QuizProps) => { Logging you in... ) : ( - + ) ) : ( diff --git a/packages/gatsby-theme-sso-ui-kit/README.md b/packages/gatsby-theme-sso-ui-kit/README.md index 69518fa07a..4eec838dfc 100644 --- a/packages/gatsby-theme-sso-ui-kit/README.md +++ b/packages/gatsby-theme-sso-ui-kit/README.md @@ -5,12 +5,14 @@ The plugin interacts with auth0 authentication provider and therefore needs to b ## Configuration -`gatsby-theme-sso-ui-kit` plugin expects 2 parameters: +`gatsby-theme-sso-ui-kit` plugin expects 3 parameters: - `auth0Domain`: the auth0 application domain url (it is defined in the auth0 management app) - `auth0ClientId`: the auth0 application client id (it is defined in the auth0 management app) - `learnApiBaseUrl`: the learn API base url. It can be omitted if the host running the site matches the api host. +You can also add the optional `hideLogin` parameter if you don't want the login information to be visible in the top bar. + In order to enable the plugin, the following configuration should be added to the `gatsby-config.js` plugin section: ``` @@ -20,6 +22,7 @@ In order to enable the plugin, the following configuration should be added to th auth0Domain: 'auth0domain.dummy.tld', auth0ClientId: 'cliendItString', learnApiBaseUrl: 'https://api.host.tld', + hideLogin: false, }, }, ``` diff --git a/packages/gatsby-theme-sso-ui-kit/gatsby-browser.js b/packages/gatsby-theme-sso-ui-kit/gatsby-browser.js index b1ca07a692..f7b18f8f30 100644 --- a/packages/gatsby-theme-sso-ui-kit/gatsby-browser.js +++ b/packages/gatsby-theme-sso-ui-kit/gatsby-browser.js @@ -19,6 +19,7 @@ export const wrapRootElement = ({ element }, pluginOptions) => { learnApiBaseUrl: pluginOptions.learnApiBaseUrl, auth0Domain: pluginOptions.auth0Domain, auth0ClientId: pluginOptions.auth0ClientId, + hideLogin: pluginOptions.hideLogin || false, }} > { .allow('') .default('') .description(`Learn API base url`), + hideLogin: Joi.bool().description( + `Flag that determines if the login information are visible in the top bar` + ), }); }; diff --git a/packages/gatsby-theme-sso-ui-kit/gatsby-ssr.js b/packages/gatsby-theme-sso-ui-kit/gatsby-ssr.js new file mode 100644 index 0000000000..14cef2b25d --- /dev/null +++ b/packages/gatsby-theme-sso-ui-kit/gatsby-ssr.js @@ -0,0 +1,21 @@ +import ConfigContext from './src/components/config-context'; + +export const wrapRootElement = ({ element }, pluginOptions) => { + const isPluginEnabled = + pluginOptions.auth0Domain && pluginOptions.auth0ClientId; + + return isPluginEnabled ? ( + + {element} + + ) : ( + <>{element} + ); +}; diff --git a/packages/gatsby-theme-sso-ui-kit/package.json b/packages/gatsby-theme-sso-ui-kit/package.json index 223e8f8695..aad57ef88a 100644 --- a/packages/gatsby-theme-sso-ui-kit/package.json +++ b/packages/gatsby-theme-sso-ui-kit/package.json @@ -15,13 +15,11 @@ "dependencies": { "@auth0/auth0-react": "2.0.1", "@commercetools-docs/ui-kit": "21.3.1", - "@commercetools-uikit/avatar": "16.0.0", "@commercetools-uikit/icons": "16.0.0", "@commercetools-uikit/secondary-button": "16.0.0", "@commercetools-uikit/spacings": "16.0.0", "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", - "downshift": "7.6.0", "md5": "2.3.0", "react-intl": "^6.2.8", "react-router-dom": "6.9.0" diff --git a/packages/gatsby-theme-sso-ui-kit/src/@commercetools-docs/gatsby-theme-docs/overrides/avatar.js b/packages/gatsby-theme-sso-ui-kit/src/@commercetools-docs/gatsby-theme-docs/overrides/avatar.js deleted file mode 100644 index 750b6c08d6..0000000000 --- a/packages/gatsby-theme-sso-ui-kit/src/@commercetools-docs/gatsby-theme-docs/overrides/avatar.js +++ /dev/null @@ -1,228 +0,0 @@ -// A React component to be rendered in the top bar next to the top menu toggle button -import { useEffect, useState, useContext } from 'react'; -import PropTypes from 'prop-types'; -import md5 from 'md5'; -import { useSelect } from 'downshift'; -import styled from '@emotion/styled'; -import { useAuth0 } from '@auth0/auth0-react'; -import Avatar from '@commercetools-uikit/avatar'; -import Spacings from '@commercetools-uikit/spacings'; -import { designSystem } from '@commercetools-docs/ui-kit'; -import { AngleDownIcon, AngleUpIcon } from '@commercetools-uikit/icons'; -import ConfigContext from '../../../components/config-context'; -import { - getAvatarInitials, - getLogoutReturnUrl, -} from '../../../components/sso.utils'; -import CommercetoolsIDIcon from '../../../icons/commercetools_ID_logo.svg'; -import { - AUTH0_CLAIM_DISPLAYNAME, - AUTH0_CLAIM_GLOBAL_ACCOUNT_NAME, -} from '../../../sso.const'; - -const AvatarContainer = styled.div` - display: flex; - flex-direction: column; - align-items: flex-end; -`; - -const AvatarButton = styled.button` - cursor: pointer; - border: none; - padding: 0; - display: flex; - background: transparent; -`; - -const DropdownContainer = styled.div` - color: #666666; - min-width: 200px; - padding: ${designSystem.dimensions.spacings.s}; - border: 1px solid ${designSystem.colors.light.borderInput}; - position: absolute; - margin-top: 30px; - background-color: ${designSystem.colors.light.surfacePrimary}; - border-radius: ${designSystem.tokens.borderRadiusForCard}; - box-shadow: ${designSystem.tokens.shadowForBetaFlag}; -`; - -const CommercetoolsIDLogo = styled.div` - height: 42px; - width: 70px; - margin: 0 auto; -`; - -const LogoutSection = styled.div` - border-top: 1px solid ${designSystem.colors.light.borderInput}; - :hover { - background-color: ${designSystem.colors.light.surfaceSecondary1}; - } -`; - -const LogoutButton = styled.button` - color: #666666; - font-size: ${designSystem.typography.fontSizes.extraSmall}; - padding: 6px 0 0 0; - cursor: pointer; - border: none; - width: 100%; - background: transparent; -`; - -const MenuItem = styled.div` - padding: 0; - font-family: ${designSystem.typography.fontFamilies.primary}; - font-size: ${designSystem.typography.fontSizes.extraSmall}; - text-align: ${(props) => props.align || 'left'}; - font-weight: ${(props) => - props.type === 'primary' - ? designSystem.typography.fontWeights.bold - : designSystem.typography.fontWeights.regular}; -`; - -const UserAvatar = (props) => { - const [isMouseOver, setIsMouseOver] = useState(false); - const email = props.userData.find( - (item) => Object.keys(item)[0] === 'email' - )?.email; - const name = props.userData.find( - (item) => Object.keys(item)[0] === 'name' - )?.name; - const avatarInitials = getAvatarInitials(name || email); - return ( -
setIsMouseOver(true)} - onMouseOut={() => setIsMouseOver(false)} - > - - - {props.isOpen ? ( - - ) : ( - - )} - -
- ); -}; -UserAvatar.displayName = 'UserAvatar'; - -const UserInformation = (props) => { - const { learnApiBaseUrl } = useContext(ConfigContext); - const { isOpen, getToggleButtonProps, getMenuProps } = useSelect({ - items: Object.values(props.userData), - }); - - return ( - - - - - {isOpen && ( - - - - - - {props.userData.map((obj, index) => { - const [key, data] = Object.entries(obj)[0]; - return ( - - {data} - - ); - })} - - - - props.logout({ - logoutParams: { - returnTo: getLogoutReturnUrl( - learnApiBaseUrl, - document.location - ), - }, - }) - } - > - Logout - - - - - )} - - ); -}; - -UserInformation.displayName = 'UserInformation'; - -const UserProfile = () => { - const { isAuthenticated, logout, getIdTokenClaims } = useAuth0(); - const [customClaims, setCustomClaims] = useState({}); - useEffect(() => { - const fetchCustomClaims = async () => { - try { - const results = await getIdTokenClaims(); - setCustomClaims(results); - } catch (error) { - console.error('error fetching custom claims'); - } - }; - if (isAuthenticated) { - fetchCustomClaims(); - } - }, [isAuthenticated, getIdTokenClaims]); - - if (isAuthenticated) { - const userData = []; - - if (customClaims[AUTH0_CLAIM_DISPLAYNAME] !== customClaims.email) { - // we do have a real full name - userData.push({ name: customClaims[AUTH0_CLAIM_DISPLAYNAME] }); - } - - userData.push({ email: customClaims.email }); - - if (customClaims[AUTH0_CLAIM_GLOBAL_ACCOUNT_NAME]) { - userData.push({ - association: customClaims[AUTH0_CLAIM_GLOBAL_ACCOUNT_NAME], - }); - } - - return ; - } - return null; -}; - -UserProfile.displayName = 'UserProfile'; - -UserAvatar.propTypes = { - isOpen: PropTypes.bool.isRequired, - userData: PropTypes.array.isRequired, -}; - -UserInformation.propTypes = { - userData: PropTypes.array.isRequired, - logout: PropTypes.func.isRequired, -}; - -export default UserProfile; diff --git a/packages/gatsby-theme-sso-ui-kit/src/@commercetools-docs/gatsby-theme-docs/overrides/topbar-login-info.js b/packages/gatsby-theme-sso-ui-kit/src/@commercetools-docs/gatsby-theme-docs/overrides/topbar-login-info.js new file mode 100644 index 0000000000..ea425381ff --- /dev/null +++ b/packages/gatsby-theme-sso-ui-kit/src/@commercetools-docs/gatsby-theme-docs/overrides/topbar-login-info.js @@ -0,0 +1,11 @@ +// A React component to be rendered in the top bar next to the top menu toggle button +import { useContext } from 'react'; +import ConfigContext from '../../../components/config-context'; +import UserProfile from '../../../components/avatar'; + +const LoginInfo = () => { + const { hideLogin } = useContext(ConfigContext); + return hideLogin ? null : ; +}; + +export default LoginInfo; diff --git a/packages/gatsby-theme-sso-ui-kit/src/components/avatar.js b/packages/gatsby-theme-sso-ui-kit/src/components/avatar.js new file mode 100644 index 0000000000..89dbb4932c --- /dev/null +++ b/packages/gatsby-theme-sso-ui-kit/src/components/avatar.js @@ -0,0 +1,131 @@ +// A React component to be rendered in the top bar next to the top menu toggle button +import { useEffect, useState } from 'react'; +import PropTypes from 'prop-types'; +import styled from '@emotion/styled'; +import { useAuth0 } from '@auth0/auth0-react'; +import Spacings from '@commercetools-uikit/spacings'; +import { designSystem } from '@commercetools-docs/ui-kit'; +import { GraduationCapIcon } from '@commercetools-uikit/icons'; +import LoginButton from './login-button'; +import LogoutButton from './logout-button'; +import PrimaryButton from './primary-button'; +import { getAvatarInitials } from './sso.utils'; +import { AUTH0_CLAIM_DISPLAYNAME } from '../sso.const'; + +const AvatarContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; + padding-right: ${designSystem.dimensions.spacings.s}; +`; + +const Avatar = styled.div` + width: ${designSystem.typography.lineHeights.cardSmallTitle}; + height: ${designSystem.typography.lineHeights.cardSmallTitle}; + color: white; + background-color: ${designSystem.colors.light.link}; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; +`; + +const UserAvatar = (props) => { + const email = props.userData.find( + (item) => Object.keys(item)[0] === 'email' + )?.email; + const name = props.userData.find( + (item) => Object.keys(item)[0] === 'name' + )?.name; + const avatarInitials = getAvatarInitials(name || email).map((initial) => + initial.toUpperCase() + ); + return ( + + {avatarInitials} + + ); +}; +UserAvatar.displayName = 'UserAvatar'; + +const LoggedInState = (props) => { + return ( + + + + + ); +}; + +LoggedInState.displayName = 'LoggedInState'; + +const LoggedOutState = () => { + const { loginWithRedirect } = useAuth0(); + + return ( + + + + loginWithRedirect({ + appState: { + returnTo: window.location.pathname, + }, + authorizationParams: { + screen_hint: 'signup', + }, + }) + } + > + +

Sign up

+
+
+ ); +}; + +LoggedOutState.displayName = 'LoggedOutState'; + +const UserProfile = () => { + const { isAuthenticated, logout, getIdTokenClaims } = useAuth0(); + const [customClaims, setCustomClaims] = useState({}); + useEffect(() => { + const fetchCustomClaims = async () => { + try { + const results = await getIdTokenClaims(); + setCustomClaims(results); + } catch (error) { + console.error('error fetching custom claims'); + } + }; + if (isAuthenticated) { + fetchCustomClaims(); + } + }, [isAuthenticated, getIdTokenClaims]); + + if (isAuthenticated) { + const userData = []; + + if (customClaims[AUTH0_CLAIM_DISPLAYNAME] !== customClaims.email) { + // we do have a real full name + userData.push({ name: customClaims[AUTH0_CLAIM_DISPLAYNAME] }); + } + + userData.push({ email: customClaims.email }); + + return ; + } + return ; +}; + +UserProfile.displayName = 'UserProfile'; + +UserAvatar.propTypes = { + userData: PropTypes.array.isRequired, +}; + +LoggedInState.propTypes = { + userData: PropTypes.array.isRequired, +}; + +export default UserProfile; diff --git a/packages/gatsby-theme-sso-ui-kit/src/components/config-context.ts b/packages/gatsby-theme-sso-ui-kit/src/components/config-context.ts index dc37fa5fd0..f1db929d50 100644 --- a/packages/gatsby-theme-sso-ui-kit/src/components/config-context.ts +++ b/packages/gatsby-theme-sso-ui-kit/src/components/config-context.ts @@ -4,12 +4,14 @@ export type Config = { learnApiBaseUrl: string; auth0Domain: string; auth0ClientId: string; + hideLogin: boolean; }; const ConfigContext = createContext({ learnApiBaseUrl: '', auth0Domain: '', auth0ClientId: '', + hideLogin: false, }); export default ConfigContext; diff --git a/packages/gatsby-theme-sso-ui-kit/src/components/login-button.tsx b/packages/gatsby-theme-sso-ui-kit/src/components/login-button.tsx index 61134e92e8..67e90c3a56 100644 --- a/packages/gatsby-theme-sso-ui-kit/src/components/login-button.tsx +++ b/packages/gatsby-theme-sso-ui-kit/src/components/login-button.tsx @@ -1,19 +1,13 @@ import React from 'react'; import { useAuth0 } from '@auth0/auth0-react'; -import SecondaryButton from '@commercetools-uikit/secondary-button'; import { UserFilledIcon } from '@commercetools-uikit/icons'; +import PrimaryButton from './primary-button'; +import SecondaryButton from './secondary-button'; type LoginButtonProps = { - label: string; - icon: JSX.Element; quizId?: string; }; -const defaultProps: Pick = { - label: 'Log In', - icon: , -}; - const LoginButton = (props: LoginButtonProps) => { const { loginWithRedirect } = useAuth0(); @@ -30,12 +24,27 @@ const LoginButton = (props: LoginButtonProps) => { : window.location.pathname; }; + if (props.quizId) { + return ( + + loginWithRedirect({ + appState: { + returnTo: getTargetUrl(), + }, + }) + } + > + +

Login to start the quiz

+
+ ); + } + return ( loginWithRedirect({ appState: { @@ -43,9 +52,10 @@ const LoginButton = (props: LoginButtonProps) => { }, }) } - /> + > + Login + ); }; -LoginButton.defaultProps = defaultProps; export default LoginButton; diff --git a/packages/gatsby-theme-sso-ui-kit/src/components/login-component.spec.tsx b/packages/gatsby-theme-sso-ui-kit/src/components/login-component.spec.tsx index 91f342f8e4..708ae09b52 100644 --- a/packages/gatsby-theme-sso-ui-kit/src/components/login-component.spec.tsx +++ b/packages/gatsby-theme-sso-ui-kit/src/components/login-component.spec.tsx @@ -10,37 +10,13 @@ jest.mock('@auth0/auth0-react', () => ({ })); describe('login-button', () => { - const DEFAULT_LABEL = 'Log In'; + const DEFAULT_LABEL = 'Login'; it('should render login-component with default text if no label is specified', () => { render(); const loginButtonElement = screen.getByTestId('login-button'); expect(loginButtonElement).toBeInTheDocument(); expect(loginButtonElement).toHaveTextContent(DEFAULT_LABEL); }); - - it('should render login-component with specified label', () => { - const label = 'Click me please!'; - render(); - const loginButtonElement = screen.getByTestId('login-button'); - expect(loginButtonElement).toBeInTheDocument(); - expect(loginButtonElement).toHaveTextContent(label); - }); - - it('should render the default icon if no icon is specified', () => { - render(); - const defaultIcon = screen.getByTestId('default-icon'); - expect(defaultIcon).toBeInTheDocument(); - }); - - it('should render the specified icon', () => { - const CusotomIcon = () => { - return
; - }; - render(} />); - const defaultIcon = screen.getByTestId('custom-icon'); - expect(defaultIcon).toBeInTheDocument(); - }); - it('should invoke loginWithRedirect with the expected url when clicked', () => { const expectedLoginWithRedirect = { appState: { diff --git a/packages/gatsby-theme-sso-ui-kit/src/components/logout-button.tsx b/packages/gatsby-theme-sso-ui-kit/src/components/logout-button.tsx index 9c10554df9..f8513fe654 100644 --- a/packages/gatsby-theme-sso-ui-kit/src/components/logout-button.tsx +++ b/packages/gatsby-theme-sso-ui-kit/src/components/logout-button.tsx @@ -1,29 +1,16 @@ import { useContext } from 'react'; import { useAuth0 } from '@auth0/auth0-react'; -import SecondaryButton from '@commercetools-uikit/secondary-button'; -import { LogoutIcon } from '@commercetools-uikit/icons'; import { getLogoutReturnUrl } from './sso.utils'; import ConfigContext from './config-context'; +import SecondaryButton from './secondary-button'; -type LogoutButtonProps = { - label: string; - icon: JSX.Element; -}; - -const defaultProps: Pick = { - label: 'Log Out', - icon: , -}; - -const LogoutButton = (props: LogoutButtonProps) => { +const LogoutButton = () => { const { learnApiBaseUrl } = useContext(ConfigContext); const { logout } = useAuth0(); return ( logout({ logoutParams: { @@ -32,10 +19,9 @@ const LogoutButton = (props: LogoutButtonProps) => { }) } > - Log Out + Log out ); }; -LogoutButton.defaultProps = defaultProps; export default LogoutButton; diff --git a/packages/gatsby-theme-sso-ui-kit/src/components/logout-component.spec.tsx b/packages/gatsby-theme-sso-ui-kit/src/components/logout-component.spec.tsx index 530550c244..4593e311a1 100644 --- a/packages/gatsby-theme-sso-ui-kit/src/components/logout-component.spec.tsx +++ b/packages/gatsby-theme-sso-ui-kit/src/components/logout-component.spec.tsx @@ -9,37 +9,14 @@ jest.mock('@auth0/auth0-react', () => ({ })); describe('logout-button', () => { - const DEFAULT_LABEL = 'Log Out'; - it('should render logout-component with default text if no label is specified', () => { + const DEFAULT_LABEL = 'Log out'; + it('should render logout-component with specified text', () => { render(); const logoutButtonElement = screen.getByTestId('logout-button'); expect(logoutButtonElement).toBeInTheDocument(); expect(logoutButtonElement).toHaveTextContent(DEFAULT_LABEL); }); - it('should render logout-component with specified label', () => { - const label = 'Click me please!'; - render(); - const logoutButtonElement = screen.getByTestId('logout-button'); - expect(logoutButtonElement).toBeInTheDocument(); - expect(logoutButtonElement).toHaveTextContent(label); - }); - - it('should render the default icon if no icon is specified', () => { - render(); - const defaultIcon = screen.getByTestId('default-icon'); - expect(defaultIcon).toBeInTheDocument(); - }); - - it('should render the specified icon', () => { - const CusotomIcon = () => { - return
; - }; - render(} />); - const customIcon = screen.getByTestId('custom-icon'); - expect(customIcon).toBeInTheDocument(); - }); - it('should invoke logout with the expected url when clicked', () => { const expectedLogout = { logoutParams: { diff --git a/packages/gatsby-theme-sso-ui-kit/src/components/primary-button.tsx b/packages/gatsby-theme-sso-ui-kit/src/components/primary-button.tsx new file mode 100644 index 0000000000..ed18a0e26e --- /dev/null +++ b/packages/gatsby-theme-sso-ui-kit/src/components/primary-button.tsx @@ -0,0 +1,25 @@ +import styled from '@emotion/styled'; +import { designSystem } from '@commercetools-docs/ui-kit'; + +const PrimaryButton = styled.div` + display: flex; + flex-direction: row; + align-items: center; + padding: ${designSystem.dimensions.spacings.xs} + ${designSystem.dimensions.spacings.m}; + gap: ${designSystem.dimensions.spacings.s}; + color: white; + cursor: pointer; + background: ${designSystem.colors.light.link}; + box-shadow: ${designSystem.tokens.shadowForBetaFlag}; + border-radius: 6px; + + p { + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: 18px; + } +`; + +export default PrimaryButton; diff --git a/packages/gatsby-theme-sso-ui-kit/src/components/secondary-button.tsx b/packages/gatsby-theme-sso-ui-kit/src/components/secondary-button.tsx new file mode 100644 index 0000000000..89a3937d8a --- /dev/null +++ b/packages/gatsby-theme-sso-ui-kit/src/components/secondary-button.tsx @@ -0,0 +1,18 @@ +import styled from '@emotion/styled'; +import { designSystem } from '@commercetools-docs/ui-kit'; + +const SecondaryButton = styled.button` + padding-right: 16px; + color: ${designSystem.colors.light.link}; + font-size: ${designSystem.typography.fontSizes.small}; + outline: none !important; + cursor: pointer; + border: none; + background: transparent; + + :hover { + color: ${designSystem.colors.light.linkHover}; + } +`; + +export default SecondaryButton; diff --git a/websites/docs-smoke-test/package.json b/websites/docs-smoke-test/package.json index 55b04c1e84..b42207e502 100644 --- a/websites/docs-smoke-test/package.json +++ b/websites/docs-smoke-test/package.json @@ -19,9 +19,9 @@ "@commercetools-docs/gatsby-theme-code-examples": "21.3.1", "@commercetools-docs/gatsby-theme-constants": "21.3.1", "@commercetools-docs/gatsby-theme-docs": "21.3.2", + "@commercetools-docs/gatsby-theme-learning": "21.3.1", "@commercetools-docs/gatsby-theme-sso-ui-kit": "21.3.1", "@commercetools-docs/ui-kit": "21.3.1", - "@commercetools-uikit/avatar": "16.0.0", "@commercetools-uikit/icons": "16.0.0", "@commercetools-uikit/radio-input": "16.0.0", "gatsby": "5.8.0", diff --git a/websites/documentation/gatsby-config.mjs b/websites/documentation/gatsby-config.mjs index 8e1ef8f6d5..725d4d9487 100644 --- a/websites/documentation/gatsby-config.mjs +++ b/websites/documentation/gatsby-config.mjs @@ -26,6 +26,7 @@ const config = { auth0Domain: 'auth.id.commercetools.com', auth0ClientId: 'xLk8EDUCc8PKqCbrSJCnuahvn86nEn4z', learnApiBaseUrl: 'https://learning-api.commercetools.vercel.app', + hideLogin: true, }, }, ], diff --git a/websites/documentation/src/content/configuration/sso.mdx b/websites/documentation/src/content/configuration/sso.mdx index 92774db482..ea9191992b 100644 --- a/websites/documentation/src/content/configuration/sso.mdx +++ b/websites/documentation/src/content/configuration/sso.mdx @@ -15,13 +15,15 @@ The plugin interacts with auth0 authentication provider and therefore needs to b ## Configuration -`gatsby-theme-sso-ui-kit` plugin expects 2 parameters: +`gatsby-theme-sso-ui-kit` plugin expects 3 parameters: - `auth0Domain`: the auth0 application domain url (it is defined in the auth0 management app) - `auth0ClientId`: the auth0 application client id (it is defined in the auth0 management app) - `learnApiBaseUrl`: the learn API base url. It can be omitted if the host running the site matches the api host. Often needs to be a conditional value for prod vs. preview to use the respective (sub)domain scope for cookies. +You can also add the optional `hideLogin` parameter if you don't want the login information to be visible in the top bar. + In order to enable the plugin, the following configuration should be added to the `gatsby-config.js` plugin section: ``` @@ -32,6 +34,7 @@ const isProd = process.env.NODE_ENV === 'production'; auth0Domain: 'auth0domain.dummy.tld', auth0ClientId: 'cliendItString', learnApiBaseUrl: isProd ? 'https://learning-api.prod-domain.tld' : 'https://learning-api.preview-domain.tld', + hideLogin: false, }, }, ``` diff --git a/yarn.lock b/yarn.lock index e46496606d..4b62908d8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2350,7 +2350,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.14.8, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.7, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.7, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.19.4 resolution: "@babel/runtime@npm:7.19.4" dependencies: @@ -3089,7 +3089,6 @@ __metadata: "@auth0/auth0-react": 2.0.1 "@commercetools-docs/gatsby-theme-sso-ui-kit": 21.3.1 "@commercetools-docs/ui-kit": 21.3.1 - "@commercetools-uikit/avatar": 16.0.0 "@commercetools-uikit/checkbox-input": 16.0.0 "@commercetools-uikit/design-system": 16.0.0 "@commercetools-uikit/icons": 16.0.0 @@ -3126,7 +3125,6 @@ __metadata: dependencies: "@auth0/auth0-react": 2.0.1 "@commercetools-docs/ui-kit": 21.3.1 - "@commercetools-uikit/avatar": 16.0.0 "@commercetools-uikit/icons": 16.0.0 "@commercetools-uikit/secondary-button": 16.0.0 "@commercetools-uikit/spacings": 16.0.0 @@ -3135,7 +3133,6 @@ __metadata: "@testing-library/jest-dom": 5.16.5 "@testing-library/react": 14.0.0 "@types/react": 18.0.28 - downshift: 7.6.0 md5: 2.3.0 prop-types: 15.8.1 react: 18.2.0 @@ -3333,23 +3330,6 @@ __metadata: languageName: node linkType: hard -"@commercetools-uikit/avatar@npm:16.0.0": - version: 16.0.0 - resolution: "@commercetools-uikit/avatar@npm:16.0.0" - dependencies: - "@babel/runtime": ^7.20.13 - "@babel/runtime-corejs3": ^7.20.13 - "@commercetools-uikit/design-system": 16.0.0 - "@commercetools-uikit/utils": 16.0.0 - "@emotion/react": ^11.10.5 - "@emotion/styled": ^11.10.5 - prop-types: 15.8.1 - peerDependencies: - react: 17.x - checksum: 756049971df2dba34acb05103c742f97fcec3a9bd67329fa7213f8a7810ba2d51e21de9ae38b10546ff243b4604f1585b9f01bd502f9287ce1aa2dfbe050bb91 - languageName: node - linkType: hard - "@commercetools-uikit/card@npm:16.0.0": version: 16.0.0 resolution: "@commercetools-uikit/card@npm:16.0.0" @@ -3968,9 +3948,9 @@ __metadata: "@commercetools-docs/gatsby-theme-code-examples": 21.3.1 "@commercetools-docs/gatsby-theme-constants": 21.3.1 "@commercetools-docs/gatsby-theme-docs": 21.3.2 + "@commercetools-docs/gatsby-theme-learning": 21.3.1 "@commercetools-docs/gatsby-theme-sso-ui-kit": 21.3.1 "@commercetools-docs/ui-kit": 21.3.1 - "@commercetools-uikit/avatar": 16.0.0 "@commercetools-uikit/icons": 16.0.0 "@commercetools-uikit/radio-input": 16.0.0 "@svgr/cli": 7.0.0 @@ -12774,13 +12754,6 @@ __metadata: languageName: node linkType: hard -"compute-scroll-into-view@npm:^2.0.4": - version: 2.0.4 - resolution: "compute-scroll-into-view@npm:2.0.4" - checksum: f3d1db9276c16af42155b572750514939cd0ab0a0f46498906f6811c5b654c5ff2b3f9bfd65958e57439e000a5e1ae092eb96b9e153d194a73e52ffd2380550c - languageName: node - linkType: hard - "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -14510,21 +14483,6 @@ __metadata: languageName: node linkType: hard -"downshift@npm:7.6.0": - version: 7.6.0 - resolution: "downshift@npm:7.6.0" - dependencies: - "@babel/runtime": ^7.14.8 - compute-scroll-into-view: ^2.0.4 - prop-types: ^15.7.2 - react-is: ^17.0.2 - tslib: ^2.3.0 - peerDependencies: - react: ">=16.12.0" - checksum: f738e0b50bcacedbf14c8de3baceb8e7be88ec4a2ab6becdc58ae253883d47de1085240db189cc485eb5995d0f35ac017836266116a95e0ac8c19b4600d38598 - languageName: node - linkType: hard - "duplexer2@npm:^0.1.2": version: 0.1.4 resolution: "duplexer2@npm:0.1.4" @@ -27676,7 +27634,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:15.8.1, prop-types@npm:^15.8.1": +"prop-types@npm:15.8.1, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -27687,7 +27645,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2": +"prop-types@npm:^15.6.0, prop-types@npm:^15.6.2": version: 15.7.2 resolution: "prop-types@npm:15.7.2" dependencies: @@ -28155,7 +28113,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:17.0.2, react-is@npm:^17.0.1, react-is@npm:^17.0.2": +"react-is@npm:17.0.2, react-is@npm:^17.0.1": version: 17.0.2 resolution: "react-is@npm:17.0.2" checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8 @@ -31740,7 +31698,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.0": +"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0": version: 2.3.1 resolution: "tslib@npm:2.3.1" checksum: de17a98d4614481f7fcb5cd53ffc1aaf8654313be0291e1bfaee4b4bb31a20494b7d218ff2e15017883e8ea9626599b3b0e0229c18383ba9dce89da2adf15cb9