Skip to content

Commit

Permalink
HMS-1623 refact: application context
Browse files Browse the repository at this point in the history
Simplify the application context so it is cleaner and easier to add
changes in the future. It adds AppContextProvider tag and refactor
according to it. This new tag assign the setters and the value of the
current states so it is propagated accordingly to the rest of the
application (no more getter callbacks).

Signed-off-by: Alejandro Visiedo <[email protected]>
  • Loading branch information
avisiedo committed Oct 31, 2023
1 parent 8801822 commit 7c3d4af
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 163 deletions.
98 changes: 56 additions & 42 deletions src/AppContext.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
import { createContext } from 'react';
import { ReactNode, createContext, useState } from 'react';
import { Domain } from './Api';
import { VerifyState } from './Routes/WizardPage/Components/VerifyRegistry/VerifyRegistry';
import React from 'react';

/**
* It represents the application context so common events and properties
* are shared for many components, making their values accessible.
* @public
*/
export interface IAppContext {
export interface AppContextType {
/** Represent the current list of domains to be displayed in the listDomains view. */
getDomains: () => Domain[];
domains: Domain[];
/** Callback to set the value of `domains`. */
setDomains: (domains: Domain[]) => void;
/** The current editing domain */
getEditing: () => Domain | undefined;
editing?: Domain;
/** Set the current editing domain */
setEditing: (value: Domain | undefined) => void;
setEditing: (value?: Domain) => void;

/** Encapsulates the context related with the wizard. */
wizard: {
/** Retrieve the current token, required to register a domain. */
getToken: () => string;
token: string;
/** Set the value of the token. */
setToken: (value: string) => void;

/** Retrieve the value of the registered status which is updated once
* the user has registered the domain by using ipa-hcc tool. */
getRegisteredStatus: () => VerifyState;
registeredStatus: VerifyState;
/** Setter for the registered status. */
setRegisteredStatus: (value: VerifyState) => void;

/** Get the ephemeral domain state that manage the wizard. */
getDomain: () => Domain;
domain: Domain;
/** Set the ephemeral domain information. */
setDomain: (value: Domain) => void;
};
Expand All @@ -38,37 +42,47 @@ export interface IAppContext {
* Represent the application context.
* @public
*/
export const AppContext = createContext<IAppContext>({
getDomains: (): Domain[] => {
return [];
},
setDomains: (domains: Domain[]) => {
throw new Error('Function "setDomains" not implemented: domains=' + domains);
},
getEditing: (): Domain | undefined => {
return undefined;
},
setEditing: (value: Domain | undefined) => {
throw new Error('Function "setEditing" not implemented: value=' + value);
},
wizard: {
getToken: (): string => {
return '';
},
setToken: (value: string) => {
throw new Error('Function "setToken" not implemented: value=' + value);
},
getRegisteredStatus: (): VerifyState => {
return 'initial';
},
setRegisteredStatus: (value: VerifyState) => {
throw new Error('Function "setRegisteredStatus" not implemented: value=' + value);
},
getDomain: (): Domain => {
return {} as Domain;
},
setDomain: (value: Domain) => {
throw new Error('Function "setDomain" not implemented: value=' + value);
},
},
});
export const AppContext = createContext<AppContextType | undefined>(undefined);

/**
* The properties accepted by the AppContextProvider.
*/
interface AppContextProviderProps {
/** The children components. */
children: ReactNode;
}

/**
* Define the provider for the application context.
* @param param0 The children components.
* @returns the application context.
*/
export const AppContextProvider: React.FC<AppContextProviderProps> = ({ children }) => {
const [domains, _setDomains] = useState<Domain[]>([]);
const [editing, _setEditing] = useState<Domain>();

const [wizardToken, _setWizardSetToken] = useState<string>();
const [wizardRegisteredStatus, _setWizardRegisteredStatus] = useState<VerifyState>('initial');
const [wizardDomain, _setWizardDomain] = useState<Domain>();

return (
<AppContext.Provider
value={{
domains: domains,
setDomains: _setDomains,
editing: editing,
setEditing: _setEditing,
wizard: {
token: wizardToken || '',
setToken: _setWizardSetToken,
registeredStatus: wizardRegisteredStatus,
setRegisteredStatus: _setWizardRegisteredStatus,
domain: wizardDomain || ({} as Domain),
setDomain: _setWizardDomain,
},
}}
>
{children}
</AppContext.Provider>
);
};
61 changes: 4 additions & 57 deletions src/AppEntry.tsx
Original file line number Diff line number Diff line change
@@ -1,72 +1,19 @@
import React, { useState } from 'react';
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import { init } from './store';
import App from './App';
import { getBaseName } from '@redhat-cloud-services/frontend-components-utilities/helpers';
import logger from 'redux-logger';
import { AppContext } from './AppContext';
import { Domain } from './Api';
import { VerifyState } from './Routes/WizardPage/Components/VerifyRegistry/VerifyRegistry';
import { AppContextProvider } from './AppContext';

const AppEntry = () => {
const [domains, setDomains] = useState<Domain[]>([]);
const [wizardToken, setWizardToken] = useState<string>('');
const [wizardDomain, setWizardDomain] = useState<Domain>({} as Domain);
const [wizardRegisterStatus, setWizardRegisterStatus] = useState<VerifyState>('initial');
const [editing, setEditing] = useState<Domain | undefined>(undefined);

const cbGetDomains = (): Domain[] => {
return domains;
};
const cbSetDomains = (domains: Domain[]) => {
setDomains(domains);
};
const cbGetWizardToken = (): string => {
return wizardToken;
};
const cbSetWizardToken = (value: string) => {
setWizardToken(value);
};
const cbGetWizardDomain = (): Domain => {
return wizardDomain;
};
const cbSetWizardDomain = (value: Domain) => {
setWizardDomain(value);
};
const cbGetRegisterStatus = (): VerifyState => {
return wizardRegisterStatus;
};
const cbSetRegisterStatus = (value: VerifyState) => {
setWizardRegisterStatus(value);
};
const cbGetEditing = (): Domain | undefined => {
return editing;
};
const cbSetEditing = (value: Domain | undefined) => {
setEditing(value);
};
return (
<Provider store={init(...(process.env.NODE_ENV !== 'production' ? [logger] : [])).getStore()}>
<Router basename={getBaseName(window.location.pathname)}>
<AppContext.Provider
value={{
getEditing: cbGetEditing,
setEditing: cbSetEditing,
getDomains: cbGetDomains,
setDomains: cbSetDomains,
wizard: {
getToken: cbGetWizardToken,
setToken: cbSetWizardToken,
getRegisteredStatus: cbGetRegisterStatus,
setRegisteredStatus: cbSetRegisterStatus,
getDomain: cbGetWizardDomain,
setDomain: cbSetWizardDomain,
},
}}
>
<AppContextProvider>
<App />
</AppContext.Provider>
</AppContextProvider>
</Router>
</Provider>
);
Expand Down
10 changes: 5 additions & 5 deletions src/Components/DomainList/DomainList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Fragment, useContext, useState } from 'react';
import React from 'react';

import { Domain, DomainType, ResourcesApiFactory } from '../../Api/api';
import { Link, useNavigate } from 'react-router-dom';
import { AppContext, IAppContext } from '../../AppContext';
import { useNavigate } from 'react-router-dom';
import { AppContext, AppContextType } from '../../AppContext';
import { Button } from '@patternfly/react-core';

export interface IColumnType<T> {
Expand Down Expand Up @@ -95,7 +95,7 @@ export const DomainList = () => {
const base_url = '/api/idmsvc/v1';
const resources_api = ResourcesApiFactory(undefined, base_url, undefined);

const context = useContext<IAppContext>(AppContext);
const context = useContext<AppContextType | undefined>(AppContext);
const navigate = useNavigate();

// Index of the currently sorted column
Expand All @@ -106,7 +106,7 @@ export const DomainList = () => {
// Sort direction of the currently sorted column
const [activeSortDirection, setActiveSortDirection] = React.useState<'asc' | 'desc'>('asc');

const [domains, setDomains] = useState<Domain[]>(context.getDomains());
const [domains, setDomains] = useState<Domain[]>(context?.domains || ([] as Domain[]));
const enabledText = 'Enabled';
const disabledText = 'Disabled';

Expand Down Expand Up @@ -204,7 +204,7 @@ export const DomainList = () => {

const onShowDetails = (domain: Domain | undefined) => {
if (domain !== undefined) {
context.setEditing(domain);
context?.setEditing(domain);
navigate('/details/' + domain?.domain_id);
}
};
Expand Down
44 changes: 24 additions & 20 deletions src/Routes/DefaultPage/DefaultPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import './DefaultPage.scss';
import Section from '@redhat-cloud-services/frontend-components/Section';
import { Domain, ResourcesApiFactory } from '../../Api/api';
import { DomainList } from '../../Components/DomainList/DomainList';
import { AppContext, IAppContext } from '../../AppContext';
import { AppContext, AppContextType } from '../../AppContext';

const Header = () => {
const linkLearnMoreAbout = 'https://access.redhat.com/articles/1586893';
Expand All @@ -55,13 +55,15 @@ const EmptyContent = (props: EmptyContentProps) => {
// FIXME Update this link in the future
const linkLearnMoreAbout = 'https://access.redhat.com/articles/1586893';
const navigate = useNavigate();
const appContext = useContext<IAppContext>(AppContext);
const appContext = useContext<AppContextType | undefined>(AppContext);

const handleOpenWizard = () => {
appContext.wizard.setDomain({ domain_id: '', title: '', description: '' } as Domain);
appContext.wizard.setToken('');
appContext.wizard.setRegisteredStatus('initial');
navigate('/domains/wizard', { replace: true });
if (appContext !== undefined) {
appContext.wizard.setDomain({ domain_id: '', title: '', description: '' } as Domain);
appContext.wizard.setToken('');
appContext.wizard.setRegisteredStatus('initial');
navigate('/domains/wizard', { replace: true });
}
};

return (
Expand Down Expand Up @@ -131,7 +133,7 @@ const ListContent = () => {
.then((res_domain) => {
local_domains[count++] = res_domain.data;
if (res.data.data.length == local_domains.length) {
appContext.setDomains(local_domains);
appContext?.setDomains(local_domains);
const newOffset = Math.floor((offset + perPage - 1) / perPage) * perPage;
const newPage = newOffset / perPage;
setItemCount(res.data.meta.count);
Expand All @@ -154,10 +156,12 @@ const ListContent = () => {
}, [page, perPage, offset]);

const handleOpenWizard = () => {
appContext.wizard.setDomain({ domain_id: '', title: '', description: '' } as Domain);
appContext.wizard.setRegisteredStatus('initial');
appContext.wizard.setToken('');
navigate('/domains/wizard', { replace: true });
if (appContext !== undefined) {
appContext.wizard.setDomain({ domain_id: '', title: '', description: '' } as Domain);
appContext.wizard.setRegisteredStatus('initial');
appContext.wizard.setToken('');
navigate('/domains/wizard', { replace: true });
}
};

const onSetPage = (_event: React.MouseEvent | React.KeyboardEvent | MouseEvent, newPage: number) => {
Expand Down Expand Up @@ -222,7 +226,7 @@ const DefaultPage = () => {

// States
const [page, setPage] = useState<number>(0);
const [itemCount, setItemCount] = useState<number>(appContext.getDomains().length || -1);
const [itemCount, setItemCount] = useState<number>(appContext?.domains.length || -1);
const [perPage] = useState<number>(10);
const [offset, setOffset] = useState<number>(0);

Expand All @@ -240,14 +244,14 @@ const DefaultPage = () => {
.readDomain(item.domain_id)
.then((res_domain) => {
local_domains[count++] = res_domain.data;
// if (res.data.data.length == local_domains.length) {
appContext.setDomains(local_domains);
const newOffset = Math.floor((offset + perPage - 1) / perPage) * perPage;
const newPage = newOffset / perPage;
setItemCount(res.data.meta.count);
setOffset(newOffset);
setPage(newPage);
// }
if (res.data.data.length == local_domains.length) {
appContext?.setDomains(local_domains);
const newOffset = Math.floor((offset + perPage - 1) / perPage) * perPage;
const newPage = newOffset / perPage;
setItemCount(res.data.meta.count);
setOffset(newOffset);
setPage(newPage);
}
console.log('INFO:domain list updated');
})
.catch((reason) => {
Expand Down
21 changes: 17 additions & 4 deletions src/Routes/DetailPage/DetailPage.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { useNavigate, useParams } from 'react-router-dom';
import React, { useContext, useEffect, useState } from 'react';

import { Card, CardBody, Dropdown, DropdownItem, Flex, FlexItem, KebabToggle, Page, PageSection, Tab, TabTitleText, Tabs, setTabIndex } from '@patternfly/react-core';
import {
Card,
CardBody,
Dropdown,
DropdownItem,
Flex,
FlexItem,
KebabToggle,
Page,
PageSection,
Tab,
TabTitleText,
Tabs,
} from '@patternfly/react-core';
import { PageHeader, PageHeaderTitle } from '@redhat-cloud-services/frontend-components/PageHeader';

import './DetailPage.scss';
import { Domain, ResourcesApiFactory } from '../../Api/api';
import { AppContext } from '../../AppContext';
import { AppContext, AppContextType } from '../../AppContext';
import { DetailGeneral } from './Components/DetailGeneral/DetailGeneral';
import { DetailServers } from './Components/DetailServers/DetailServers';

Expand All @@ -21,7 +34,7 @@ interface DetailContentProps extends React.HTMLProps<HTMLDivElement> {
* @see https://reactrouter.com/en/main/hooks/use-params
*/
const DetailPage = () => {
const appContext = useContext(AppContext);
const appContext = useContext<AppContextType | undefined>(AppContext);
const base_url = '/api/idmsvc/v1';
const resources_api = ResourcesApiFactory(undefined, base_url, undefined);
const navigate = useNavigate();
Expand All @@ -31,7 +44,7 @@ const DetailPage = () => {

// States
const [domain, setDomain] = useState<Domain>();
const domains = appContext.getDomains();
const domains = appContext?.domains;

console.log('INFO:DetailPage render:domain_id=' + domain_id);

Expand Down
Loading

0 comments on commit 7c3d4af

Please sign in to comment.