diff --git a/src/components/README.md b/src/components/README.md
index 9cc623444..288a5cd8a 100644
--- a/src/components/README.md
+++ b/src/components/README.md
@@ -298,10 +298,14 @@ Initialize an app, and return a combined state store that includes authorization
options.hideGlobalFilter | function |
+ options.onNavigation | function |
+
options.useChrome | function |
options.useDispatch | function |
+ options.useNavigate | function |
+
options.useSelectorsResponse | function |
diff --git a/src/components/authentication/__tests__/__snapshots__/authentication.test.js.snap b/src/components/authentication/__tests__/__snapshots__/authentication.test.js.snap
index 58dbd9365..dc264cf2a 100644
--- a/src/components/authentication/__tests__/__snapshots__/authentication.test.js.snap
+++ b/src/components/authentication/__tests__/__snapshots__/authentication.test.js.snap
@@ -4,9 +4,11 @@ exports[`Authentication Component should allow being disabled: disabled 1`] = `
@@ -27,9 +29,9 @@ exports[`Authentication Component should render a basic component: basic 1`] = `
diff --git a/src/components/authentication/__tests__/__snapshots__/authenticationContext.test.js.snap b/src/components/authentication/__tests__/__snapshots__/authenticationContext.test.js.snap
index 16ab23006..b348ce345 100644
--- a/src/components/authentication/__tests__/__snapshots__/authenticationContext.test.js.snap
+++ b/src/components/authentication/__tests__/__snapshots__/authenticationContext.test.js.snap
@@ -76,6 +76,9 @@ exports[`AuthenticationContext should apply a hook for retrieving auth data from
},
],
],
+ [
+ [Function],
+ ],
]
`;
diff --git a/src/components/authentication/__tests__/authentication.test.js b/src/components/authentication/__tests__/authentication.test.js
index 8717a6b09..c45dd2788 100644
--- a/src/components/authentication/__tests__/authentication.test.js
+++ b/src/components/authentication/__tests__/authentication.test.js
@@ -5,8 +5,20 @@ import { rhsmConstants } from '../../../services/rhsm/rhsmConstants';
describe('Authentication Component', () => {
it('should render a basic component', async () => {
+ const props = {
+ useGetAuthorization: () => ({
+ error: false,
+ pending: false,
+ data: {
+ authorized: {},
+ errorCodes: [],
+ errorStatus: undefined
+ }
+ })
+ };
+
const component = await shallowHookComponent(
-
+
lorem
);
@@ -37,7 +49,18 @@ describe('Authentication Component', () => {
it('should allow being disabled', async () => {
const props = {
- isDisabled: true
+ isDisabled: true,
+ useGetAuthorization: () => ({
+ error: false,
+ pending: false,
+ data: {
+ authorized: {
+ [helpers.UI_NAME]: true
+ },
+ errorCodes: [],
+ errorStatus: undefined
+ }
+ })
};
const component = await shallowHookComponent(
diff --git a/src/components/authentication/__tests__/authenticationContext.test.js b/src/components/authentication/__tests__/authenticationContext.test.js
index 8881fb31b..ca82aee95 100644
--- a/src/components/authentication/__tests__/authenticationContext.test.js
+++ b/src/components/authentication/__tests__/authenticationContext.test.js
@@ -9,6 +9,7 @@ describe('AuthenticationContext', () => {
it('should apply a hook for retrieving auth data from multiple selectors', async () => {
const { result: errorResponse } = shallowHook(() =>
useGetAuthorization({
+ useNavigate: () => jest.fn(),
useSelectorsResponse: () => ({
error: true,
data: {
@@ -33,6 +34,7 @@ describe('AuthenticationContext', () => {
const { result: successResponse } = await mountHook(() =>
useGetAuthorization({
useDispatch: () => mockDispatch,
+ useNavigate: () => jest.fn(),
useSelectorsResponse: () => ({
fulfilled: true,
data: {
@@ -52,57 +54,66 @@ describe('AuthenticationContext', () => {
expect(mockDispatch.mock.calls).toMatchSnapshot('success dispatch');
expect(successResponse).toMatchSnapshot('success response');
- const { result: mockStoreSuccessResponse } = shallowHook(() => useGetAuthorization(), {
- state: {
- user: {
- auth: {
- fulfilled: true,
- data: [
- { isAdmin: true, isEntitled: true },
- {
- permissions: [
- {
- subscriptions: {
- all: true,
- resources: {
- '*': {
- '*': [],
- loremCustom: [],
- read: []
+ const { result: mockStoreSuccessResponse } = shallowHook(
+ () => useGetAuthorization({ useNavigate: () => jest.fn() }),
+ {
+ state: {
+ user: {
+ auth: {
+ fulfilled: true,
+ data: [
+ { isAdmin: true, isEntitled: true },
+ {
+ permissions: [
+ {
+ subscriptions: {
+ all: true,
+ resources: {
+ '*': {
+ '*': [],
+ loremCustom: [],
+ read: []
+ }
}
}
}
+ ],
+ authorized: {
+ subscriptions: true
}
- ],
- authorized: {
- subscriptions: true
}
- }
- ]
- },
- locale: { fulfilled: true, data: {} },
- errors: {}
+ ]
+ },
+ locale: { fulfilled: true, data: {} },
+ errors: {}
+ }
}
}
- });
+ );
expect(mockStoreSuccessResponse).toMatchSnapshot('mock store success response');
- const { result: mockStoreErrorResponse } = shallowHook(() => useGetAuthorization(), {
- state: {
- user: {
- auth: {
- error: true,
- data: []
- },
- locale: { fulfilled: true, data: {} },
- errors: {
- error: true,
- data: ['lorem', 'ipsum']
+ const { result: mockStoreErrorResponse } = shallowHook(
+ () =>
+ useGetAuthorization({
+ useNavigate: () => jest.fn()
+ }),
+ {
+ state: {
+ user: {
+ auth: {
+ error: true,
+ data: []
+ },
+ locale: { fulfilled: true, data: {} },
+ errors: {
+ error: true,
+ data: ['lorem', 'ipsum']
+ }
}
}
}
- });
+ );
expect(mockStoreErrorResponse).toMatchSnapshot('mock store error response');
});
diff --git a/src/components/authentication/authenticationContext.js b/src/components/authentication/authenticationContext.js
index 7361a4014..f511a6f82 100644
--- a/src/components/authentication/authenticationContext.js
+++ b/src/components/authentication/authenticationContext.js
@@ -1,9 +1,9 @@
-import React, { useContext } from 'react';
-import { useMount } from 'react-use';
+import React, { useContext, useState } from 'react';
+import { useMount, useUnmount } from 'react-use';
import { useChrome } from '@redhat-cloud-services/frontend-components/useChrome';
import { reduxActions, storeHooks } from '../../redux';
import { helpers } from '../../common';
-import { routerHelpers } from '../router';
+import { routerContext, routerHelpers } from '../router';
/**
* @memberof Authentication
@@ -33,8 +33,10 @@ const useAuthContext = () => useContext(AuthenticationContext);
* @param {string} options.appName
* @param {Function} options.authorizeUser
* @param {Function} options.hideGlobalFilter
+ * @param {Function} options.onNavigation
* @param {Function} options.useChrome
* @param {Function} options.useDispatch
+ * @param {Function} options.useNavigate
* @param {Function} options.useSelectorsResponse
* @returns {{data: {errorCodes, errorStatus: *, locale}, pending: boolean, fulfilled: boolean, error: boolean}}
*/
@@ -42,10 +44,14 @@ const useGetAuthorization = ({
appName = routerHelpers.appName,
authorizeUser = reduxActions.platform.authorizeUser,
hideGlobalFilter = reduxActions.platform.hideGlobalFilter,
+ onNavigation = reduxActions.platform.onNavigation,
useChrome: useAliasChrome = useChrome,
useDispatch: useAliasDispatch = storeHooks.reactRedux.useDispatch,
+ useNavigate: useAliasNavigate = routerContext.useNavigate,
useSelectorsResponse: useAliasSelectorsResponse = storeHooks.reactRedux.useSelectorsResponse
} = {}) => {
+ const [unregister, setUnregister] = useState(() => helpers.noop);
+ const navigate = useAliasNavigate();
const dispatch = useAliasDispatch();
const { updateDocumentTitle = helpers.noop } = useAliasChrome();
const { data, error, fulfilled, pending, responses } = useAliasSelectorsResponse([
@@ -61,6 +67,11 @@ const useGetAuthorization = ({
await dispatch(authorizeUser());
updateDocumentTitle(appName);
dispatch([hideGlobalFilter()]);
+ setUnregister(() => dispatch(onNavigation(event => navigate(event.navId))));
+ });
+
+ useUnmount(() => {
+ unregister();
});
const [user = {}, app = {}] = (Array.isArray(data.auth) && data.auth) || [];
diff --git a/src/redux/README.md b/src/redux/README.md
index daf22d8e2..9f280a98a 100644
--- a/src/redux/README.md
+++ b/src/redux/README.md
@@ -80,6 +80,7 @@ Platform service wrappers for dispatch, state update.
* [~clearNotifications()](#Actions.module_PlatformActions..clearNotifications) ⇒ \*
* [~authorizeUser(appName)](#Actions.module_PlatformActions..authorizeUser) ⇒ function
* [~hideGlobalFilter(isHidden)](#Actions.module_PlatformActions..hideGlobalFilter) ⇒ Object
+ * [~onNavigation(callback)](#Actions.module_PlatformActions..onNavigation) ⇒ function
@@ -159,6 +160,24 @@ Hide platform global filter.
+
+
+### PlatformActions~onNavigation(callback) ⇒ function
+Apply platform method for updating routing history on "navigating" with the left-nav.
+
+**Kind**: inner method of [PlatformActions
](#Actions.module_PlatformActions)
+
+
+
+ Param | Type |
+
+
+
+
+ callback | function |
+
+
+
## RhsmActions
diff --git a/src/redux/actions/__tests__/__snapshots__/platformActions.test.js.snap b/src/redux/actions/__tests__/__snapshots__/platformActions.test.js.snap
index fd1e38a27..1fe44e5d4 100644
--- a/src/redux/actions/__tests__/__snapshots__/platformActions.test.js.snap
+++ b/src/redux/actions/__tests__/__snapshots__/platformActions.test.js.snap
@@ -6,3 +6,7 @@ exports[`PlatformActions Should return a dispatch object for the hideGlobalFilte
"type": "PLATFORM_GLOBAL_FILTER_HIDE",
}
`;
+
+exports[`PlatformActions Should return a function for the onNavigation method: expected process 1`] = `"lorem ipsum"`;
+
+exports[`PlatformActions Should return a function for the onNavigation method: function 1`] = `[Function]`;
diff --git a/src/redux/actions/__tests__/platformActions.test.js b/src/redux/actions/__tests__/platformActions.test.js
index 7d2f173e2..6eeccebd4 100644
--- a/src/redux/actions/__tests__/platformActions.test.js
+++ b/src/redux/actions/__tests__/platformActions.test.js
@@ -28,4 +28,12 @@ describe('PlatformActions', () => {
it('Should return a dispatch object for the hideGlobalFilter method', () => {
expect(platformActions.hideGlobalFilter()).toMatchSnapshot('dispatch object');
});
+
+ it('Should return a function for the onNavigation method', () => {
+ expect(platformActions.onNavigation()).toMatchSnapshot('function');
+
+ window.insights.chrome.on = jest.fn().mockImplementation((id, value) => value('lorem'));
+ const dispatch = obj => obj;
+ expect(platformActions.onNavigation(event => `${event} ipsum`)(dispatch)).toMatchSnapshot('expected process');
+ });
});
diff --git a/src/redux/actions/platformActions.js b/src/redux/actions/platformActions.js
index ad184432e..978dbc1d6 100644
--- a/src/redux/actions/platformActions.js
+++ b/src/redux/actions/platformActions.js
@@ -59,12 +59,26 @@ const hideGlobalFilter = isHidden => ({
payload: platformServices.hideGlobalFilter(isHidden)
});
+/**
+ * Apply platform method for updating routing history on "navigating" with the left-nav.
+ *
+ * @param {Function} callback
+ * @returns {Function}
+ */
+const onNavigation = callback => dispatch => {
+ dispatch({
+ type: platformTypes.PLATFORM_ON_NAV
+ });
+ return platformServices.onNavigation(callback);
+};
+
const platformActions = {
addNotification,
removeNotification,
clearNotifications,
authorizeUser,
- hideGlobalFilter
+ hideGlobalFilter,
+ onNavigation
};
export {
@@ -74,5 +88,6 @@ export {
removeNotification,
clearNotifications,
authorizeUser,
- hideGlobalFilter
+ hideGlobalFilter,
+ onNavigation
};
diff --git a/src/redux/types/__tests__/__snapshots__/index.test.js.snap b/src/redux/types/__tests__/__snapshots__/index.test.js.snap
index 6317adb1b..77f303c42 100644
--- a/src/redux/types/__tests__/__snapshots__/index.test.js.snap
+++ b/src/redux/types/__tests__/__snapshots__/index.test.js.snap
@@ -24,6 +24,7 @@ exports[`ReduxTypes should have specific type properties: all redux types 1`] =
"PLATFORM_ADD_NOTIFICATION": "@@INSIGHTS-CORE/NOTIFICATIONS/ADD_NOTIFICATION",
"PLATFORM_CLEAR_NOTIFICATIONS": "@@INSIGHTS-CORE/NOTIFICATIONS/CLEAR_NOTIFICATIONS",
"PLATFORM_GLOBAL_FILTER_HIDE": "PLATFORM_GLOBAL_FILTER_HIDE",
+ "PLATFORM_ON_NAV": "PLATFORM_ON_NAV",
"PLATFORM_REMOVE_NOTIFICATION": "@@INSIGHTS-CORE/NOTIFICATIONS/REMOVE_NOTIFICATION",
"PLATFORM_USER_AUTH": "PLATFORM_USER_AUTH",
},
@@ -93,6 +94,7 @@ exports[`ReduxTypes should have specific type properties: all redux types 1`] =
"PLATFORM_ADD_NOTIFICATION": "@@INSIGHTS-CORE/NOTIFICATIONS/ADD_NOTIFICATION",
"PLATFORM_CLEAR_NOTIFICATIONS": "@@INSIGHTS-CORE/NOTIFICATIONS/CLEAR_NOTIFICATIONS",
"PLATFORM_GLOBAL_FILTER_HIDE": "PLATFORM_GLOBAL_FILTER_HIDE",
+ "PLATFORM_ON_NAV": "PLATFORM_ON_NAV",
"PLATFORM_REMOVE_NOTIFICATION": "@@INSIGHTS-CORE/NOTIFICATIONS/REMOVE_NOTIFICATION",
"PLATFORM_USER_AUTH": "PLATFORM_USER_AUTH",
},
@@ -146,6 +148,7 @@ exports[`ReduxTypes should have specific type properties: all redux types 1`] =
"PLATFORM_ADD_NOTIFICATION": "@@INSIGHTS-CORE/NOTIFICATIONS/ADD_NOTIFICATION",
"PLATFORM_CLEAR_NOTIFICATIONS": "@@INSIGHTS-CORE/NOTIFICATIONS/CLEAR_NOTIFICATIONS",
"PLATFORM_GLOBAL_FILTER_HIDE": "PLATFORM_GLOBAL_FILTER_HIDE",
+ "PLATFORM_ON_NAV": "PLATFORM_ON_NAV",
"PLATFORM_REMOVE_NOTIFICATION": "@@INSIGHTS-CORE/NOTIFICATIONS/REMOVE_NOTIFICATION",
"PLATFORM_USER_AUTH": "PLATFORM_USER_AUTH",
},
@@ -246,6 +249,7 @@ exports[`ReduxTypes should have specific type properties: specific types 1`] = `
"PLATFORM_ADD_NOTIFICATION": "@@INSIGHTS-CORE/NOTIFICATIONS/ADD_NOTIFICATION",
"PLATFORM_CLEAR_NOTIFICATIONS": "@@INSIGHTS-CORE/NOTIFICATIONS/CLEAR_NOTIFICATIONS",
"PLATFORM_GLOBAL_FILTER_HIDE": "PLATFORM_GLOBAL_FILTER_HIDE",
+ "PLATFORM_ON_NAV": "PLATFORM_ON_NAV",
"PLATFORM_REMOVE_NOTIFICATION": "@@INSIGHTS-CORE/NOTIFICATIONS/REMOVE_NOTIFICATION",
"PLATFORM_USER_AUTH": "PLATFORM_USER_AUTH",
},
diff --git a/src/redux/types/platformTypes.js b/src/redux/types/platformTypes.js
index 541883db1..b138854e2 100644
--- a/src/redux/types/platformTypes.js
+++ b/src/redux/types/platformTypes.js
@@ -13,19 +13,21 @@ const PLATFORM_ADD_NOTIFICATION = ADD_NOTIFICATION;
const PLATFORM_REMOVE_NOTIFICATION = REMOVE_NOTIFICATION;
const PLATFORM_CLEAR_NOTIFICATIONS = CLEAR_NOTIFICATIONS;
const PLATFORM_GLOBAL_FILTER_HIDE = 'PLATFORM_GLOBAL_FILTER_HIDE';
+const PLATFORM_ON_NAV = 'PLATFORM_ON_NAV';
const PLATFORM_USER_AUTH = 'PLATFORM_USER_AUTH';
/**
* Platform action, reducer types.
*
* @type {{PLATFORM_USER_AUTH: string, PLATFORM_GLOBAL_FILTER_HIDE: string, PLATFORM_CLEAR_NOTIFICATIONS: string,
- * PLATFORM_ADD_NOTIFICATION: string, PLATFORM_REMOVE_NOTIFICATION: string}}
+ * PLATFORM_ADD_NOTIFICATION: string, PLATFORM_REMOVE_NOTIFICATION: string, PLATFORM_ON_NAV: string}}
*/
const platformTypes = {
PLATFORM_ADD_NOTIFICATION,
PLATFORM_REMOVE_NOTIFICATION,
PLATFORM_CLEAR_NOTIFICATIONS,
PLATFORM_GLOBAL_FILTER_HIDE,
+ PLATFORM_ON_NAV,
PLATFORM_USER_AUTH
};
@@ -36,5 +38,6 @@ export {
PLATFORM_REMOVE_NOTIFICATION,
PLATFORM_CLEAR_NOTIFICATIONS,
PLATFORM_GLOBAL_FILTER_HIDE,
+ PLATFORM_ON_NAV,
PLATFORM_USER_AUTH
};
diff --git a/src/services/README.md b/src/services/README.md
index 3236859c5..a1b94bc80 100644
--- a/src/services/README.md
+++ b/src/services/README.md
@@ -325,6 +325,7 @@ Emulated service calls for platform globals.
* [~getUser(options)](#Platform.module_PlatformServices..getUser) ⇒ Promise.<\*>
* [~getUserPermissions(appName, options)](#Platform.module_PlatformServices..getUserPermissions) ⇒ Promise.<\*>
* [~hideGlobalFilter(isHidden)](#Platform.module_PlatformServices..hideGlobalFilter) ⇒ Promise.<\*>
+ * [~onNavigation(callback)](#Platform.module_PlatformServices..onNavigation) ⇒ function
@@ -382,6 +383,24 @@ Disables the Platform's global filter display.
+
+
+### PlatformServices~onNavigation(callback) ⇒ function
+Apply on "app_navigation" event. Return an un-listener.
+
+**Kind**: inner method of [PlatformServices
](#Platform.module_PlatformServices)
+
+
+
+ Param | Type |
+
+
+
+
+ callback | function |
+
+
+
## PlatformTransformers
diff --git a/src/services/platform/__tests__/platformServices.test.js b/src/services/platform/__tests__/platformServices.test.js
index dd02c68a9..200e13b2c 100644
--- a/src/services/platform/__tests__/platformServices.test.js
+++ b/src/services/platform/__tests__/platformServices.test.js
@@ -15,13 +15,14 @@ describe('PlatformServices', () => {
};
it('should export a specific number of methods and classes', () => {
- expect(Object.keys(platformServices)).toHaveLength(3);
+ expect(Object.keys(platformServices)).toHaveLength(4);
});
it('should have specific methods', () => {
expect(platformServices.getUser).toBeDefined();
expect(platformServices.getUserPermissions).toBeDefined();
expect(platformServices.hideGlobalFilter).toBeDefined();
+ expect(platformServices.onNavigation).toBeDefined();
});
/**
@@ -68,4 +69,9 @@ describe('PlatformServices', () => {
expect(response).toMatchSnapshot('failed hideGlobalFilter');
});
+
+ it('should return a failed onNavigation', () => {
+ window.insights.chrome.on = undefined;
+ expect(platformServices.onNavigation).toThrow('{ on } = insights.chrome, insights.chrome.on is not a function');
+ });
});
diff --git a/src/services/platform/platformServices.js b/src/services/platform/platformServices.js
index 260389981..2b9a77dce 100644
--- a/src/services/platform/platformServices.js
+++ b/src/services/platform/platformServices.js
@@ -108,10 +108,26 @@ const hideGlobalFilter = async (isHidden = true) => {
}
};
+/**
+ * Apply on "app_navigation" event. Return an un-listener.
+ *
+ * @param {Function} callback
+ * @returns {Function}
+ */
+const onNavigation = callback => {
+ const { insights } = window;
+ try {
+ return insights.chrome.on('APP_NAVIGATION', callback);
+ } catch (e) {
+ throw new Error(`{ on } = insights.chrome, ${e.message}`);
+ }
+};
+
const platformServices = {
getUser,
getUserPermissions,
- hideGlobalFilter
+ hideGlobalFilter,
+ onNavigation
};
-export { platformServices as default, platformServices, getUser, getUserPermissions, hideGlobalFilter };
+export { platformServices as default, platformServices, getUser, getUserPermissions, hideGlobalFilter, onNavigation };
diff --git a/tests/__snapshots__/dist.test.js.snap b/tests/__snapshots__/dist.test.js.snap
index 4a9c98540..ac2f31693 100644
--- a/tests/__snapshots__/dist.test.js.snap
+++ b/tests/__snapshots__/dist.test.js.snap
@@ -289,6 +289,7 @@ exports[`Build distribution should match a specific file output 1`] = `
"./dist/js/2217*js",
"./dist/js/2227*js",
"./dist/js/2243*js",
+ "./dist/js/2293*js",
"./dist/js/2622*js",
"./dist/js/2701*js",
"./dist/js/2738*js",
@@ -299,9 +300,10 @@ exports[`Build distribution should match a specific file output 1`] = `
"./dist/js/2948*js",
"./dist/js/31*js",
"./dist/js/3128*js",
+ "./dist/js/325*js",
+ "./dist/js/325*txt",
"./dist/js/3267*js",
"./dist/js/3280*js",
- "./dist/js/3385*js",
"./dist/js/353*js",
"./dist/js/3557*js",
"./dist/js/3597*js",
@@ -321,8 +323,6 @@ exports[`Build distribution should match a specific file output 1`] = `
"./dist/js/5242*js",
"./dist/js/5394*js",
"./dist/js/5426*js",
- "./dist/js/5704*js",
- "./dist/js/5704*txt",
"./dist/js/5876*js",
"./dist/js/5925*js",
"./dist/js/5993*js",
@@ -372,6 +372,7 @@ exports[`Build distribution should match a specific file output 1`] = `
"./dist/sourcemaps/2217*map",
"./dist/sourcemaps/2227*map",
"./dist/sourcemaps/2243*map",
+ "./dist/sourcemaps/2293*map",
"./dist/sourcemaps/2622*map",
"./dist/sourcemaps/2701*map",
"./dist/sourcemaps/2738*map",
@@ -382,9 +383,9 @@ exports[`Build distribution should match a specific file output 1`] = `
"./dist/sourcemaps/2948*map",
"./dist/sourcemaps/31*map",
"./dist/sourcemaps/3128*map",
+ "./dist/sourcemaps/325*map",
"./dist/sourcemaps/3267*map",
"./dist/sourcemaps/3280*map",
- "./dist/sourcemaps/3385*map",
"./dist/sourcemaps/353*map",
"./dist/sourcemaps/3557*map",
"./dist/sourcemaps/3597*map",
@@ -401,7 +402,6 @@ exports[`Build distribution should match a specific file output 1`] = `
"./dist/sourcemaps/5242*map",
"./dist/sourcemaps/5394*map",
"./dist/sourcemaps/5426*map",
- "./dist/sourcemaps/5704*map",
"./dist/sourcemaps/5876*map",
"./dist/sourcemaps/5925*map",
"./dist/sourcemaps/5993*map",