Skip to content

Commit

Permalink
Merge branch 'master' of github-chisom:dhis2/maintenance-app-beta int…
Browse files Browse the repository at this point in the history
…o DHIS2-18142/category-option-group-forms
  • Loading branch information
Chisomchima committed Oct 22, 2024
2 parents b74afbf + 5f0ecee commit b4f85ce
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 28 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# [0.9.0](https://github.com/dhis2/maintenance-app-beta/compare/v0.8.0...v0.9.0) (2024-10-22)


### Features

* new org unit form ([cee3edc](https://github.com/dhis2/maintenance-app-beta/commit/cee3edc5eded14f57dd6ec076baf7f8733b19ea5))
* preserve list state between form navigation ([#425](https://github.com/dhis2/maintenance-app-beta/issues/425)) ([da1f11f](https://github.com/dhis2/maintenance-app-beta/commit/da1f11f5a53c6c1f8874d9ce7af449f1d02e6ffc))

# [0.8.0](https://github.com/dhis2/maintenance-app-beta/compare/v0.7.1...v0.8.0) (2024-10-17)


Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "maintenance-app",
"version": "0.8.0",
"version": "0.9.0",
"description": "",
"license": "BSD-3-Clause",
"private": true,
Expand Down
4 changes: 3 additions & 1 deletion src/app/layout/Breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
isOverviewSection,
getSectionPath,
getOverviewPath,
useToWithSearchState,
} from '../../lib'
import type { MatchRouteHandle } from '../routes/types'
import css from './Breadcrumb.module.css'
Expand All @@ -19,11 +20,12 @@ type BreadcrumbItemProps = {
export const BreadcrumbItem = ({ section, label }: BreadcrumbItemProps) => {
const isOverview = isOverviewSection(section)
const link = isOverview ? getOverviewPath(section) : getSectionPath(section)
const to = useToWithSearchState(`/${link}`)

label = label ?? isOverview ? section.titlePlural : section.title

return (
<Link className={css.breadcrumbItem} to={`/${link}`}>
<Link className={css.breadcrumbItem} to={to}>
{label}
</Link>
)
Expand Down
7 changes: 3 additions & 4 deletions src/components/form/DefaultFormContents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import i18n from '@dhis2/d2-i18n'
import { Card } from '@dhis2/ui'
import React from 'react'
import { useFormState } from 'react-final-form'
import { useNavigate } from 'react-router-dom'
import { getSectionPath } from '../../lib'
import { getSectionPath, useNavigateWithSearchState } from '../../lib'
import { ModelSection } from '../../types'
import { StandardFormActions, StandardFormSection } from '../standardForm'
import classes from './DefaultFormContents.module.css'
Expand All @@ -19,7 +18,7 @@ export function DefaultEditFormContents({
const { submitting } = useFormState({
subscription: { submitting: true },
})
const navigate = useNavigate()
const navigate = useNavigateWithSearchState()

const listPath = `/${getSectionPath(section)}`

Expand Down Expand Up @@ -55,7 +54,7 @@ export function DefaultNewFormContents({
subscription: { submitting: true },
})

const navigate = useNavigate()
const navigate = useNavigateWithSearchState()

const listPath = `/${getSectionPath(section)}`

Expand Down
48 changes: 34 additions & 14 deletions src/components/sectionList/listActions/SectionListActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from '@dhis2/ui'
import React, { useRef, useState } from 'react'
import { useHref, useLinkClickHandler } from 'react-router-dom'
import { TOOLTIPS, BaseListModel } from '../../../lib'
import { TOOLTIPS, BaseListModel, useLocationSearchState } from '../../../lib'
import { LinkButton } from '../../LinkButton'
import { TooltipWrapper } from '../../tooltip'
import { DeleteAction } from './DeleteAction'
Expand All @@ -28,8 +28,14 @@ export const ListActions = ({ children }: React.PropsWithChildren) => {
}

export const ActionEdit = ({ modelId }: { modelId: string }) => {
const preservedSearchState = useLocationSearchState()
return (
<LinkButton small secondary to={modelId}>
<LinkButton
small
secondary
to={{ pathname: modelId }}
state={preservedSearchState}
>
<IconEdit24 />
</LinkButton>
)
Expand Down Expand Up @@ -60,8 +66,16 @@ export const ActionMore = ({
const [open, setOpen] = useState(false)
const ref = useRef(null)
const href = useHref(model.id, { relative: 'path' })
const preservedSearchState = useLocationSearchState()

const handleEditClick = useLinkClickHandler(model.id)
const handleEditClick = useLinkClickHandler(
{
pathname: model.id,
},
{
state: preservedSearchState,
}
)

return (
<div ref={ref}>
Expand Down Expand Up @@ -89,17 +103,23 @@ export const ActionMore = ({
setOpen(false)
}}
/>
<MenuItem
dense
label={i18n.t('Edit')}
icon={<IconEdit16 />}
onClick={(_, e) => {
handleEditClick(e)
setOpen(false)
}}
target="_blank"
href={href}
/>

<TooltipWrapper
condition={!editable}
content={TOOLTIPS.noEditAccess}
>
<MenuItem
dense
label={i18n.t('Edit')}
icon={<IconEdit16 />}
onClick={(_, e) => {
handleEditClick(e)
setOpen(false)
}}
target="_blank"
href={href}
/>
</TooltipWrapper>

{shareable && (
<TooltipWrapper
Expand Down
4 changes: 3 additions & 1 deletion src/components/sectionList/toolbar/ToolbarNormal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Link } from 'react-router-dom'
import {
routePaths,
useCanCreateModelInSection,
useLocationSearchState,
useModelSectionHandleOrThrow,
} from '../../../lib'
import { ManageListViewDialog } from '../listView/ManageListViewDialog'
Expand All @@ -21,12 +22,13 @@ export const ToolbarNormal = ({
const [manageColumnsOpen, setManageColumnsOpen] = React.useState(false)
const section = useModelSectionHandleOrThrow()
const canCreateModel = useCanCreateModelInSection(section)
const locationState = useLocationSearchState()

const handleClose = () => setManageColumnsOpen(false)
return (
<DataTableToolbar className={css.listHeaderNormal}>
{canCreateModel && (
<Link to={routePaths.sectionNew}>
<Link to={routePaths.sectionNew} state={locationState}>
<Button small icon={<IconAdd24 />}>
{i18n.t('New')}
</Button>
Expand Down
7 changes: 4 additions & 3 deletions src/lib/form/useOnSubmit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FormProps } from 'react-final-form'
import { useNavigate } from 'react-router-dom'
import { ModelSection } from '../../types'
import { IdentifiableObject } from '../../types/generated'
import { getSectionPath } from '../routeUtils'
import { getSectionPath, useNavigateWithSearchState } from '../routeUtils'
import { createJsonPatchOperations } from './createJsonPatchOperations'
import { useCreateModel } from './useCreateModel'
import { usePatchModel } from './usePatchModel'
Expand All @@ -26,7 +26,8 @@ export const useOnSubmitEdit = <TFormValues extends IdentifiableObject>({
({ message }) => message,
(options) => options
)
const navigate = useNavigate()

const navigate = useNavigateWithSearchState()

return useMemo<OnSubmit<TFormValues>>(
() => async (values, form) => {
Expand Down Expand Up @@ -68,7 +69,7 @@ export const useOnSubmitNew = <TFormValues>({
({ message }) => message,
(options) => options
)
const navigate = useNavigate()
const navigate = useNavigateWithSearchState()

return useMemo<OnSubmit<TFormValues>>(
() => async (values) => {
Expand Down
1 change: 1 addition & 0 deletions src/lib/routeUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export {
getSectionNewPath,
} from './routePaths'
export * from './useSectionHandle'
export * from './useLocationSearchState'
81 changes: 81 additions & 0 deletions src/lib/routeUtils/useLocationSearchState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { useCallback, useMemo } from 'react'
import {
Location,
NavigateOptions,
To,
useLocation,
useNavigate,
} from 'react-router-dom'

/* We use location.state to transiently save search-params between pages.
Eg. when a user navigates from a list to a form, we can save the previously active filter-state
in location.state when navigating. This will "remove" the query-params from the URL in the form-page.
When navigating back to the list through a link, we reapply this saved state using `useNavigateWithSearchState` below.
Using the browsers-back button should have the same behaviour, since the query-params are part of the history. */

type LocationSearchState = {
search?: string
} | null

const createLocationState = (search: string): LocationSearchState => ({
search,
})

const applySearchState = (to: To, locationSearchState: LocationSearchState) => {
if (typeof to === 'string') {
return { pathname: to, search: locationSearchState?.search }
}
return { ...to, search: to.search || locationSearchState?.search }
}

/**
* Use this to preserve the current search-state between pages.
* Pass the returned state to Link components or as options to navigate as "state"-property.
* @returns an object that holds the current search-state.
*/
export const useLocationSearchState = () => {
const location = useLocation()

return useMemo(
() => createLocationState(location.search),
[location.search]
)
}

/** This is just a type-wrapper, applying the LocationSearchState type to useLocation */
export const useLocationWithSearchState: () => Location<LocationSearchState> =
useLocation

/**
* Wraps react-router "useNavigate" to include the search state as query-Paramters, retrieved from the location state.
*
* Use this to reapply the saved search-state when navigating between pages.
*
* Note that the current route has to include the search state in the location state,
* which can be achieved by passing "state" to Link components or as options to navigate.
* This will put the transiently saved search-state back in as active search-params (eg. result in query-Params in the URL).
* @returns
*/
export const useNavigateWithSearchState = () => {
const location = useLocationWithSearchState()

const navigate = useNavigate()

const overiddenNavigate = useCallback(
(to: To, options?: NavigateOptions) => {
const toWithSearchState = applySearchState(to, location.state)
return navigate(toWithSearchState, options)
},
[navigate, location.state]
)
return overiddenNavigate
}

/* Helper-hook to create a "to"-object that can be passed to react-router Link components (and navigate).
Use this to re-apply the saved-search-state when navigating between pages. */
export const useToWithSearchState = (to: To) => {
const location = useLocationWithSearchState()
return useMemo(() => {
return applySearchState(to, location.state)
}, [to, location.state])
}
11 changes: 8 additions & 3 deletions src/pages/dataElements/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import {
} from '../../components'
import { useCustomAttributesQuery } from '../../components/form'
import { AttributeMetadata } from '../../components/form/attributes/useCustomAttributesQuery'
import { SCHEMA_SECTIONS, getSectionPath, validate } from '../../lib'
import {
SCHEMA_SECTIONS,
getSectionPath,
useNavigateWithSearchState,
validate,
} from '../../lib'
import { createJsonPatchOperations } from '../../lib/form/createJsonPatchOperations'
import { getAllAttributeValues } from '../../lib/models/attributes'
import { JsonPatchOperation } from '../../types'
Expand Down Expand Up @@ -130,7 +135,7 @@ function usePatchDirtyFields() {
}

export const Component = () => {
const navigate = useNavigate()
const navigate = useNavigateWithSearchState()
const params = useParams()
const dataElementId = params.id as string
const dataElementQuery = useDataElementQuery(dataElementId)
Expand Down Expand Up @@ -193,7 +198,7 @@ function FormContents({
submitError?: string
}) {
const formErrorRef = useRef<HTMLDivElement | null>(null)
const navigate = useNavigate()
const navigate = useNavigateWithSearchState()

useEffect(() => {
if (submitError) {
Expand Down
3 changes: 2 additions & 1 deletion src/pages/dataElements/New.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
DEFAULT_CATEGORY_COMBO,
SCHEMA_SECTIONS,
getSectionPath,
useNavigateWithSearchState,
useSchemas,
validate,
} from '../../lib'
Expand Down Expand Up @@ -100,7 +101,7 @@ function formatFormValues({ values }: { values: FormValues }) {

export const Component = () => {
const dataEngine = useDataEngine()
const navigate = useNavigate()
const navigate = useNavigateWithSearchState()
const customAttributesQuery = useCustomAttributesQuery()
const initialValues = useInitialValues(customAttributesQuery.data)

Expand Down

0 comments on commit b4f85ce

Please sign in to comment.