From 10abdc264909fc52d9947d42428152a82974694d Mon Sep 17 00:00:00 2001 From: Marcelo Blechner Date: Thu, 5 Nov 2020 17:43:21 -0300 Subject: [PATCH 1/6] feat(suiteheader): Separating the data fetching function from the useSuiteHeaderData hook so that it is also possible to import the plain function that calls all the required APIs without the need to use React Hooks. --- .../__snapshots__/Welcome.story.storyshot | 12 + jest.config.js | 1 + .../SuiteHeader/SuiteHeader.story.jsx | 99 +++++++- .../SuiteHeader/hooks/useSuiteHeaderData.js | 221 +--------------- .../suiteHeaderData.fixture.js | 0 .../SuiteHeader/util/suiteHeaderData.js | 235 ++++++++++++++++++ src/index.js | 1 + .../__snapshots__/publicAPI.test.js.snap | 1 + 8 files changed, 352 insertions(+), 218 deletions(-) rename src/components/SuiteHeader/{hooks => util}/suiteHeaderData.fixture.js (100%) create mode 100644 src/components/SuiteHeader/util/suiteHeaderData.js diff --git a/.storybook/__snapshots__/Welcome.story.storyshot b/.storybook/__snapshots__/Welcome.story.storyshot index c2e72e3748..d5d978f5d8 100644 --- a/.storybook/__snapshots__/Welcome.story.storyshot +++ b/.storybook/__snapshots__/Welcome.story.storyshot @@ -3012,6 +3012,18 @@ exports[`Storybook Snapshot tests and console checks Storyshots 0/Getting Starte useSuiteHeaderData +
+
+
+ suiteHeaderData +
+
diff --git a/jest.config.js b/jest.config.js index 0a76eec30b..705bc6a657 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,6 +3,7 @@ module.exports = { 'src/components/**/*.js?(x)', '!src/**/*.story.js?(x)', '!src/**/hooks/*.js', + '!src/**/util/*.js', ], coveragePathIgnorePatterns: ['/node_modules/', '/lib/', '/coverage/'], coverageReporters: ['html', 'text-summary', 'lcov'], diff --git a/src/components/SuiteHeader/SuiteHeader.story.jsx b/src/components/SuiteHeader/SuiteHeader.story.jsx index f622bf0cfc..a49753674c 100644 --- a/src/components/SuiteHeader/SuiteHeader.story.jsx +++ b/src/components/SuiteHeader/SuiteHeader.story.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { text, object, boolean, select } from '@storybook/addon-knobs'; import { Switcher24 } from '@carbon/icons-react'; import Chip from '@carbon/icons-react/lib/chip/24'; @@ -7,6 +7,7 @@ import Group from '@carbon/icons-react/lib/group/24'; import SuiteHeader from './SuiteHeader'; import SuiteHeaderI18N from './i18n'; +// import getSuiteHeaderData from './util/suiteHeaderData'; // import useSuiteHeaderData from './hooks/useSuiteHeaderData'; const sideNavLinks = [ @@ -227,6 +228,102 @@ export const HeaderWithSurveyNotification = () => { ); }; +/* Sample of SuiteHeader usage with data hook +export const HeaderWithHook = () => { + const StatefulExample = () => { + const [data, isLoading, error, refreshData] = useSuiteHeaderData({ + baseApiUrl: 'http://localhost:3001/internal', + domain: 'mydomain.com', + // isTest: true, + surveyConfig: { + id: 'suite', + delayIntervalDays: -1, + frequencyDays: -1, + }, + lang: 'en', + }); + const surveyData = data.showSurvey ? { surveyLink: 'https://www.ibm.com', privacyLink: 'https://www.ibm.com'} : null; + return ( + + ); + } + return ; +}; + +HeaderWithHook.story = { + name: 'Header with hook', +}; + +export const HeaderWithDataFetching = () => { + const StatefulExample = () => { + const [data, setData] = useState({ + username: null, + userDisplayName: null, + email: null, + routes: { + profile: null, + navigator: null, + admin: null, + logout: null, + about: null, + documentation: null, + whatsNew: null, + requestEnhancement: null, + support: null, + gettingStarted: null, + }, + applications: [], + showSurvey: false, + }); + useEffect(() => { + getSuiteHeaderData({ + // baseApiUrl: 'http://localhost:3001/internal', + domain: 'mydomain.com', + isTest: true, + surveyConfig: { + id: 'suite', + delayIntervalDays: 30, + frequencyDays: 90, + }, + lang: 'en', + }).then(suiteHeaderData => setData(suiteHeaderData)); + }, []); + + const surveyData = data.showSurvey ? { surveyLink: 'https://www.ibm.com', privacyLink: 'https://www.ibm.com'} : null; + return ( + + ); + } + return +}; + +HeaderWithDataFetching.story = { + name: 'Header with data fetching', +}; + +*/ + HeaderWithSurveyNotification.story = { name: 'Header with survey notification', }; diff --git a/src/components/SuiteHeader/hooks/useSuiteHeaderData.js b/src/components/SuiteHeader/hooks/useSuiteHeaderData.js index 2f3414a310..bbcc088eee 100644 --- a/src/components/SuiteHeader/hooks/useSuiteHeaderData.js +++ b/src/components/SuiteHeader/hooks/useSuiteHeaderData.js @@ -1,168 +1,8 @@ import { useState, useEffect, useCallback } from 'react'; -import moment from 'moment'; - -import SuiteHeaderI18N from '../i18n'; // eslint-disable-next-line import/extensions -import testApiData from './suiteHeaderData.fixture.js'; - -// default route calculation logic -const calcRoutes = (domain, user, workspaces, applications) => { - const workspaceId = Object.keys(user.workspaces)[0]; - const getApplicationUrl = (appId) => - user.workspaces[workspaceId].applications[appId].href; - const isAdmin = user.permissions.systemAdmin || user.permissions.userAdmin; - const routeData = { - profile: `https://home.${domain}/myaccount`, - navigator: `https://${workspaceId}.home.${domain}`, - admin: isAdmin ? `https://admin.${domain}` : null, - logout: `https://home.${domain}/logout`, - whatsNew: - 'https://www.ibm.com/support/knowledgecenter/SSRHPA_current/appsuite/overview/whats_new.html', - gettingStarted: - 'https://www.ibm.com/support/knowledgecenter/SSRHPA_current/appsuite/overview/getting_started.html', - documentation: 'https://www.ibm.com/support/knowledgecenter/SSRHPA_current', - requestEnhancement: 'https://ibm-watson-iot.ideas.aha.io/', - support: 'https://www.ibm.com/mysupport', - about: `https://home.${domain}/about`, - }; - const appOrdering = ['monitor', 'health', 'predict', 'visualinspection']; - const workspaceApplications = user.workspaces[workspaceId].applications || {}; - const applicationSyncStates = user.applications || {}; - const appData = Object.keys(workspaceApplications) - .filter((appId) => workspaceApplications[appId].role !== 'NO_ACCESS') - .filter((appId) => applicationSyncStates[appId]?.sync?.state === 'SUCCESS') - .filter( - (appId) => - (applications.find((i) => i.id === appId) || {}).category === - 'application' - ) - .sort( - (a, b) => - appOrdering.findIndex((i) => i === a) - - appOrdering.findIndex((i) => i === b) - ) - .map((appId) => ({ - id: appId, - name: - (applications.find((i) => i.id === appId) || {}).name || - appId.charAt(0).toUpperCase() + appId.slice(1), - href: getApplicationUrl(appId), - isExternal: getApplicationUrl(appId).indexOf(domain) >= 0, - })) - .sort(); - return [routeData, appData]; -}; - -// Default survey status calculation logic -const calcSurveyStatus = async (userId, surveyConfig, apiFct) => { - let showSurvey = false; - - // Check if it is time to show the survey - const isTimeForSurvey = (surveyData) => { - // If survey is not enabled, return false - if (!surveyData.enabled) { - return false; - } - // If lastPromptTimestamp is set and it is greater than initialInteractionTimestamp, - // it means that at least one survey has already been prompted to the user, - // so, we check if another survey prompt is due. - if ( - surveyData.lastPromptTimestamp && - moment(surveyData.lastPromptTimestamp).isAfter( - surveyData.initialInteractionTimestamp - ) - ) { - if ( - moment().diff(surveyData.lastPromptTimestamp, 'days') > - surveyData.frequencyDays - ) { - return true; - } - } - // No survey has been prompted yet, so we check if it is time for the first one. - else if ( - moment().diff(surveyData.initialInteractionTimestamp, 'days') > - surveyData.delayIntervalDays - ) { - return true; - } - return false; - }; - - const surveyData = await apiFct( - 'GET', - `/users/${userId}/surveys/${surveyConfig.id}` - ); - if (surveyData) { - // Survey data found, check it some config props need to be updated on the backend - const updateObject = {}; - ['delayIntervalDays', 'frequencyDays', 'enabled'].forEach((surveyProp) => { - if ( - surveyConfig[surveyProp] && - surveyConfig[surveyProp] !== surveyData[surveyProp] - ) { - updateObject[surveyProp] = surveyConfig[surveyProp]; - } - }); - // If at least one config prop is different than the one in the existing record, update it - if (Object.keys(updateObject).length > 0) { - await apiFct( - 'PUT', - `/users/${userId}/surveys/${surveyConfig.id}`, - updateObject - ); - } - // Based on survey data and current timestamp, make the proper time comparisons to check if it is time to show a survey - showSurvey = isTimeForSurvey(surveyData); - if (showSurvey) { - // Update lastPromptTimestamp to the current timestamp so that we need to wait another 'frequencyDays' days until the next survey - await apiFct('PUT', `/users/${userId}/surveys/${surveyConfig.id}`, { - lastPromptTimestamp: moment.utc().format(), - }); - } - } else { - // Survey record not found, create it - await apiFct('POST', `/users/${userId}/surveys`, { - ...surveyConfig, - delayIntervalDays: surveyConfig.delayIntervalDays ?? 30, - frequencyDays: surveyConfig.frequencyDays ?? 90, - enabled: surveyConfig.enabled ?? true, - initialInteractionTimestamp: moment.utc().format(), - }); - } - return showSurvey; -}; +import getSuiteHeaderData, { calcRoutes, calcSurveyStatus, calcI18N, defaultFetchApi } from '../util/suiteHeaderData'; -// default i18n calculation logic -const calcI18N = (i18nData) => ({ - ...i18nData, - surveyTitle: (solutionName) => - i18nData.surveyTitle.replace('{solutionName}', solutionName), - profileLogoutModalBody: (solutionName, userName) => - i18nData.profileLogoutModalBody - .replace('{solutionName}', solutionName) - .replace('{userName}', userName), -}); - -const defaultFetchApi = async (method, url, body, headers, testResponse) => - testResponse || - fetch(url, { - method, - credentials: 'include', - headers: headers || { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }) - .then((res) => res.json()) - .then((resJson) => { - // Don't return any data if an error happened (401, 404, 409, etc) - if (resJson.error || resJson.exception) { - return null; - } - return resJson; - }); const useSuiteHeaderData = ({ baseApiUrl, @@ -194,67 +34,14 @@ const useSuiteHeaderData = ({ gettingStarted: null, }, applications: [], + showSurvey: false, }); const refreshData = useCallback(async () => { - const api = (method, path, body, headers) => - fetchApi( - method, - `${baseApiUrl}${path}`, - body, - headers, - isTest ? testApiData[path] : null - ); - try { setIsLoading(true); - const profileData = await api('GET', '/profile'); - const appsData = await api('GET', '/applications'); - const eamData = await api('GET', '/config/eam'); - const i18nData = await api('GET', `/i18n/header/${isTest ? 'en' : lang}`); - - // Routes - const [routes, applications] = calculateRoutes( - domain, - profileData.user, - profileData.workspaces, - appsData - ); - - // Survey - const showSurvey = surveyConfig?.id - ? await calculateSurveyStatus( - profileData.user.username, - surveyConfig, - api - ) - : false; - - // i18n - const i18n = i18nData ? calculateI18N(i18nData) : SuiteHeaderI18N.en; - - setData({ - username: profileData.user.username, - userDisplayName: profileData.user.displayName, - email: profileData.user.email, - routes, - applications: [ - ...(eamData?.url - ? [ - { - id: 'eam', - name: 'Manage', - href: eamData.url, - isExternal: true, - }, - ] - : []), - ...applications, - ], - i18n, - showSurvey, - }); - setIsLoading(false); + const suiteHeaderData = await getSuiteHeaderData({ baseApiUrl, domain, lang, calculateRoutes, calculateSurveyStatus, calculateI18N, fetchApi, surveyConfig, isTest }); + setData(suiteHeaderData); } catch (err) { setError(err); setIsLoading(false); diff --git a/src/components/SuiteHeader/hooks/suiteHeaderData.fixture.js b/src/components/SuiteHeader/util/suiteHeaderData.fixture.js similarity index 100% rename from src/components/SuiteHeader/hooks/suiteHeaderData.fixture.js rename to src/components/SuiteHeader/util/suiteHeaderData.fixture.js diff --git a/src/components/SuiteHeader/util/suiteHeaderData.js b/src/components/SuiteHeader/util/suiteHeaderData.js new file mode 100644 index 0000000000..f587acbc59 --- /dev/null +++ b/src/components/SuiteHeader/util/suiteHeaderData.js @@ -0,0 +1,235 @@ +import moment from 'moment'; + +import SuiteHeaderI18N from '../i18n'; + +// eslint-disable-next-line import/extensions +import testApiData from './suiteHeaderData.fixture.js'; + +// default route calculation logic +export const calcRoutes = (domain, user, workspaces, applications) => { + const workspaceId = Object.keys(user.workspaces)[0]; + const getApplicationUrl = (appId) => + user.workspaces[workspaceId].applications[appId].href; + const isAdmin = user.permissions.systemAdmin || user.permissions.userAdmin; + const routeData = { + profile: `https://home.${domain}/myaccount`, + navigator: `https://${workspaceId}.home.${domain}`, + admin: isAdmin ? `https://admin.${domain}` : null, + logout: `https://home.${domain}/logout`, + whatsNew: + 'https://www.ibm.com/support/knowledgecenter/SSRHPA_current/appsuite/overview/whats_new.html', + gettingStarted: + 'https://www.ibm.com/support/knowledgecenter/SSRHPA_current/appsuite/overview/getting_started.html', + documentation: 'https://www.ibm.com/support/knowledgecenter/SSRHPA_current', + requestEnhancement: 'https://ibm-watson-iot.ideas.aha.io/', + support: 'https://www.ibm.com/mysupport', + about: `https://home.${domain}/about`, + }; + const appOrdering = ['monitor', 'health', 'predict', 'visualinspection']; + const workspaceApplications = user.workspaces[workspaceId].applications || {}; + const applicationSyncStates = user.applications || {}; + const appData = Object.keys(workspaceApplications) + .filter((appId) => workspaceApplications[appId].role !== 'NO_ACCESS') + .filter((appId) => applicationSyncStates[appId]?.sync?.state === 'SUCCESS') + .filter( + (appId) => + (applications.find((i) => i.id === appId) || {}).category === + 'application' + ) + .sort( + (a, b) => + appOrdering.findIndex((i) => i === a) - + appOrdering.findIndex((i) => i === b) + ) + .map((appId) => ({ + id: appId, + name: + (applications.find((i) => i.id === appId) || {}).name || + appId.charAt(0).toUpperCase() + appId.slice(1), + href: getApplicationUrl(appId), + isExternal: getApplicationUrl(appId).indexOf(domain) >= 0, + })) + .sort(); + return [routeData, appData]; +}; + +// Default survey status calculation logic +export const calcSurveyStatus = async (userId, surveyConfig, apiFct) => { + let showSurvey = false; + + // Check if it is time to show the survey + const isTimeForSurvey = (surveyData) => { + // If survey is not enabled, return false + if (!surveyData.enabled) { + return false; + } + // If lastPromptTimestamp is set and it is greater than initialInteractionTimestamp, + // it means that at least one survey has already been prompted to the user, + // so, we check if another survey prompt is due. + if ( + surveyData.lastPromptTimestamp && + moment(surveyData.lastPromptTimestamp).isAfter( + surveyData.initialInteractionTimestamp + ) + ) { + if ( + moment().diff(surveyData.lastPromptTimestamp, 'days') > + surveyData.frequencyDays + ) { + return true; + } + } + // No survey has been prompted yet, so we check if it is time for the first one. + else if ( + moment().diff(surveyData.initialInteractionTimestamp, 'days') > + surveyData.delayIntervalDays + ) { + return true; + } + return false; + }; + + const surveyData = await apiFct( + 'GET', + `/users/${userId}/surveys/${surveyConfig.id}` + ); + if (surveyData) { + // Survey data found, check it some config props need to be updated on the backend + const updateObject = {}; + ['delayIntervalDays', 'frequencyDays', 'enabled'].forEach((surveyProp) => { + if ( + surveyConfig[surveyProp] && + surveyConfig[surveyProp] !== surveyData[surveyProp] + ) { + updateObject[surveyProp] = surveyConfig[surveyProp]; + } + }); + // If at least one config prop is different than the one in the existing record, update it + if (Object.keys(updateObject).length > 0) { + await apiFct( + 'PUT', + `/users/${userId}/surveys/${surveyConfig.id}`, + updateObject + ); + } + // Based on survey data and current timestamp, make the proper time comparisons to check if it is time to show a survey + showSurvey = isTimeForSurvey(surveyData); + if (showSurvey) { + // Update lastPromptTimestamp to the current timestamp so that we need to wait another 'frequencyDays' days until the next survey + await apiFct('PUT', `/users/${userId}/surveys/${surveyConfig.id}`, { + lastPromptTimestamp: moment.utc().format(), + }); + } + } else { + // Survey record not found, create it + await apiFct('POST', `/users/${userId}/surveys`, { + ...surveyConfig, + delayIntervalDays: surveyConfig.delayIntervalDays ?? 30, + frequencyDays: surveyConfig.frequencyDays ?? 90, + enabled: surveyConfig.enabled ?? true, + initialInteractionTimestamp: moment.utc().format(), + }); + } + return showSurvey; +}; + +// default i18n calculation logic +export const calcI18N = (i18nData) => ({ + ...i18nData, + surveyTitle: (solutionName) => + i18nData.surveyTitle.replace('{solutionName}', solutionName), + profileLogoutModalBody: (solutionName, userName) => + i18nData.profileLogoutModalBody + .replace('{solutionName}', solutionName) + .replace('{userName}', userName), +}); + +export const defaultFetchApi = async (method, url, body, headers, testResponse) => + testResponse || + fetch(url, { + method, + credentials: 'include', + headers: headers || { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }) + .then((res) => res.json()) + .then((resJson) => { + // Don't return any data if an error happened (401, 404, 409, etc) + if (resJson.error || resJson.exception) { + return null; + } + return resJson; + }); + +const getSuiteHeaderData = async ({ + baseApiUrl, + domain, + lang = 'en', + calculateRoutes = calcRoutes, + calculateSurveyStatus = calcSurveyStatus, + calculateI18N = calcI18N, + fetchApi = defaultFetchApi, + surveyConfig = null, + isTest = false, +}) => { + + const api = (method, path, body, headers) => + fetchApi( + method, + `${baseApiUrl}${path}`, + body, + headers, + isTest ? testApiData[path] : null + ); + + const profileData = await api('GET', '/profile'); + const appsData = await api('GET', '/applications'); + const eamData = await api('GET', '/config/eam'); + const i18nData = await api('GET', `/i18n/header/${isTest ? 'en' : lang}`); + + // Routes + const [routes, applications] = calculateRoutes( + domain, + profileData.user, + profileData.workspaces, + appsData + ); + + // Survey + const showSurvey = surveyConfig?.id + ? await calculateSurveyStatus( + profileData.user.username, + surveyConfig, + api + ) + : false; + + // i18n + const i18n = i18nData ? calculateI18N(i18nData) : SuiteHeaderI18N.en; + + return({ + username: profileData.user.username, + userDisplayName: profileData.user.displayName, + email: profileData.user.email, + routes, + applications: [ + ...(eamData?.url + ? [ + { + id: 'eam', + name: 'Manage', + href: eamData.url, + isExternal: true, + }, + ] + : []), + ...applications, + ], + i18n, + showSurvey, + }); +} + +export default getSuiteHeaderData; diff --git a/src/index.js b/src/index.js index a850b39aa8..d2dd86cf68 100755 --- a/src/index.js +++ b/src/index.js @@ -58,6 +58,7 @@ export SuiteHeaderAppSwitcher from './components/SuiteHeader/SuiteHeaderAppSwitc export SuiteHeaderLogoutModal from './components/SuiteHeader/SuiteHeaderLogoutModal/SuiteHeaderLogoutModal'; export SuiteHeaderI18N from './components/SuiteHeader/i18n'; export useSuiteHeaderData from './components/SuiteHeader/hooks/useSuiteHeaderData'; +export suiteHeaderData from './components/SuiteHeader/util/suiteHeaderData'; // Dashboard export Dashboard from './components/Dashboard/Dashboard'; diff --git a/src/utils/__tests__/__snapshots__/publicAPI.test.js.snap b/src/utils/__tests__/__snapshots__/publicAPI.test.js.snap index 26e0651ee1..5e812a6025 100644 --- a/src/utils/__tests__/__snapshots__/publicAPI.test.js.snap +++ b/src/utils/__tests__/__snapshots__/publicAPI.test.js.snap @@ -6932,6 +6932,7 @@ Map { }, }, "useSuiteHeaderData" => Object {}, + "suiteHeaderData" => Object {}, "Dashboard" => Object { "defaultProps": Object { "actions": Array [], From a27d2b19c11ec6afa40e156907f58e2b6a5875a8 Mon Sep 17 00:00:00 2001 From: Marcelo Blechner Date: Thu, 5 Nov 2020 18:27:34 -0300 Subject: [PATCH 2/6] feat(suiteheader): Minor changes in a story that is commented out. Running prettier. --- src/components/SuiteHeader/SuiteHeader.story.jsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/SuiteHeader/SuiteHeader.story.jsx b/src/components/SuiteHeader/SuiteHeader.story.jsx index a49753674c..163a02c189 100644 --- a/src/components/SuiteHeader/SuiteHeader.story.jsx +++ b/src/components/SuiteHeader/SuiteHeader.story.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { text, object, boolean, select } from '@storybook/addon-knobs'; import { Switcher24 } from '@carbon/icons-react'; import Chip from '@carbon/icons-react/lib/chip/24'; @@ -232,13 +232,13 @@ export const HeaderWithSurveyNotification = () => { export const HeaderWithHook = () => { const StatefulExample = () => { const [data, isLoading, error, refreshData] = useSuiteHeaderData({ - baseApiUrl: 'http://localhost:3001/internal', + // baseApiUrl: 'http://localhost:3001/internal', domain: 'mydomain.com', - // isTest: true, + isTest: true, surveyConfig: { id: 'suite', - delayIntervalDays: -1, - frequencyDays: -1, + delayIntervalDays: 30, + frequencyDays: 90, }, lang: 'en', }); @@ -251,9 +251,6 @@ export const HeaderWithHook = () => { username={data.username} routes={data.routes} applications={data.applications} - sideNavProps={{ - links: sideNavLinks, - }} i18n={data.i18n} surveyData={surveyData} /> From 43fcc99f33941833818976f41eb94b2788f58f61 Mon Sep 17 00:00:00 2001 From: Marcelo Blechner Date: Thu, 5 Nov 2020 18:28:11 -0300 Subject: [PATCH 3/6] feat(suiteheader): Running prettier. --- .../SuiteHeader/hooks/useSuiteHeaderData.js | 20 +++++++++++++++--- .../SuiteHeader/util/suiteHeaderData.js | 21 ++++++++++--------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/components/SuiteHeader/hooks/useSuiteHeaderData.js b/src/components/SuiteHeader/hooks/useSuiteHeaderData.js index bbcc088eee..d4139f61bc 100644 --- a/src/components/SuiteHeader/hooks/useSuiteHeaderData.js +++ b/src/components/SuiteHeader/hooks/useSuiteHeaderData.js @@ -1,8 +1,12 @@ import { useState, useEffect, useCallback } from 'react'; // eslint-disable-next-line import/extensions -import getSuiteHeaderData, { calcRoutes, calcSurveyStatus, calcI18N, defaultFetchApi } from '../util/suiteHeaderData'; - +import getSuiteHeaderData, { + calcRoutes, + calcSurveyStatus, + calcI18N, + defaultFetchApi, +} from '../util/suiteHeaderData'; const useSuiteHeaderData = ({ baseApiUrl, @@ -40,7 +44,17 @@ const useSuiteHeaderData = ({ const refreshData = useCallback(async () => { try { setIsLoading(true); - const suiteHeaderData = await getSuiteHeaderData({ baseApiUrl, domain, lang, calculateRoutes, calculateSurveyStatus, calculateI18N, fetchApi, surveyConfig, isTest }); + const suiteHeaderData = await getSuiteHeaderData({ + baseApiUrl, + domain, + lang, + calculateRoutes, + calculateSurveyStatus, + calculateI18N, + fetchApi, + surveyConfig, + isTest, + }); setData(suiteHeaderData); } catch (err) { setError(err); diff --git a/src/components/SuiteHeader/util/suiteHeaderData.js b/src/components/SuiteHeader/util/suiteHeaderData.js index f587acbc59..d01c0e2fe1 100644 --- a/src/components/SuiteHeader/util/suiteHeaderData.js +++ b/src/components/SuiteHeader/util/suiteHeaderData.js @@ -144,7 +144,13 @@ export const calcI18N = (i18nData) => ({ .replace('{userName}', userName), }); -export const defaultFetchApi = async (method, url, body, headers, testResponse) => +export const defaultFetchApi = async ( + method, + url, + body, + headers, + testResponse +) => testResponse || fetch(url, { method, @@ -174,7 +180,6 @@ const getSuiteHeaderData = async ({ surveyConfig = null, isTest = false, }) => { - const api = (method, path, body, headers) => fetchApi( method, @@ -199,17 +204,13 @@ const getSuiteHeaderData = async ({ // Survey const showSurvey = surveyConfig?.id - ? await calculateSurveyStatus( - profileData.user.username, - surveyConfig, - api - ) + ? await calculateSurveyStatus(profileData.user.username, surveyConfig, api) : false; // i18n const i18n = i18nData ? calculateI18N(i18nData) : SuiteHeaderI18N.en; - return({ + return { username: profileData.user.username, userDisplayName: profileData.user.displayName, email: profileData.user.email, @@ -229,7 +230,7 @@ const getSuiteHeaderData = async ({ ], i18n, showSurvey, - }); -} + }; +}; export default getSuiteHeaderData; From 9ee23fa5edeefe443d68a5cdc7c4ebc9c137de76 Mon Sep 17 00:00:00 2001 From: blechner Date: Mon, 16 Nov 2020 13:02:53 -0300 Subject: [PATCH 4/6] Changing jest.config.js to exempt only the specific util file Co-authored-by: Taylor Jones --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index 705bc6a657..7d4c8c7c13 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,7 +3,7 @@ module.exports = { 'src/components/**/*.js?(x)', '!src/**/*.story.js?(x)', '!src/**/hooks/*.js', - '!src/**/util/*.js', + '! src/components/SuiteHeader/util/suiteHeaderData.js', ], coveragePathIgnorePatterns: ['/node_modules/', '/lib/', '/coverage/'], coverageReporters: ['html', 'text-summary', 'lcov'], From 1c05a269672037263425e2fc217c9fa0dc0c6ae2 Mon Sep 17 00:00:00 2001 From: Marcelo Blechner Date: Mon, 16 Nov 2020 16:57:44 -0300 Subject: [PATCH 5/6] Fixing a typo. --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index 7d4c8c7c13..501c4af416 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,7 +3,7 @@ module.exports = { 'src/components/**/*.js?(x)', '!src/**/*.story.js?(x)', '!src/**/hooks/*.js', - '! src/components/SuiteHeader/util/suiteHeaderData.js', + '!src/components/SuiteHeader/util/suiteHeaderData.js', ], coveragePathIgnorePatterns: ['/node_modules/', '/lib/', '/coverage/'], coverageReporters: ['html', 'text-summary', 'lcov'], From 8c2813738eb6e3bd4e91fc313761461adc6c7653 Mon Sep 17 00:00:00 2001 From: Marcelo Blechner Date: Mon, 16 Nov 2020 18:58:53 -0300 Subject: [PATCH 6/6] Running Prettier --- .../SuiteHeader/SuiteHeader.story.jsx | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/components/SuiteHeader/SuiteHeader.story.jsx b/src/components/SuiteHeader/SuiteHeader.story.jsx index 163a02c189..e4ec6d89bf 100644 --- a/src/components/SuiteHeader/SuiteHeader.story.jsx +++ b/src/components/SuiteHeader/SuiteHeader.story.jsx @@ -231,7 +231,7 @@ export const HeaderWithSurveyNotification = () => { /* Sample of SuiteHeader usage with data hook export const HeaderWithHook = () => { const StatefulExample = () => { - const [data, isLoading, error, refreshData] = useSuiteHeaderData({ + const [data] = useSuiteHeaderData({ // baseApiUrl: 'http://localhost:3001/internal', domain: 'mydomain.com', isTest: true, @@ -242,8 +242,13 @@ export const HeaderWithHook = () => { }, lang: 'en', }); - const surveyData = data.showSurvey ? { surveyLink: 'https://www.ibm.com', privacyLink: 'https://www.ibm.com'} : null; - return ( + const surveyData = data.showSurvey + ? { + surveyLink: 'https://www.ibm.com', + privacyLink: 'https://www.ibm.com', + } + : null; + return data.username ? ( { i18n={data.i18n} surveyData={surveyData} /> - ); - } + ) : null; + }; return ; }; @@ -295,11 +300,16 @@ export const HeaderWithDataFetching = () => { frequencyDays: 90, }, lang: 'en', - }).then(suiteHeaderData => setData(suiteHeaderData)); + }).then((suiteHeaderData) => setData(suiteHeaderData)); }, []); - - const surveyData = data.showSurvey ? { surveyLink: 'https://www.ibm.com', privacyLink: 'https://www.ibm.com'} : null; - return ( + + const surveyData = data.showSurvey + ? { + surveyLink: 'https://www.ibm.com', + privacyLink: 'https://www.ibm.com', + } + : null; + return data.username ? ( { i18n={data.i18n} surveyData={surveyData} /> - ); - } - return + ) : null; + }; + return ; }; HeaderWithDataFetching.story = {