Skip to content

Commit

Permalink
Merge branch 'master' into account-on-hold-error-screen
Browse files Browse the repository at this point in the history
  • Loading branch information
Hyperkid123 authored Aug 13, 2024
2 parents 8ab13b7 + d5f7cc7 commit 59e67df
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 35 deletions.
47 changes: 27 additions & 20 deletions cypress/component/ChromeContext/feedbackModal.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@ import { IntlProvider } from 'react-intl';
import InternalChromeContext from '../../../src/utils/internalChromeContext';
import { Provider as JotaiProvider } from 'jotai';
import chromeStore from '../../../src/state/chromeStore';
import { BrowserRouter } from 'react-router-dom';

describe('Feedback Modal', () => {
let chromeContext: Context<ChromeAPI>;
let contextValue: ChromeAPI;
const NestedComponen = () => {
return (
<IntlProvider locale="en">
<InternalChromeContext.Provider value={{ getEnvironment: () => 'stage' } as any}>
<Feedback />
</InternalChromeContext.Provider>
</IntlProvider>
<BrowserRouter>
<IntlProvider locale="en">
<InternalChromeContext.Provider value={{ getEnvironment: () => 'stage' } as any}>
<Feedback />
</InternalChromeContext.Provider>
</IntlProvider>
</BrowserRouter>
);
};
const InnerComponent = () => {
Expand All @@ -32,13 +35,15 @@ describe('Feedback Modal', () => {
const Wrapper = () => {
const [removeComponent, setRemoveComponent] = useState(false);
return (
<IntlProvider locale="en">
<InternalChromeContext.Provider value={{ getEnvironment: () => 'stage' } as any}>
<Feedback />
{!removeComponent ? <InnerComponent /> : null}
<button onClick={() => setRemoveComponent(true)}>Remove component from dom</button>
</InternalChromeContext.Provider>
</IntlProvider>
<BrowserRouter>
<IntlProvider locale="en">
<InternalChromeContext.Provider value={{ getEnvironment: () => 'stage' } as any}>
<Feedback />
{!removeComponent ? <InnerComponent /> : null}
<button onClick={() => setRemoveComponent(true)}>Remove component from dom</button>
</InternalChromeContext.Provider>
</IntlProvider>
</BrowserRouter>
);
};

Expand All @@ -54,14 +59,16 @@ describe('Feedback Modal', () => {

const CustomComponent = () => {
return (
<IntlProvider locale="en">
<JotaiProvider store={chromeStore}>
<InternalChromeContext.Provider value={{ getEnvironment: () => 'stage' } as any}>
<CustomButton />
<Feedback />
</InternalChromeContext.Provider>
</JotaiProvider>
</IntlProvider>
<BrowserRouter>
<IntlProvider locale="en">
<JotaiProvider store={chromeStore}>
<InternalChromeContext.Provider value={{ getEnvironment: () => 'stage' } as any}>
<CustomButton />
<Feedback />
</InternalChromeContext.Provider>
</JotaiProvider>
</IntlProvider>
</BrowserRouter>
);
};

Expand Down
15 changes: 15 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,21 @@ chrome.createCase({
})
```
You can also configure the version and product of the support cases:
```js
const chrome = useChrome()

chrome.createCase({
supportCaseData: {
product: 'Red Hat Insights',
version: 'Advisor',
},
caseFields: {}
...
})
```
## Deprecated functions
* `chrome.navigation` this is a legacy function and is no longer supported. Invoking it has no effect.
Expand Down
23 changes: 14 additions & 9 deletions src/@types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,19 @@ export type RouteDefinition = {
props?: any;

Check warning on line 138 in src/@types/types.d.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
};

export type ModuleRoute =
| {
isFedramp?: boolean;
pathname: string;
exact?: boolean;
dynamic?: boolean;
props?: Record<string, unknown>;
}
| string;
export type SupportCaseConfig = {
product: string;
version: string;
};

export type ModuleRoute = {
isFedramp?: boolean;
pathname: string;
exact?: boolean;
dynamic?: boolean;
props?: Record<string, unknown>;
supportCaseData?: SupportCaseConfig;
};

export type RemoteModule = {
module: string;
Expand All @@ -157,6 +161,7 @@ export type ChromeModule = {
manifestLocation: string;
ssoUrl?: string;
config?: {
supportCaseData?: SupportCaseConfig;
ssoUrl?: string;
fullProfile?: boolean;
props?: Record<string, unknown>;
Expand Down
2 changes: 1 addition & 1 deletion src/chrome/create-chrome.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const createChromeContext = ({
return environment;
},
getAvailableBundles: () => Object.entries(bundleMapping).map(([key, value]) => ({ id: key, title: value })),
createCase: (fields?: any) => chromeAuth.getUser().then((user) => createSupportCase(user!.identity, chromeAuth.token, fields)),
createCase: (options?: any) => chromeAuth.getUser().then((user) => createSupportCase(user!.identity, chromeAuth.token, options)),
getUserPermissions: async (app = '', bypassCache?: boolean) => {
const token = await chromeAuth.getToken();
return fetchPermissions(token, app, bypassCache);
Expand Down
4 changes: 3 additions & 1 deletion src/components/Feedback/FeedbackModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import './Feedback.scss';
import ChromeAuthContext from '../../auth/ChromeAuthContext';
import { useSegment } from '../../analytics/useSegment';
import { isPreviewAtom } from '../../state/atoms/releaseAtom';
import useSupportCaseData from '../../hooks/useSupportCaseData';

const FEEDBACK_OPEN_EVENT = 'chrome.feedback.open';

Expand Down Expand Up @@ -56,6 +57,7 @@ const FeedbackModal = memo(() => {
setModalPage('feedbackHome');
};
const isPreview = useAtomValue(isPreviewAtom);
const supportCaseData = useSupportCaseData();

const ModalDescription = ({ modalPage }: { modalPage: FeedbackPages }) => {
switch (modalPage) {
Expand All @@ -79,7 +81,7 @@ const FeedbackModal = memo(() => {
className="pf-v5-u-mb-lg"
isSelectableRaised
isCompact
onClick={() => createSupportCase(user.identity, chromeAuth.token, isPreview)}
onClick={() => createSupportCase(user.identity, chromeAuth.token, isPreview, { supportCaseData })}
>
<CardTitle className="pf-v5-u-primary-color-100">
<Text>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Header/Tools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import ChromeAuthContext from '../../auth/ChromeAuthContext';
import { isPreviewAtom } from '../../state/atoms/releaseAtom';
import { notificationDrawerExpandedAtom, unreadNotificationsAtom } from '../../state/atoms/notificationDrawerAtom';
import PreviewAlert from './PreviewAlert';
import useSupportCaseData from '../../hooks/useSupportCaseData';

const isITLessEnv = ITLess();

Expand Down Expand Up @@ -174,6 +175,7 @@ const Tools = () => {
});
}
}, [user]);
const supportCaseData = useSupportCaseData();

const supportOptionsUrl = () => {
return isITLessEnv ? 'https://redhatgov.servicenowservices.com/css' : 'https://access.redhat.com/support';
Expand All @@ -188,7 +190,7 @@ const Tools = () => {
},
{
title: intl.formatMessage(messages.openSupportCase),
onClick: () => createSupportCase(user.identity, token, isPreview),
onClick: () => createSupportCase(user.identity, token, isPreview, { supportCaseData }),
isDisabled: window.location.href.includes('/application-services') && !isRhosakEntitled,
isHidden: isITLessEnv,
},
Expand Down
42 changes: 42 additions & 0 deletions src/hooks/useSupportCaseData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useMemo } from 'react';
import { useAtomValue } from 'jotai';
import { matchPath, useLocation } from 'react-router-dom';
import { chromeModulesAtom } from '../state/atoms/chromeModuleAtom';
import { ModuleRoute, SupportCaseConfig } from '../@types/types';
import { activeModuleAtom } from '../state/atoms/activeModuleAtom';

function findRouteSupportCaseData(routes: ModuleRoute[], currentPathname: string): SupportCaseConfig | undefined {
const sortedModules = routes.sort((a, b) => b.pathname.length - a.pathname.length);
const matchedRoute = sortedModules.find(({ pathname }) => {
return matchPath(
{
path: pathname,
end: false,
},
currentPathname
);
});

return matchedRoute?.supportCaseData;
}

const useSupportCaseData = (): SupportCaseConfig | undefined => {
const scope = useAtomValue(activeModuleAtom);
const location = useLocation();
const modules = useAtomValue(chromeModulesAtom);
const moduleConfig = useMemo(() => (scope ? modules[scope] : undefined), [modules, scope]);
const supportCaseData = useMemo(() => {
if (!moduleConfig?.modules) {
return undefined;
}
const routeCaseData = findRouteSupportCaseData(
moduleConfig.modules.flatMap(({ routes }) => routes),
location.pathname
);
return routeCaseData ?? moduleConfig?.config?.supportCaseData;
}, [moduleConfig, location]);

return supportCaseData;
};

export default useSupportCaseData;
14 changes: 11 additions & 3 deletions src/utils/createCase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ChromeUser } from '@redhat-cloud-services/types';
import { getUrl } from '../hooks/useBundle';
import chromeStore from '../state/chromeStore';
import { activeModuleAtom } from '../state/atoms/activeModuleAtom';
import { SupportCaseConfig } from '../@types/types';

// Lit of products that are bundles
const BUNDLE_PRODUCTS = [
Expand Down Expand Up @@ -72,8 +73,9 @@ export async function createSupportCase(
userInfo: ChromeUser['identity'],
token: string,
isPreview: boolean,
fields?: {
caseFields: Record<string, unknown>;
options?: {
supportCaseData?: SupportCaseConfig | undefined;
caseFields?: Record<string, unknown>;
}
) {
const currentProduct = registerProduct() || 'Other';
Expand All @@ -82,6 +84,7 @@ export async function createSupportCase(
const { src_hash, app_name } = { src_hash: productData?.src_hash, app_name: productData?.app_name ?? getUrl('app') };
const portalUrl = `${getEnvDetails()?.portal}`;
const caseUrl = `${portalUrl}${HYDRA_ENDPOINT}`;
const { supportCaseData, ...fields } = options ?? { caseFields: {} };

log('Creating a support case');

Expand Down Expand Up @@ -112,7 +115,12 @@ export async function createSupportCase(
.then((response) => response.json())
.then((data) => {
if (data) {
const query = URI(`?seSessionId=${data.session.id}&product=${data.sessionDetails.product}&version=${src_hash}`).normalize();
// FIXME: Use the URLSearchParams API instead of URI.js
const query = URI(
`?seSessionId=${data.session.id}&product=${supportCaseData?.product ?? data.sessionDetails.product}&version=${
supportCaseData?.version ?? src_hash
}`
).normalize();
window.open(`${portalUrl}/support/cases/#/case/new/open-case/describe-issue${query.readable()}`);
return createSupportSentry(data.session.id, fields);
}
Expand Down

0 comments on commit 59e67df

Please sign in to comment.