Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JNG-5386 add view data context and hooks #282

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/pages/01_ui_react.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,22 @@ export function SomeAction() {
> Certain routes may require a `signedIdentifier` param, but that's okay because if we miss it out, we get IDE errors,
and compiler errors as well.

== Hooks

=== useViewData

The `useViewData()` hook can be used to obtain the latest view page/dialog's latest data.

*Available methods:*

- getLatestViewData(): Returns the data for the last loaded View page/dialog.
- setLatestViewData(): Used internally only to update the data. Should not be used in application code.

[WARN]
====
If for whatever reason the data's owning View fails it's refresh request, the `getLatestViewData()` method return `null`
====

== Opt-in features

=== Generate pro+ MUI code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { {{# unless page.container.table }}useCallback, useEffect, useRef, {{/ u
{{/ if }}
import { useJudoNavigation } from '~/components';
import { useConfirmDialog, useDialog, useFilterDialog } from '~/components/dialog';
import { useSnacks, useCRUDDialog } from '~/hooks';
import { useSnacks, useCRUDDialog, useViewData } from '~/hooks';
import {
{{# if (hasPageRequiredBy page) }}passesLocalValidation,{{/ if }}
processQueryCustomizer,
Expand Down Expand Up @@ -158,6 +158,7 @@ export default function {{ pageName page }}(props: {{ pageName page }}Props) {
const { navigate, back: navigateBack } = useJudoNavigation();
const { openFilterDialog } = useFilterDialog();
const { openConfirmDialog } = useConfirmDialog();
const { setLatestViewData } = useViewData();
const handleError = useErrorHandler();
const openCRUDDialog = useCRUDDialog();
const [createDialog, closeDialog] = useDialog();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { FC, ReactNode } from 'react';
import { createContext, useContext, useState } from 'react';
import type { JudoIdentifiable } from '~/services/data-api/common';

interface DataContextProps {
children: ReactNode;
}

interface ViewContextContextValue {
setLatestViewData: (newData: JudoIdentifiable<any> | null) => void;
getLatestViewData: () => JudoIdentifiable<any> | null;
}

const ViewDataContext = createContext<ViewContextContextValue | undefined>(undefined);

export const ViewDataProvider: FC<DataContextProps> = ({ children }) => {
const [data, setData] = useState<JudoIdentifiable<any> | null>(null);

const useData = (): ViewContextContextValue => {
const setLatestViewData = (newData: JudoIdentifiable<any> | null): void => {
setData(newData);
};
const getLatestViewData = (): JudoIdentifiable<any> | null => data;
return { setLatestViewData, getLatestViewData };
};

return <ViewDataContext.Provider value={useData()}>{children}</ViewDataContext.Provider>;
};

export const useViewData = (): ViewContextContextValue => {
const context = useContext(ViewDataContext);

if (!context) {
throw new Error('useViewData must be used within a ViewDataProvider');
}

return context;
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './useLocalStorage';
export * from './useLogoProps';
export * from './useNavigationConfirmation';
export * from './useSnacks';
export * from './ViewDataContext';
30 changes: 16 additions & 14 deletions judo-ui-react/src/main/resources/actor/src/main.tsx.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { accessServiceImpl, judoAxiosProvider } from '~/services/data-axios';
import App from './App';
import { routes } from './routes';
import { RootErrorBoundary } from './components/RootErrorBoundary';
import { ConfigProvider } from './hooks';
import { ConfigProvider, ViewDataProvider } from './hooks';

{{# if isMUILicensed }}
LicenseInfo.setLicenseKey(import.meta.env.VITE_MUI_LICENSE_KEY);
Expand Down Expand Up @@ -90,19 +90,21 @@ const FILE_DEFAULT_BASE_URL: string = import.meta.env.VITE_FILE_DEFAULT_BASE_URL
<StrictMode>
<ConfigProvider>
<ThemeCustomization>
<PandinoProvider ctx={pandino.getBundleContext()}>
<L10NProvider axios={axios}>
{{# if application.authentication }}
<AuthProvider {...oidcConfig} >
<Auth>
{{/ if }}
<RouterProvider router={router} />
{{# if application.authentication }}
</Auth>
</AuthProvider>
{{/ if }}
</L10NProvider>
</PandinoProvider>
<ViewDataProvider>
<PandinoProvider ctx={pandino.getBundleContext()}>
<L10NProvider axios={axios}>
{{# if application.authentication }}
<AuthProvider {...oidcConfig} >
<Auth>
{{/ if }}
<RouterProvider router={router} />
{{# if application.authentication }}
</Auth>
</AuthProvider>
{{/ if }}
</L10NProvider>
</PandinoProvider>
</ViewDataProvider>
</ThemeCustomization>
</ConfigProvider>
</StrictMode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {{ simpleActionDefinitionName action.actionDefinition }} = async (queryCus
{{ else }}
const result = await {{ getServiceImplForPage page }}.refresh({{{ refreshActionDataParameter action }}}, pageQueryCustomizer);
setData(result);
setLatestViewData(result);
// re-set payloadDiff
payloadDiff.current = {
__identifier: result.__identifier,
Expand All @@ -26,6 +27,7 @@ const {{ simpleActionDefinitionName action.actionDefinition }} = async (queryCus
{{/ if }}
} catch (error) {
handleError(error);
setLatestViewData(null);
return Promise.reject(error);
} finally {
setIsLoading(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { {{# unless page.container.table }}useCallback, useEffect, useRef, {{/ u
{{/ if }}
import { useJudoNavigation } from '~/components';
import { useConfirmDialog, useFilterDialog } from '~/components/dialog';
import { useSnacks, useCRUDDialog } from '~/hooks';
import { useSnacks, useCRUDDialog, useViewData } from '~/hooks';
import {
{{# if (hasPageRequiredBy page) }}passesLocalValidation,{{/ if }}
processQueryCustomizer,
Expand Down Expand Up @@ -94,6 +94,7 @@ export default function {{ pageName page }}() {
const { navigate, back: navigateBack } = useJudoNavigation();
const { openFilterDialog } = useFilterDialog();
const { openConfirmDialog } = useConfirmDialog();
const { setLatestViewData } = useViewData();
const handleError = useErrorHandler();
const openCRUDDialog = useCRUDDialog();

Expand Down
4 changes: 4 additions & 0 deletions judo-ui-react/src/main/resources/ui-react.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ templates:
pathExpression: "'src/hooks/useSnacks.ts'"
templateName: actor/src/hooks/useSnacks.ts.hbs

- name: actor/src/hooks/ViewDataContext.tsx
pathExpression: "'src/hooks/ViewDataContext.tsx'"
templateName: actor/src/hooks/ViewDataContext.tsx.hbs

# Actor - src - config

- name: actor/src/config/index.ts
Expand Down
Loading