From d1842ad6e2136848b1d2034f202999fa19e695b6 Mon Sep 17 00:00:00 2001 From: Henri Bernard <132286421+hebernardEquisoft@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:52:03 -0500 Subject: [PATCH 1/5] feat(Webapp): implement create user button and user page --- .../src/browser/bootstrap/bootstrap.tsx | 2 +- .../webapp/src/browser/core/config/index.ts | 1 + .../webapp/src/browser/core/config/routes.ts | 23 ++++++++ .../src/browser/core/i18n/translations.ts | 16 ++++- .../browser/core/navigation/route.types.ts | 4 +- .../src/browser/modules/app/App.component.tsx | 59 ++++--------------- .../modules/app/Providers.component.tsx | 43 ++++++++++++++ .../browser/modules/app/Router.component.tsx | 57 ++++++++++++++++++ .../webapp/src/browser/modules/app/index.ts | 2 +- .../app/layout/AppLayout.component.tsx | 2 +- .../app/layout/ErrorBoundary.component.tsx | 39 ++++++++++++ .../modules/app/layout/Menu.component.tsx | 2 +- .../UnexpectedErrorBoundary.component.tsx | 16 ----- .../src/browser/modules/app/layout/index.ts | 2 +- .../webapp/src/browser/modules/app/routes.ts | 31 ---------- .../browser/modules/users/User.component.tsx | 48 ++++++++++++++- .../users/components/form/Form.component.tsx | 14 +++++ .../components/table/Table.component.tsx | 4 +- .../table/toolbar/CreateUser.component.tsx | 18 ++++++ .../table/toolbar/Toolbar.component.tsx | 18 ++++++ .../src/browser/modules/users/types/index.ts | 1 + .../browser/modules/users/types/user-mode.ts | 5 ++ 22 files changed, 299 insertions(+), 108 deletions(-) create mode 100644 packages/webapp/src/browser/core/config/routes.ts create mode 100644 packages/webapp/src/browser/modules/app/Providers.component.tsx create mode 100644 packages/webapp/src/browser/modules/app/Router.component.tsx create mode 100644 packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx delete mode 100644 packages/webapp/src/browser/modules/app/layout/UnexpectedErrorBoundary.component.tsx delete mode 100644 packages/webapp/src/browser/modules/app/routes.ts create mode 100644 packages/webapp/src/browser/modules/users/components/form/Form.component.tsx create mode 100644 packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx create mode 100644 packages/webapp/src/browser/modules/users/components/table/toolbar/Toolbar.component.tsx create mode 100644 packages/webapp/src/browser/modules/users/types/user-mode.ts diff --git a/packages/webapp/src/browser/bootstrap/bootstrap.tsx b/packages/webapp/src/browser/bootstrap/bootstrap.tsx index f1444829c8..3342e7521c 100644 --- a/packages/webapp/src/browser/bootstrap/bootstrap.tsx +++ b/packages/webapp/src/browser/bootstrap/bootstrap.tsx @@ -10,6 +10,6 @@ export async function bootstrap(document: NonElementParentNode): Promise { if (rootElement) { const root = createRoot(rootElement); - root.render(); + root.render(); } } diff --git a/packages/webapp/src/browser/core/config/index.ts b/packages/webapp/src/browser/core/config/index.ts index b41f1e1f59..a240c43e9e 100644 --- a/packages/webapp/src/browser/core/config/index.ts +++ b/packages/webapp/src/browser/core/config/index.ts @@ -1,3 +1,4 @@ export * from './configuration'; export * from './configuration.factory'; export * from './configuration.hook'; +export * from './routes'; diff --git a/packages/webapp/src/browser/core/config/routes.ts b/packages/webapp/src/browser/core/config/routes.ts new file mode 100644 index 0000000000..44dca700ee --- /dev/null +++ b/packages/webapp/src/browser/core/config/routes.ts @@ -0,0 +1,23 @@ +import { RouteCollection } from '../navigation'; + +export const ROUTES: RouteCollection = { + root: { + path: '/', + getHref: () => '/', + }, + home: { + path: '/home', + getHref: () => '/home', + end: true, + }, + users: { + path: '/users', + getHref: () => '/users', + end: true, + }, + user: { + path: '/users/:mode/:id?', + getHref: (mode: string, id?: string) => `/users/${mode}${id ? `/${id}` : ''}`, + end: true, + }, +}; diff --git a/packages/webapp/src/browser/core/i18n/translations.ts b/packages/webapp/src/browser/core/i18n/translations.ts index 05ed366969..6c0d757fbb 100644 --- a/packages/webapp/src/browser/core/i18n/translations.ts +++ b/packages/webapp/src/browser/core/i18n/translations.ts @@ -2,6 +2,8 @@ export const translations = { en: { core: { helloWorld: 'Hello World!', + notFoundTitle: 'Page not found', + notFoundMessage: 'The page you are looking for does not exist.', }, nav: { changeLanguageTo: 'Change language to {{nextLanguage}} ({{lng}})', @@ -19,14 +21,20 @@ export const translations = { deleteUser: 'Delete {{user}}', deleteUserMessage: 'Are you sure you want to delete this user?', deleteUserSuccess: 'User {{user}} has been deleted!', + create: 'Create user...', }, user: { - viewTitle: 'User information', + readTitle: 'User information', + editTitle: 'Edit user', + createTitle: 'Create user', + requiredFields: 'Required fields are marked with an asterisk', }, }, fr: { core: { helloWorld: 'Bonjour le monde!', + notFoundTitle: 'Page non trouvée', + notFoundMessage: 'La page que vous cherchez n\'existe pas.', }, nav: { changeLanguageTo: 'Changer la langue pour {{nextLanguage}} ({{lng}})', @@ -44,9 +52,13 @@ export const translations = { deleteUser: 'Supprimer {{user}}', deleteUserMessage: 'Êtes-vous sûr de vouloir supprimer cet utilisateur?', deleteUserSuccess: 'L\'utilisateur {{user}} a été supprimé!', + create: 'Créer un utilisateur...', }, user: { - viewTitle: 'Information sur l\'utilisateur', + readTitle: 'Information sur l\'utilisateur', + editTitle: 'Modifier l\'utilisateur', + createTitle: 'Créer un utilisateur', + requiredFields: 'Les champs obligatoires sont marqués d\'un astérisque', }, }, }; diff --git a/packages/webapp/src/browser/core/navigation/route.types.ts b/packages/webapp/src/browser/core/navigation/route.types.ts index ce485516d4..79ff346f7c 100644 --- a/packages/webapp/src/browser/core/navigation/route.types.ts +++ b/packages/webapp/src/browser/core/navigation/route.types.ts @@ -1,8 +1,6 @@ -import { FunctionComponent } from 'react'; - export interface RouteDefinition { path: string; - component: FunctionComponent; + getHref: (...args: any[]) => string; end?: boolean; } diff --git a/packages/webapp/src/browser/modules/app/App.component.tsx b/packages/webapp/src/browser/modules/app/App.component.tsx index 5ef79fb130..a2d2d52ac5 100644 --- a/packages/webapp/src/browser/modules/app/App.component.tsx +++ b/packages/webapp/src/browser/modules/app/App.component.tsx @@ -1,51 +1,12 @@ -import { DesignSystem } from '@equisoft/design-elements-react'; import { FunctionComponent } from 'react'; -import { useTranslation } from 'react-i18next'; -import { RouterProvider } from 'react-router-dom'; -import { Configuration, ConfigurationProvider, createRouter, initializeConfiguration } from '../../core'; -import { Provider as UsersProvider } from '../users/components/Provider.component'; -import { AppLayout, AppLoader, UnexpectedErrorBoundary } from './layout'; -import { ROUTER_ROUTES } from './routes'; - -export interface AppProps { - configuration: Configuration; -} - -const appConfig = initializeConfiguration(); -const router = createRouter([ - { - path: '/', - element: , - children: ROUTER_ROUTES, - }, -], { - basename: appConfig.publicPath, -}); - -export const DataProviders: FunctionComponent = ( - { children }, -) => ( - - {children} - +import { AppLoader } from './layout'; +import { AppProviders } from './Providers.component'; +import { AppRouter } from './Router.component'; + +export const App: FunctionComponent = () => ( + + + + + ); - -export const App: FunctionComponent = ({ - configuration, -}) => { - const { i18n } = useTranslation(); - - return ( - - - - - - - - - - - - ); -}; diff --git a/packages/webapp/src/browser/modules/app/Providers.component.tsx b/packages/webapp/src/browser/modules/app/Providers.component.tsx new file mode 100644 index 0000000000..0ae5fa2e5d --- /dev/null +++ b/packages/webapp/src/browser/modules/app/Providers.component.tsx @@ -0,0 +1,43 @@ +import { DesignSystem } from '@equisoft/design-elements-react'; +import { FunctionComponent } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ConfigurationProvider, initializeConfiguration } from '../../core'; +import { Provider as UsersProvider } from '../users/components/Provider.component'; +import { UnexpectedErrorBoundary } from './layout'; + +const ServerProviders: FunctionComponent = ( + { children }, +) => { + const appConfig = initializeConfiguration(); + return ( + + + + {children} + + + + ); +}; + +const ClientProviders: FunctionComponent = ( + { children }, +) => { + const { i18n } = useTranslation(); + + return ( + + {children} + + ); +}; + +export const AppProviders: FunctionComponent = ( + { children }, +) => ( + + + {children} + + +); diff --git a/packages/webapp/src/browser/modules/app/Router.component.tsx b/packages/webapp/src/browser/modules/app/Router.component.tsx new file mode 100644 index 0000000000..616ee00684 --- /dev/null +++ b/packages/webapp/src/browser/modules/app/Router.component.tsx @@ -0,0 +1,57 @@ +import { FunctionComponent } from 'react'; +import { RouterProvider, createBrowserRouter } from 'react-router-dom'; +import { ROUTES, useConfiguration } from '../../core'; +import { UnexpectedError, NotFoundRoute, AppLayout } from './layout'; + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export const createAppRouter = (publicPath: string) => createBrowserRouter([ + { + path: ROUTES.root.path, + element: , + ErrorBoundary: UnexpectedError, + children: [ + { + path: ROUTES.home.path, + lazy: async () => { + const { HomePage } = await import('../home'); + return { Component: HomePage }; + }, + ErrorBoundary: UnexpectedError, + }, + { + path: ROUTES.users.path, + lazy: async () => { + const { UsersPage } = await import('../users'); + return { Component: UsersPage }; + }, + ErrorBoundary: UnexpectedError, + }, + { + path: ROUTES.user.path, + lazy: async () => { + const { UserPage } = await import('../users'); + return { Component: UserPage }; + }, + ErrorBoundary: UnexpectedError, + }, + ], + }, + { + path: '*', + lazy: async () => ({ + Component: NotFoundRoute, + }), + ErrorBoundary: UnexpectedError, + }, +], { + basename: publicPath, +}); + +export const AppRouter: FunctionComponent = () => { + const { configuration } = useConfiguration(); + const router = createAppRouter(configuration.publicPath); + + return ( + + ); +}; diff --git a/packages/webapp/src/browser/modules/app/index.ts b/packages/webapp/src/browser/modules/app/index.ts index f8e3c97091..1b6c8de891 100644 --- a/packages/webapp/src/browser/modules/app/index.ts +++ b/packages/webapp/src/browser/modules/app/index.ts @@ -1 +1 @@ -export { App, AppProps } from './App.component'; +export { App } from './App.component'; diff --git a/packages/webapp/src/browser/modules/app/layout/AppLayout.component.tsx b/packages/webapp/src/browser/modules/app/layout/AppLayout.component.tsx index 13855a5e3e..1d90452d94 100644 --- a/packages/webapp/src/browser/modules/app/layout/AppLayout.component.tsx +++ b/packages/webapp/src/browser/modules/app/layout/AppLayout.component.tsx @@ -4,7 +4,7 @@ import { Outlet } from 'react-router'; import styled from 'styled-components'; import { Header } from './Header.component'; import { Menu } from './Menu.component'; -import { UnexpectedErrorBoundary } from './UnexpectedErrorBoundary.component'; +import { UnexpectedErrorBoundary } from './ErrorBoundary.component'; const Screen = styled.div` display: grid; diff --git a/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx b/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx new file mode 100644 index 0000000000..bb1bf7e3c1 --- /dev/null +++ b/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx @@ -0,0 +1,39 @@ +import { Link } from '@equisoft/design-elements-react'; +import { FC, FunctionComponent, PropsWithChildren } from 'react'; +import { useTranslation } from 'react-i18next'; +import styled from 'styled-components'; +import { ErrorBoundary, ROUTES } from '../../../core'; +import { ScreenCentered } from './styled-elements'; + +const NotFoundContainer = styled.div` + margin-top: 13rem; /* mt-52 */ + display: flex; + flex-direction: column; + align-items: center; + font-weight: 600; /* font-semibold */ +`; + +export const NotFoundRoute: FC = () => { + const { t } = useTranslation('core'); + return ( + +

{t('notFoundTitle')}

+

{t('notFoundMessage')}

+ + {t('backToHome')} + +
+ ); +}; + +export const UnexpectedError: FunctionComponent = () => { + const { t } = useTranslation(); + + return ({t('unexpectedError')}); +}; + +export const UnexpectedErrorBoundary: FunctionComponent> = ({ children }) => ( + }> + {children} + +); diff --git a/packages/webapp/src/browser/modules/app/layout/Menu.component.tsx b/packages/webapp/src/browser/modules/app/layout/Menu.component.tsx index 5242316aa3..9f143ce0dd 100644 --- a/packages/webapp/src/browser/modules/app/layout/Menu.component.tsx +++ b/packages/webapp/src/browser/modules/app/layout/Menu.component.tsx @@ -1,7 +1,7 @@ import { GlobalNavigation } from '@equisoft/design-elements-react'; import { FunctionComponent } from 'react'; import { useTranslation } from 'react-i18next'; -import { ROUTES } from '../routes'; +import { ROUTES } from '../../../core'; export const Menu: FunctionComponent = () => { const { t } = useTranslation(); diff --git a/packages/webapp/src/browser/modules/app/layout/UnexpectedErrorBoundary.component.tsx b/packages/webapp/src/browser/modules/app/layout/UnexpectedErrorBoundary.component.tsx deleted file mode 100644 index 099f84732a..0000000000 --- a/packages/webapp/src/browser/modules/app/layout/UnexpectedErrorBoundary.component.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { FunctionComponent, PropsWithChildren } from 'react'; -import { useTranslation } from 'react-i18next'; -import { ErrorBoundary } from '../../../core'; -import { ScreenCentered } from './styled-elements'; - -const UnexpectedError: FunctionComponent = () => { - const { t } = useTranslation(); - - return ({t('unexpectedError')}); -}; - -export const UnexpectedErrorBoundary: FunctionComponent> = ({ children }) => ( - }> - {children} - -); diff --git a/packages/webapp/src/browser/modules/app/layout/index.ts b/packages/webapp/src/browser/modules/app/layout/index.ts index f079bd85ba..e6c931c74f 100644 --- a/packages/webapp/src/browser/modules/app/layout/index.ts +++ b/packages/webapp/src/browser/modules/app/layout/index.ts @@ -1,3 +1,3 @@ export { AppLayout } from './AppLayout.component'; export { AppLoader } from './AppLoader.component'; -export { UnexpectedErrorBoundary } from './UnexpectedErrorBoundary.component'; +export { UnexpectedErrorBoundary, UnexpectedError, NotFoundRoute } from './ErrorBoundary.component'; diff --git a/packages/webapp/src/browser/modules/app/routes.ts b/packages/webapp/src/browser/modules/app/routes.ts deleted file mode 100644 index a1d6e03059..0000000000 --- a/packages/webapp/src/browser/modules/app/routes.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { RouteObject } from 'react-router'; -import { RouteCollection, RouteDefinition } from '../../core'; -import { HomePage } from '../home'; -import { UserPage, UsersPage } from '../users'; - -export const ROUTES: RouteCollection = { - home: { - path: '/', - component: HomePage, - end: true, - }, - users: { - path: '/users', - component: UsersPage, - end: true, - }, - user: { - path: '/user/:id?', - component: UserPage, - end: true, - }, -}; - -export const ROUTER_ROUTES: RouteObject[] = Object.keys(ROUTES).map((key: string): RouteObject => { - const route: Readonly = ROUTES[key]; - return { - id: key, - path: route.path, - Component: route.component, - }; -}); diff --git a/packages/webapp/src/browser/modules/users/User.component.tsx b/packages/webapp/src/browser/modules/users/User.component.tsx index df4a34a9dd..a5860e63c4 100644 --- a/packages/webapp/src/browser/modules/users/User.component.tsx +++ b/packages/webapp/src/browser/modules/users/User.component.tsx @@ -1,11 +1,57 @@ import { Heading } from '@equisoft/design-elements-react'; import { FunctionComponent } from 'react'; import { useTranslation } from 'react-i18next'; +import { useParams } from 'react-router'; +import styled from 'styled-components'; +import { Form as UserForm } from './components/form/Form.component'; +import { UserMode } from './types'; + +const PageWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 16px; +`; + +const StyledWarning = styled.span` + display: flex; + flex-direction: row; + gap: 4px; + color: ${({ theme }) => theme.alias['color-content']}; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: 0.2px; +`; + +const StyledAsterisk = styled.span` + color: ${({ theme }) => theme.alias['color-feedback-border-alert']}; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: 0.2px; +`; export const UserPage: FunctionComponent = () => { const { t } = useTranslation('user'); + const { mode, id } = useParams(); + const userMode = mode as UserMode || UserMode.CREATE; + const titleMap = { + [UserMode.CREATE]: t('createTitle'), + [UserMode.EDIT]: t('editTitle'), + [UserMode.READ]: t('readTitle'), + }; + const title = titleMap[userMode]; return ( - {t('viewTitle')} + + {title} + + {t('requiredFields')} + * + + + ); }; diff --git a/packages/webapp/src/browser/modules/users/components/form/Form.component.tsx b/packages/webapp/src/browser/modules/users/components/form/Form.component.tsx new file mode 100644 index 0000000000..a930a7bdf8 --- /dev/null +++ b/packages/webapp/src/browser/modules/users/components/form/Form.component.tsx @@ -0,0 +1,14 @@ +import { FunctionComponent } from 'react'; + +interface UserFormProps { + id?: string; +} + +export const Form: FunctionComponent = ( + { id }, +) => { + console.log(id); + return ( +
+ ); +}; diff --git a/packages/webapp/src/browser/modules/users/components/table/Table.component.tsx b/packages/webapp/src/browser/modules/users/components/table/Table.component.tsx index 29d829e0ef..de41f58f60 100644 --- a/packages/webapp/src/browser/modules/users/components/table/Table.component.tsx +++ b/packages/webapp/src/browser/modules/users/components/table/Table.component.tsx @@ -12,6 +12,7 @@ import { Delete as DeleteCell, } from './cells'; import { Footer as TableFooter } from './Footer.component'; +import { ToolBar } from './toolbar/Toolbar.component'; const TableContainer = styled.div` align-items: flex-start; @@ -25,7 +26,7 @@ const TableContainer = styled.div` flex-shrink: 0; gap: 8px; padding: 16px 32px; - + td:nth-child(4) { padding-left: 0; padding-right: 0; @@ -91,6 +92,7 @@ export const Table: FunctionComponent = () => { return ( + { + const { t } = useTranslation('users'); + return ( + + + {t('create')} + + ); +}; diff --git a/packages/webapp/src/browser/modules/users/components/table/toolbar/Toolbar.component.tsx b/packages/webapp/src/browser/modules/users/components/table/toolbar/Toolbar.component.tsx new file mode 100644 index 0000000000..9edd06ff7e --- /dev/null +++ b/packages/webapp/src/browser/modules/users/components/table/toolbar/Toolbar.component.tsx @@ -0,0 +1,18 @@ +import { FunctionComponent } from 'react'; +import styled from 'styled-components'; +import { CreateUser } from './CreateUser.component'; + +const ToolBarContainer = styled.div` + align-items: center; + align-self: stretch; + border-radius: 8px; + display: flex; + justify-content: flex-end; + padding: 8px 8px; +`; + +export const ToolBar: FunctionComponent = () => ( + + + +); diff --git a/packages/webapp/src/browser/modules/users/types/index.ts b/packages/webapp/src/browser/modules/users/types/index.ts index 3f95ebdfac..6596ee03df 100644 --- a/packages/webapp/src/browser/modules/users/types/index.ts +++ b/packages/webapp/src/browser/modules/users/types/index.ts @@ -3,3 +3,4 @@ export { UsersContextProps, TableContextProps, TableContextKeys, } from './users-context'; export { UsersActionProps, UsersAction } from './users-action'; +export * from './user-mode'; diff --git a/packages/webapp/src/browser/modules/users/types/user-mode.ts b/packages/webapp/src/browser/modules/users/types/user-mode.ts new file mode 100644 index 0000000000..a6b88b375d --- /dev/null +++ b/packages/webapp/src/browser/modules/users/types/user-mode.ts @@ -0,0 +1,5 @@ +export enum UserMode { + EDIT = 'edit', + READ = 'read', + CREATE = 'create', +} From 63345d1c79b3c5d21e50ce956644aa4d51374826 Mon Sep 17 00:00:00 2001 From: Henri Bernard <132286421+hebernardEquisoft@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:00:47 -0500 Subject: [PATCH 2/5] fix(Webapp): stylelint --- .../modules/app/layout/ErrorBoundary.component.tsx | 4 ++-- .../webapp/src/browser/modules/users/User.component.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx b/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx index bb1bf7e3c1..2c44f0f7bf 100644 --- a/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx +++ b/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx @@ -6,11 +6,11 @@ import { ErrorBoundary, ROUTES } from '../../../core'; import { ScreenCentered } from './styled-elements'; const NotFoundContainer = styled.div` - margin-top: 13rem; /* mt-52 */ + align-items: center; display: flex; flex-direction: column; - align-items: center; font-weight: 600; /* font-semibold */ + margin-top: 13rem; /* mt-52 */ `; export const NotFoundRoute: FC = () => { diff --git a/packages/webapp/src/browser/modules/users/User.component.tsx b/packages/webapp/src/browser/modules/users/User.component.tsx index a5860e63c4..55476da18e 100644 --- a/packages/webapp/src/browser/modules/users/User.component.tsx +++ b/packages/webapp/src/browser/modules/users/User.component.tsx @@ -13,15 +13,15 @@ const PageWrapper = styled.div` `; const StyledWarning = styled.span` + color: ${({ theme }) => theme.alias['color-content']}; display: flex; flex-direction: row; - gap: 4px; - color: ${({ theme }) => theme.alias['color-content']}; font-size: 12px; font-style: normal; font-weight: 400; - line-height: 20px; + gap: 4px; letter-spacing: 0.2px; + line-height: 20px; `; const StyledAsterisk = styled.span` @@ -29,8 +29,8 @@ const StyledAsterisk = styled.span` font-size: 12px; font-style: normal; font-weight: 400; - line-height: 20px; letter-spacing: 0.2px; + line-height: 20px; `; export const UserPage: FunctionComponent = () => { From d43dbc55bfc43dd20a6b79caec6ff9dc5f2c2d6c Mon Sep 17 00:00:00 2001 From: Henri Bernard <132286421+hebernardEquisoft@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:02:11 -0500 Subject: [PATCH 3/5] fix(Webapp): eslint --- packages/webapp/src/browser/core/navigation/route.types.ts | 2 +- .../browser/modules/users/components/form/Form.component.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/webapp/src/browser/core/navigation/route.types.ts b/packages/webapp/src/browser/core/navigation/route.types.ts index 79ff346f7c..5c8649986f 100644 --- a/packages/webapp/src/browser/core/navigation/route.types.ts +++ b/packages/webapp/src/browser/core/navigation/route.types.ts @@ -1,6 +1,6 @@ export interface RouteDefinition { path: string; - getHref: (...args: any[]) => string; + getHref: (...args: string[]) => string; end?: boolean; } diff --git a/packages/webapp/src/browser/modules/users/components/form/Form.component.tsx b/packages/webapp/src/browser/modules/users/components/form/Form.component.tsx index a930a7bdf8..bb49affdd9 100644 --- a/packages/webapp/src/browser/modules/users/components/form/Form.component.tsx +++ b/packages/webapp/src/browser/modules/users/components/form/Form.component.tsx @@ -7,6 +7,7 @@ interface UserFormProps { export const Form: FunctionComponent = ( { id }, ) => { + // eslint-disable-next-line no-console console.log(id); return ( From afad5c1cc14fd8edd6fb99733406601f37b127b9 Mon Sep 17 00:00:00 2001 From: Henri Bernard <132286421+hebernardEquisoft@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:52:11 -0500 Subject: [PATCH 4/5] fix(Webapp): post review changes --- .../webapp/src/browser/core/config/index.ts | 1 - .../webapp/src/browser/core/config/routes.ts | 23 ------- .../browser/core/navigation/route.types.ts | 4 +- .../src/browser/core/navigation/routes.ts | 31 ++++++++++ .../modules/app/Providers.component.tsx | 30 ++------- .../browser/modules/app/Router.component.tsx | 62 +++++-------------- .../app/layout/ErrorBoundary.component.tsx | 3 +- .../modules/app/layout/Menu.component.tsx | 2 +- .../components/table/Table.component.tsx | 4 +- .../components/table/cells/Name.component.tsx | 27 ++++---- .../table/toolbar/CreateUser.component.tsx | 3 +- 11 files changed, 72 insertions(+), 118 deletions(-) delete mode 100644 packages/webapp/src/browser/core/config/routes.ts create mode 100644 packages/webapp/src/browser/core/navigation/routes.ts diff --git a/packages/webapp/src/browser/core/config/index.ts b/packages/webapp/src/browser/core/config/index.ts index a240c43e9e..b41f1e1f59 100644 --- a/packages/webapp/src/browser/core/config/index.ts +++ b/packages/webapp/src/browser/core/config/index.ts @@ -1,4 +1,3 @@ export * from './configuration'; export * from './configuration.factory'; export * from './configuration.hook'; -export * from './routes'; diff --git a/packages/webapp/src/browser/core/config/routes.ts b/packages/webapp/src/browser/core/config/routes.ts deleted file mode 100644 index 44dca700ee..0000000000 --- a/packages/webapp/src/browser/core/config/routes.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { RouteCollection } from '../navigation'; - -export const ROUTES: RouteCollection = { - root: { - path: '/', - getHref: () => '/', - }, - home: { - path: '/home', - getHref: () => '/home', - end: true, - }, - users: { - path: '/users', - getHref: () => '/users', - end: true, - }, - user: { - path: '/users/:mode/:id?', - getHref: (mode: string, id?: string) => `/users/${mode}${id ? `/${id}` : ''}`, - end: true, - }, -}; diff --git a/packages/webapp/src/browser/core/navigation/route.types.ts b/packages/webapp/src/browser/core/navigation/route.types.ts index 5c8649986f..ce485516d4 100644 --- a/packages/webapp/src/browser/core/navigation/route.types.ts +++ b/packages/webapp/src/browser/core/navigation/route.types.ts @@ -1,6 +1,8 @@ +import { FunctionComponent } from 'react'; + export interface RouteDefinition { path: string; - getHref: (...args: string[]) => string; + component: FunctionComponent; end?: boolean; } diff --git a/packages/webapp/src/browser/core/navigation/routes.ts b/packages/webapp/src/browser/core/navigation/routes.ts new file mode 100644 index 0000000000..3448de7ac6 --- /dev/null +++ b/packages/webapp/src/browser/core/navigation/routes.ts @@ -0,0 +1,31 @@ +import { RouteObject } from 'react-router'; +import { HomePage } from '../../modules/home'; +import { UserPage, UsersPage } from '../../modules/users'; +import { RouteCollection, RouteDefinition } from './route.types'; + +export const ROUTES: RouteCollection = { + home: { + path: '/', + component: HomePage, + end: true, + }, + users: { + path: '/users', + component: UsersPage, + end: true, + }, + user: { + path: '/users/:mode?/:id?', + component: UserPage, + end: true, + }, +}; + +export const ROUTER_ROUTES: RouteObject[] = Object.keys(ROUTES).map((key: string): RouteObject => { + const route: Readonly = ROUTES[key]; + return { + id: key, + path: route.path, + Component: route.component, + }; +}); diff --git a/packages/webapp/src/browser/modules/app/Providers.component.tsx b/packages/webapp/src/browser/modules/app/Providers.component.tsx index 0ae5fa2e5d..f411feffab 100644 --- a/packages/webapp/src/browser/modules/app/Providers.component.tsx +++ b/packages/webapp/src/browser/modules/app/Providers.component.tsx @@ -5,39 +5,21 @@ import { ConfigurationProvider, initializeConfiguration } from '../../core'; import { Provider as UsersProvider } from '../users/components/Provider.component'; import { UnexpectedErrorBoundary } from './layout'; -const ServerProviders: FunctionComponent = ( +export const AppProviders: FunctionComponent = ( { children }, ) => { const appConfig = initializeConfiguration(); + const { i18n } = useTranslation(); + return ( - {children} + + {children} + ); }; - -const ClientProviders: FunctionComponent = ( - { children }, -) => { - const { i18n } = useTranslation(); - - return ( - - {children} - - ); -}; - -export const AppProviders: FunctionComponent = ( - { children }, -) => ( - - - {children} - - -); diff --git a/packages/webapp/src/browser/modules/app/Router.component.tsx b/packages/webapp/src/browser/modules/app/Router.component.tsx index 616ee00684..aeff292fc6 100644 --- a/packages/webapp/src/browser/modules/app/Router.component.tsx +++ b/packages/webapp/src/browser/modules/app/Router.component.tsx @@ -1,55 +1,21 @@ import { FunctionComponent } from 'react'; -import { RouterProvider, createBrowserRouter } from 'react-router-dom'; -import { ROUTES, useConfiguration } from '../../core'; -import { UnexpectedError, NotFoundRoute, AppLayout } from './layout'; - -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -export const createAppRouter = (publicPath: string) => createBrowserRouter([ - { - path: ROUTES.root.path, - element: , - ErrorBoundary: UnexpectedError, - children: [ - { - path: ROUTES.home.path, - lazy: async () => { - const { HomePage } = await import('../home'); - return { Component: HomePage }; - }, - ErrorBoundary: UnexpectedError, - }, - { - path: ROUTES.users.path, - lazy: async () => { - const { UsersPage } = await import('../users'); - return { Component: UsersPage }; - }, - ErrorBoundary: UnexpectedError, - }, - { - path: ROUTES.user.path, - lazy: async () => { - const { UserPage } = await import('../users'); - return { Component: UserPage }; - }, - ErrorBoundary: UnexpectedError, - }, - ], - }, - { - path: '*', - lazy: async () => ({ - Component: NotFoundRoute, - }), - ErrorBoundary: UnexpectedError, - }, -], { - basename: publicPath, -}); +import { RouterProvider } from 'react-router-dom'; +import { createRouter, useConfiguration } from '../../core'; +import { ROUTER_ROUTES } from '../../core/navigation/routes'; +import { AppLayout } from './layout'; export const AppRouter: FunctionComponent = () => { const { configuration } = useConfiguration(); - const router = createAppRouter(configuration.publicPath); + + const router = createRouter([ + { + path: '/', + element: , + children: ROUTER_ROUTES, + }, + ], { + basename: configuration.publicPath, + }); return ( diff --git a/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx b/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx index 2c44f0f7bf..be55c95db4 100644 --- a/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx +++ b/packages/webapp/src/browser/modules/app/layout/ErrorBoundary.component.tsx @@ -2,7 +2,8 @@ import { Link } from '@equisoft/design-elements-react'; import { FC, FunctionComponent, PropsWithChildren } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; -import { ErrorBoundary, ROUTES } from '../../../core'; +import { ErrorBoundary } from '../../../core'; +import { ROUTES } from '../../../core/navigation/routes'; import { ScreenCentered } from './styled-elements'; const NotFoundContainer = styled.div` diff --git a/packages/webapp/src/browser/modules/app/layout/Menu.component.tsx b/packages/webapp/src/browser/modules/app/layout/Menu.component.tsx index 9f143ce0dd..87d00b68d8 100644 --- a/packages/webapp/src/browser/modules/app/layout/Menu.component.tsx +++ b/packages/webapp/src/browser/modules/app/layout/Menu.component.tsx @@ -1,7 +1,7 @@ import { GlobalNavigation } from '@equisoft/design-elements-react'; import { FunctionComponent } from 'react'; import { useTranslation } from 'react-i18next'; -import { ROUTES } from '../../../core'; +import { ROUTES } from '../../../core/navigation/routes'; export const Menu: FunctionComponent = () => { const { t } = useTranslation(); diff --git a/packages/webapp/src/browser/modules/users/components/table/Table.component.tsx b/packages/webapp/src/browser/modules/users/components/table/Table.component.tsx index de41f58f60..889d23e92c 100644 --- a/packages/webapp/src/browser/modules/users/components/table/Table.component.tsx +++ b/packages/webapp/src/browser/modules/users/components/table/Table.component.tsx @@ -59,7 +59,7 @@ export const Table: FunctionComponent = () => { focusable: true, // eslint-disable-next-line react/no-unstable-nested-components cell: (props) => ( - + ), }, { @@ -85,7 +85,7 @@ export const Table: FunctionComponent = () => { sortable: false, // eslint-disable-next-line react/no-unstable-nested-components cell: (props) => ( - + ), }, ], [t]); diff --git a/packages/webapp/src/browser/modules/users/components/table/cells/Name.component.tsx b/packages/webapp/src/browser/modules/users/components/table/cells/Name.component.tsx index 2a9de99007..fee7a05634 100644 --- a/packages/webapp/src/browser/modules/users/components/table/cells/Name.component.tsx +++ b/packages/webapp/src/browser/modules/users/components/table/cells/Name.component.tsx @@ -1,23 +1,20 @@ -import { RouteLink } from '@equisoft/design-elements-react'; +import { Link } from '@equisoft/design-elements-react'; import { FunctionComponent } from 'react'; import { NavLink } from 'react-router-dom'; -import { useUserContext } from '../../../state'; -import { User } from '../../../types'; +import { User, UserMode } from '../../../types'; interface NameCellProps { id: User['id']; + name: User['name']; } export const Name: FunctionComponent = ( - { id }, -) => { - const user = useUserContext(id); - - return ( - - ); -}; + { id, name }, +) => ( + + {name} + +); diff --git a/packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx b/packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx index 3d6dd95093..db3fab6a1e 100644 --- a/packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx +++ b/packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx @@ -1,7 +1,6 @@ import { Icon, Link } from '@equisoft/design-elements-react'; import { FunctionComponent } from 'react'; import { useTranslation } from 'react-i18next'; -import { ROUTES } from '../../../../../core'; import { UserMode } from '../../../types'; export const CreateUser: FunctionComponent = () => { @@ -9,7 +8,7 @@ export const CreateUser: FunctionComponent = () => { return ( {t('create')} From 952dc4fb096f381ecd4b9ee2df4fbb7d29bccfdc Mon Sep 17 00:00:00 2001 From: Henri Bernard <132286421+hebernardEquisoft@users.noreply.github.com> Date: Wed, 20 Nov 2024 10:29:02 -0500 Subject: [PATCH 5/5] fix(Webapp): post review changes --- .../users/components/table/toolbar/CreateUser.component.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx b/packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx index db3fab6a1e..9db0825d75 100644 --- a/packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx +++ b/packages/webapp/src/browser/modules/users/components/table/toolbar/CreateUser.component.tsx @@ -1,6 +1,7 @@ import { Icon, Link } from '@equisoft/design-elements-react'; import { FunctionComponent } from 'react'; import { useTranslation } from 'react-i18next'; +import { NavLink } from 'react-router-dom'; import { UserMode } from '../../../types'; export const CreateUser: FunctionComponent = () => { @@ -9,6 +10,7 @@ export const CreateUser: FunctionComponent = () => { {t('create')}