From a0ee1a7793acba438c75bb6b232f24b0cb82eaf9 Mon Sep 17 00:00:00 2001 From: p-netm Date: Tue, 4 Apr 2023 16:26:15 +0300 Subject: [PATCH] Refactor the home view (#1198) * Refactor how call to action buttons on homepage are generated * Fix test regressions * Add comments and fix typo --- app/src/App/tests/App.test.tsx | 2 +- app/src/containers/pages/Home/Home.tsx | 95 ++-- .../containers/pages/Home/tests/Home.test.tsx | 105 ++-- .../tests/__snapshots__/Home.test.tsx.snap | 537 +++--------------- app/src/routes/index.tsx | 49 +- app/src/routes/tests/index.test.tsx | 3 - 6 files changed, 236 insertions(+), 555 deletions(-) diff --git a/app/src/App/tests/App.test.tsx b/app/src/App/tests/App.test.tsx index 2ebec1bbc..f9eb15674 100644 --- a/app/src/App/tests/App.test.tsx +++ b/app/src/App/tests/App.test.tsx @@ -183,7 +183,7 @@ describe('App - authenticated', () => { ); // before resolving get oauth state request, the user is logged out expect(wrapper.text()).toMatchInlineSnapshot( - `"InventoryAdministrationdemoWelcome to OpenSRPUser Management"` + `"InventoryAdministrationdemoWelcome to OpenSRPInventoryProduct CatalogueQuestionnaire ManagementUser Management"` ); await act(async () => { diff --git a/app/src/containers/pages/Home/Home.tsx b/app/src/containers/pages/Home/Home.tsx index d9967f546..3c04aa683 100644 --- a/app/src/containers/pages/Home/Home.tsx +++ b/app/src/containers/pages/Home/Home.tsx @@ -1,19 +1,33 @@ import { Helmet } from 'react-helmet'; -import { Col, Row, Button } from 'antd'; +import { Col, Row, Button, Alert } from 'antd'; import { Link } from 'react-router-dom'; import './Home.css'; import { useTranslation } from '../../../mls'; -import { URL_USER, URL_LOCATION_UNIT, URL_TEAM_ASSIGNMENT, URL_TEAMS } from '../../../constants'; -import { ENABLE_TEAMS_ASSIGNMENT_MODULE } from '../../../configs/env'; import React from 'react'; -import { - COMPOSITE_ENABLE_LOCATIONS_MANAGEMENT, - COMPOSITE_ENABLE_TEAM_MANAGEMENT, - COMPOSITE_ENABLE_USER_MANAGEMENT, -} from '../../../configs/settings'; +import { useSelector } from 'react-redux'; +import { getExtraData } from '@onaio/session-reducer'; +import { getRoutesForHomepage } from '../../../routes'; export const Home = () => { const { t } = useTranslation(); + const extraData = useSelector((state) => { + return getExtraData(state); + }); + const { roles } = extraData; + const routes = React.useMemo(() => getRoutesForHomepage(roles as string[], t), [roles, t]); + + // home page has 2 columns by defualt + let columnNum = 2; + // then depending on enabled modules set the number of colums to either 3 or 4 + if (routes.length < 5) { + columnNum = 2; + } else if (routes.length < 7) { + columnNum = 3; + } else { + columnNum = 4; + } + + const normalSpanLength = 24 / columnNum; return (
@@ -25,49 +39,38 @@ export const Home = () => {

{t('Welcome to OpenSRP')}

- - {COMPOSITE_ENABLE_USER_MANAGEMENT && ( - - - - - + + {routes.length === 0 && ( + )} - {COMPOSITE_ENABLE_TEAM_MANAGEMENT && ( - - - - - - )} - - - {COMPOSITE_ENABLE_LOCATIONS_MANAGEMENT && ( - <> - - + {routes.map((route) => { + return ( + + - - )} - - - {ENABLE_TEAMS_ASSIGNMENT_MODULE && ( - - - - - - )} + ); + })}
); diff --git a/app/src/containers/pages/Home/tests/Home.test.tsx b/app/src/containers/pages/Home/tests/Home.test.tsx index 9affeb0d5..ca2e8b33e 100644 --- a/app/src/containers/pages/Home/tests/Home.test.tsx +++ b/app/src/containers/pages/Home/tests/Home.test.tsx @@ -1,43 +1,22 @@ -import { mount } from 'enzyme'; -import toJson from 'enzyme-to-json'; import { history } from '@onaio/connected-reducer-registry'; -import React from 'react'; import { Helmet } from 'react-helmet'; import { Router } from 'react-router'; import { Home } from '../Home'; import { store } from '@opensrp/store'; import { Provider } from 'react-redux'; -import { - URL_LOCATION_UNIT, - URL_LOCATION_UNIT_GROUP, - URL_TEAMS, - URL_USER, -} from '../../../../constants'; +import { cleanup, render, screen } from '@testing-library/react'; +import { authenticateUser } from '@onaio/session-reducer'; +import React from 'react'; jest.mock('../../../../configs/env'); jest.mock('../../../../configs/settings'); describe('containers/pages/Home', () => { - it('renders Home correctly & changes Title of page', () => { - const wrapper = mount( - - - - ); - - const helmet = Helmet.peek(); - expect(helmet.title).toEqual('OpenSRP Web'); - wrapper.find('.admin-link').forEach((adminLink) => { - expect(toJson(adminLink)).toMatchSnapshot('links on home page'); - }); - wrapper.unmount(); + afterEach(() => { + cleanup(); }); - - it('displays links for user management module', () => { - const envModule = require('../../../../configs/env'); - envModule.ENABLE_USER_MANAGEMENT = true; - - const wrapper = mount( + it('renders Home correctly & changes Title of page', () => { + render( @@ -45,30 +24,46 @@ describe('containers/pages/Home', () => { ); - expect(wrapper.find(`Link[to="${URL_USER}"]`)).toHaveLength(1); + const helmet = Helmet.peek(); + expect(helmet.title).toEqual('OpenSRP Web'); + screen.getByText(/Missing the required permissions to view data on this page/i); }); - it('displays links for location unit module', () => { - const envModule = require('../../../../configs/env'); - envModule.ENABLE_LOCATIONS = true; - - const wrapper = mount( - - - - - + it('renders Home correctly & changes Title of page 2', () => { + store.dispatch( + authenticateUser( + true, + { email: 'bob@example.com', name: 'Bobbie', username: 'RobertBaratheon' }, + { + roles: ['ROLE_VIEW_KEYCLOAK_USERS'], + username: 'superset-user', + user_id: 'cab07278-c77b-4bc7-b154-bcbf01b7d35b', + } + ) ); - - expect(wrapper.find(`Link[to="${URL_LOCATION_UNIT}"]`)).toHaveLength(1); - expect(wrapper.find(`Link[to="${URL_LOCATION_UNIT_GROUP}"]`)).toHaveLength(0); - }); - - it('displays links for teams module', () => { const envModule = require('../../../../configs/env'); + envModule.ENABLE_LOCATIONS = true; envModule.ENABLE_TEAMS = true; - - const wrapper = mount( + envModule.ENABLE_INVENTORY = true; + envModule.ENABLE_FORM_CONFIGURATION = true; + envModule.ENABLE_TEAMS_ASSIGNMENT_MODULE = true; + envModule.ENABLE_PRODUCT_CATALOGUE = true; + envModule.ENABLE_PLANS = true; + envModule.ENABLE_CARD_SUPPORT = true; + envModule.ENABLE_USER_MANAGEMENT = true; + envModule.ENABLE_LOCATIONS = true; + envModule.ENABLE_TEAMS = true; + envModule.OPENSRP_ROLES = { + USERS: 'ROLE_EDIT_KEYCLOAK_USERS', + PLANS: 'ROLE_VIEW_KEYCLOAK_USERS', + CARD_SUPPORT: 'ROLE_VIEW_KEYCLOAK_USERS', + PRODUCT_CATALOGUE: 'ROLE_VIEW_KEYCLOAK_USERS', + FORM_CONFIGURATION: 'ROLE_VIEW_KEYCLOAK_USERS', + LOCATIONS: 'ROLE_VIEW_KEYCLOAK_USERS', + INVENTORY: 'ROLE_VIEW_KEYCLOAK_USERS', + TEAMS: 'ROLE_VIEW_KEYCLOAK_USERS', + }; + render( @@ -76,6 +71,20 @@ describe('containers/pages/Home', () => { ); - expect(wrapper.find(`Link[to="${URL_TEAMS}"]`)).toHaveLength(1); + const helmet = Helmet.peek(); + expect(helmet.title).toEqual('OpenSRP Web'); + const links = [...screen.queryAllByRole('link')]; + expect(links.map((x) => x.textContent)).toEqual([ + 'Card Support', + 'Form Configuration', + 'Inventory', + 'Location Management', + 'Plans', + 'Product Catalogue', + 'Team Management', + ]); + links.forEach((link) => { + expect(link).toMatchSnapshot(link.textContent ?? undefined); + }); }); }); diff --git a/app/src/containers/pages/Home/tests/__snapshots__/Home.test.tsx.snap b/app/src/containers/pages/Home/tests/__snapshots__/Home.test.tsx.snap index 3742c98b1..ac8ffa9ab 100644 --- a/app/src/containers/pages/Home/tests/__snapshots__/Home.test.tsx.snap +++ b/app/src/containers/pages/Home/tests/__snapshots__/Home.test.tsx.snap @@ -1,493 +1,120 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 1`] = ` - - - - - - - - - -`; - -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 2`] = ` - - - - - - - -`; - -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 3`] = ` +exports[`containers/pages/Home renders Home correctly & changes Title of page 2: Card Support 1`] = ` - - - + + Card Support + + `; -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 4`] = ` - - - - - - - - - + + Form Configuration + + + `; -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 5`] = ` - - - - - - - + + Inventory + + + `; -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 6`] = ` +exports[`containers/pages/Home renders Home correctly & changes Title of page 2: Location Management 1`] = ` - - - + + Location Management + + `; -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 7`] = ` - - - - - - - - - + + Plans + + + `; -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 8`] = ` - - - - - - - + + Product Catalogue + + + `; -exports[`containers/pages/Home renders Home correctly & changes Title of page: links on home page 9`] = ` +exports[`containers/pages/Home renders Home correctly & changes Title of page 2: Team Management 1`] = ` - - - + + Team Management + + `; diff --git a/app/src/routes/index.tsx b/app/src/routes/index.tsx index adeb9189b..c58b2457a 100644 --- a/app/src/routes/index.tsx +++ b/app/src/routes/index.tsx @@ -42,7 +42,6 @@ import { URL_USER_ROLES, URL_SERVER_SETTINGS, URL_FHIR_CARE_TEAM, - URL_ADMIN, URL_DOWNLOAD_DISTRICT_REPORT, } from '../constants'; import { QUEST_VIEW_URL } from '@opensrp/fhir-views'; @@ -63,12 +62,17 @@ export interface Route { enabled?: boolean; url?: string; title: string; + isHomePageLink?: boolean; otherProps?: { icon?: string | JSX.Element; }; children?: Route[]; } +export interface GetRoutes { + (roles: string[], t: TFunction): Route[]; +} + /** Gets Routes For Application * * @param roles User's roles @@ -82,6 +86,8 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { otherProps: { icon: }, title: t('Plans'), key: 'plans', + url: ACTIVE_PLANS_LIST_VIEW_URL, + isHomePageLink: true, enabled: ENABLE_PLANS && roles && @@ -98,6 +104,8 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { otherProps: { icon: }, title: t('Card Support'), key: 'card-support', + url: URL_DOWNLOAD_CLIENT_DATA, + isHomePageLink: true, enabled: ENABLE_CARD_SUPPORT && roles && @@ -115,6 +123,8 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { otherProps: { icon: }, title: t('Inventory'), key: 'inventory', + isHomePageLink: true, + url: INVENTORY_SERVICE_POINT_LIST_VIEW, enabled: ENABLE_INVENTORY && roles && @@ -138,11 +148,12 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { title: t('Administration'), key: 'admin', enabled: true, - url: URL_ADMIN, children: [ { title: t('User Management'), key: 'user-management', + isHomePageLink: true, + url: URL_USER, enabled: COMPOSITE_ENABLE_USER_MANAGEMENT && roles && @@ -157,6 +168,8 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { { title: t('Location Management'), key: 'location-management', + isHomePageLink: true, + url: URL_LOCATION_UNIT, enabled: COMPOSITE_ENABLE_LOCATIONS_MANAGEMENT && roles && @@ -175,6 +188,7 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { { title: t('Product Catalogue'), key: 'product-catalogue', + isHomePageLink: true, enabled: ENABLE_PRODUCT_CATALOGUE && roles && @@ -185,6 +199,7 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { { title: t('Care Teams Management'), key: 'fhir-care-team', + isHomePageLink: true, enabled: ENABLE_FHIR_CARE_TEAM && roles && @@ -195,6 +210,7 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { { title: t('Team Management'), key: 'team-management', + isHomePageLink: true, enabled: COMPOSITE_ENABLE_TEAM_MANAGEMENT && roles && @@ -214,6 +230,7 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { title: t('Group Management'), key: 'fhir-group', url: LIST_GROUP_URL, + isHomePageLink: true, enabled: ENABLE_FHIR_GROUP && roles && @@ -223,6 +240,7 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { { title: t('Commodity Management'), key: 'fhir-commodity', + isHomePageLink: true, url: LIST_COMMODITY_URL, enabled: ENABLE_FHIR_COMMODITY && @@ -239,10 +257,12 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { activeRoles.QUEST && isAuthorized(roles, activeRoles.QUEST.split(',')), url: QUEST_VIEW_URL, + isHomePageLink: true, }, { title: t('Healthcare Services'), key: 'healthcare', + isHomePageLink: true, url: LIST_HEALTHCARE_URL, enabled: ENABLE_HEALTHCARE_SERVICES && @@ -253,6 +273,8 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { { title: t('Form Configuration'), key: 'form-config', + isHomePageLink: true, + url: URL_MANIFEST_RELEASE_LIST, enabled: ENABLE_FORM_CONFIGURATION && roles && @@ -281,10 +303,13 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { activeRoles.SERVER_SETTINGS && isAuthorized(roles, activeRoles.SERVER_SETTINGS.split(',')), url: URL_SERVER_SETTINGS, + isHomePageLink: true, }, { title: t('Reports'), key: 'reports', + url: URL_DOWNLOAD_DISTRICT_REPORT, + isHomePageLink: true, enabled: ENABLE_REPORTS && roles && @@ -310,6 +335,7 @@ export function getRoutes(roles: string[], t: TFunction): Route[] { key: 'fhir-patients', enabled: ENABLE_PATIENTS_MODULE, url: LIST_PATIENTS_URL, + isHomePageLink: true, }, ]; @@ -330,3 +356,22 @@ export function filterFalsyRoutes(routes: Route[]): Route[] { return e.children ? { ...e, children: filterFalsyRoutes(e.children) } : e; }); } + +export const getRoutesForHomepage: GetRoutes = (roles, t) => { + const routes = getRoutes(roles, t); + const homePageRoutes: Route[] = []; + + function extractHomePAgeLink(routes: Route[]) { + for (const route of routes) { + if (route.isHomePageLink) { + homePageRoutes.push(route); + } + if (route.children) { + extractHomePAgeLink(route.children); + } + } + } + + extractHomePAgeLink(routes); + return homePageRoutes.sort((route1, route2) => route1.title.localeCompare(route2.title)); +}; diff --git a/app/src/routes/tests/index.test.tsx b/app/src/routes/tests/index.test.tsx index aa4596c09..d5f9e4c0e 100644 --- a/app/src/routes/tests/index.test.tsx +++ b/app/src/routes/tests/index.test.tsx @@ -54,7 +54,6 @@ describe('routes', () => { enabled: true, key: 'admin', title: 'Administration', - url: '/admin', }, ]); @@ -82,7 +81,6 @@ describe('routes', () => { enabled: true, key: 'admin', title: 'Administration', - url: '/admin', }, ]); }); @@ -300,7 +298,6 @@ describe('routes', () => { icon: , }, title: 'Administration', - url: '/admin', }, ]); // check inventory bulk upload title in routes as second item under inventory sub menu