diff --git a/packages/app/src/modules/Main/Components/ScoreCardManagement/hooks/useScorecardManage.ts b/packages/app/src/modules/Main/Components/ScoreCardManagement/hooks/useScorecardManage.ts index 9d278d270..a4d007049 100644 --- a/packages/app/src/modules/Main/Components/ScoreCardManagement/hooks/useScorecardManage.ts +++ b/packages/app/src/modules/Main/Components/ScoreCardManagement/hooks/useScorecardManage.ts @@ -141,7 +141,7 @@ export default function useScorecardManage() { setIsNew({ nextStepIndex: activeStepIndex + 1 }); const nextStep = steps[activeStepIndex + 1].id; - navigate(`/edit/${nextStep}/${id}?new=true`, { + navigate(`/edit/${id}/${nextStep}?new=true`, { replace: true, }); } diff --git a/packages/app/src/modules/Main/Components/ScoreCardManagement/hooks/useScorecardManagerNavigate.ts b/packages/app/src/modules/Main/Components/ScoreCardManagement/hooks/useScorecardManagerNavigate.ts index ec853dd5f..0be4f2535 100644 --- a/packages/app/src/modules/Main/Components/ScoreCardManagement/hooks/useScorecardManagerNavigate.ts +++ b/packages/app/src/modules/Main/Components/ScoreCardManagement/hooks/useScorecardManagerNavigate.ts @@ -16,11 +16,11 @@ export default function useScorecardManagerNavigate({ onSave, onNavigate, }: any) { - const { step = "general", id } = useParams(); + const { id } = useParams(); const navigate = useNavigate(); const [helpStepIndex, setHelpStepIndex] = useRecoilState(HelpIndex); const [activeStep, setActiveStep] = useRecoilState(ActiveStepState); - const { search } = useLocation(); + const { search, pathname } = useLocation(); const resetNewState = useResetRecoilState(IsNewScorecardState); const Component = activeStep.component; const { show } = useAlert( @@ -30,12 +30,17 @@ export default function useScorecardManagerNavigate({ useEffect(() => { const searchParams = new URLSearchParams(search); - const currentStep = find(steps, { id: step }); - if (!isEmpty(currentStep)) { - setActiveStep(() => { - return currentStep; - }); + const step = pathname.substring(pathname.lastIndexOf("/") + 1); + + if (!isEmpty(step)) { + const currentStep = find(steps, { id: step }); + + if (!isEmpty(currentStep)) { + setActiveStep(() => { + return currentStep; + }); + } } const isNew = searchParams.get("new"); @@ -43,13 +48,13 @@ export default function useScorecardManagerNavigate({ setActiveStep((prevStep) => { const currentIndex = findIndex(steps, ["id", prevStep.id]); if (currentIndex === 0) { - return steps[1]; + return steps[0]; } else { return prevStep; } }); } - }, [resetNewState, search, setActiveStep, step]); + }, [resetNewState, search, setActiveStep, pathname, id]); const hasNextStep = useMemo( () => findIndex(steps, ["id", activeStep.id]) !== steps.length - 1, @@ -70,18 +75,9 @@ export default function useScorecardManagerNavigate({ return; } - // if (!(await form.trigger())) { - // show({ - // message: i18n.t("Please fill in all required fields"), - // type: { info: true }, - // }); - // return; - // } - const index = findIndex(steps, ["id", activeStep.id]); if (index !== steps.length - 1) { onStepChange(steps[index + 1]); - // setActiveStep(steps[index + 1]); setHelpStepIndex(0); } }; @@ -99,10 +95,10 @@ export default function useScorecardManagerNavigate({ if (isEmpty(id)) { navigate(`/add/${step.id}`); } else { - const index = findIndex(steps, ["id", step.id]); - if (index !== 0) { - navigate(`/edit/${step.id}/${id}?new=true`); - } + const searchParams = new URLSearchParams(search); + const isNew = searchParams.get("new"); + const newQuery = isNew ? "?new=true" : ""; + navigate(`/edit/${id}/${step.id}${newQuery}`); } }, [activeStep, form, navigate], @@ -110,9 +106,8 @@ export default function useScorecardManagerNavigate({ const onPreviousStep = () => { const index = findIndex(steps, ["id", activeStep.id]); - //Why does it not allow to go back to the "General" step?? + if (index !== 0) { - // setActiveStep(steps[index - 1]); onStepChange(steps[index - 1]); setHelpStepIndex(0); } diff --git a/packages/app/src/modules/Main/Components/ScoreCardManagement/index.tsx b/packages/app/src/modules/Main/Components/ScoreCardManagement/index.tsx index 1e09213d1..af483c361 100644 --- a/packages/app/src/modules/Main/Components/ScoreCardManagement/index.tsx +++ b/packages/app/src/modules/Main/Components/ScoreCardManagement/index.tsx @@ -1,190 +1,200 @@ -import i18n from '@dhis2/d2-i18n'; -import {Button, ButtonStrip, Tooltip} from '@dhis2/ui'; -import {Step, StepLabel, Stepper} from '@material-ui/core'; -import HelpIcon from '@material-ui/icons/Help'; -import {AccessDeniedPage, FullPageLoader, HelpState, HelpSteps, STEP_OPTIONS, useMediaQuery, UserAuthorityOnScorecard,} from '@scorecard/shared'; -import {Steps} from 'intro.js-react'; -import React, {Suspense} from 'react'; -import {FormProvider} from 'react-hook-form'; -import {Outlet, useParams} from 'react-router-dom'; -import {useRecoilState, useRecoilValue} from 'recoil'; -import useScorecardManage from './hooks/useScorecardManage'; -import useScorecardManagerNavigate from './hooks/useScorecardManagerNavigate'; -import classes from './ScorecardManagement.module.css'; +import i18n from "@dhis2/d2-i18n"; +import { Button, ButtonStrip, Tooltip } from "@dhis2/ui"; +import { Step, StepLabel, Stepper } from "@material-ui/core"; +import HelpIcon from "@material-ui/icons/Help"; +import { + AccessDeniedPage, + FullPageLoader, + HelpState, + HelpSteps, + STEP_OPTIONS, + useMediaQuery, + UserAuthorityOnScorecard, +} from "@scorecard/shared"; +import { Steps } from "intro.js-react"; +import React, { Suspense } from "react"; +import { FormProvider } from "react-hook-form"; +import { Outlet, useParams } from "react-router-dom"; +import { useRecoilState, useRecoilValue } from "recoil"; +import useScorecardManage from "./hooks/useScorecardManage"; +import useScorecardManagerNavigate from "./hooks/useScorecardManagerNavigate"; +import classes from "./ScorecardManagement.module.css"; export default function ScoreCardManagement() { - const [helpEnabled, setHelpEnabled] = useRecoilState(HelpState); - const helpSteps = useRecoilValue(HelpSteps); - const {id: scorecardId} = useParams(); - const {write: writeAccess} = useRecoilValue( - UserAuthorityOnScorecard(scorecardId), - ); - const {height} = useMediaQuery(); - const { - form, - onSave, - saving, - onNavigate, - onSaveAndContinue, - savingAndContinue, - } = useScorecardManage(); - const { - Component, - activeStep, - helpStepIndex, - onCancel, - onNextStep, - onPreviousStep, - setHelpStepIndex, - steps, - currentIndex, - hasPreviousStep, - hasNextStep, - onStepChange, - } = useScorecardManagerNavigate({form, onSave, onNavigate}); + const [helpEnabled, setHelpEnabled] = useRecoilState(HelpState); + const helpSteps = useRecoilValue(HelpSteps); + const { id: scorecardId } = useParams(); - if (!writeAccess && scorecardId) { - return ; - } - //scorecardManagementTooltips - return ( - - }> -
- { - setHelpStepIndex(newStepIndex); - }} - onExit={() => { - setHelpEnabled(false); - }} - /> -
-
- - {steps?.map((step) => { - return ( - onStepChange(step)} - key={`${step.id}-step`} - > - - - {step.label} - - - - ); - })} - -
-
-
-
-
-
-
- -
+ const { write: writeAccess } = useRecoilValue( + UserAuthorityOnScorecard(scorecardId), + ); -
- { - }> - - - } -
+ const { height } = useMediaQuery(); + const { + form, + onSave, + saving, + onNavigate, + onSaveAndContinue, + savingAndContinue, + } = useScorecardManage(); + const { + Component, + activeStep, + helpStepIndex, + onCancel, + onNextStep, + onPreviousStep, + setHelpStepIndex, + steps, + currentIndex, + hasPreviousStep, + hasNextStep, + onStepChange, + } = useScorecardManagerNavigate({ form, onSave, onNavigate }); - - - - -
-
-
-
-
-
- - - {hasNextStep && ( - - )} - - -
-
-
-
-
- ); + if (!writeAccess && scorecardId) { + return ; + } + //scorecardManagementTooltips + return ( + + }> +
+ { + setHelpStepIndex(newStepIndex); + }} + onExit={() => { + setHelpEnabled(false); + }} + /> +
+
+ + {steps?.map((step) => { + return ( + onStepChange(step)} + key={`${step.id}-step`} + > + + + {step.label} + + + + ); + })} + +
+
+
+
+
+
+
+ +
+ +
+ { + }> + + + } +
+ + + + + +
+
+
+
+
+
+ + + {hasNextStep && ( + + )} + + +
+
+
+
+
+ ); } diff --git a/packages/app/src/modules/Router/index.tsx b/packages/app/src/modules/Router/index.tsx index 456a1eb18..91e137edf 100644 --- a/packages/app/src/modules/Router/index.tsx +++ b/packages/app/src/modules/Router/index.tsx @@ -1,83 +1,103 @@ -import {FullPageError, FullPageLoader, SystemSettingsState} from '@scorecard/shared'; -import React, {Suspense} from 'react'; -import {ErrorBoundary} from 'react-error-boundary'; -import {HashRouter, Navigate, Route, Routes} from 'react-router-dom'; -import {useRecoilValue} from 'recoil'; -import {steps} from '../Main/Components/ScoreCardManagement/state/pages'; +import { + FullPageError, + FullPageLoader, + SystemSettingsState, +} from "@scorecard/shared"; +import React, { Suspense, useEffect } from "react"; +import { ErrorBoundary } from "react-error-boundary"; +import { HashRouter, Navigate, Route, Routes } from "react-router-dom"; +import { useRecoilState, useRecoilValue } from "recoil"; +import { + ActiveStepState, + steps, +} from "../Main/Components/ScoreCardManagement/state/pages"; +import { find } from "lodash"; -const Main = React.lazy(() => import('../Main')); +const Main = React.lazy(() => import("../Main")); const ScorecardManagement = React.lazy(() => - import('../Main/Components/ScoreCardManagement'), + import("../Main/Components/ScoreCardManagement"), ); const ScorecardView = React.lazy(() => - import('@scorecard/shared').then((module) => ({ - default: module.ScorecardView, - })), + import("@scorecard/shared").then((module) => ({ + default: module.ScorecardView, + })), ); const ScorecardMigration = React.lazy(() => - import('../Main/Components/ScorecardMigration'), + import("../Main/Components/ScorecardMigration"), ); const pages = [ - { - path: '/migrate', - component: ScorecardMigration, - }, - { - path: '/edit/:id', - component: ScorecardManagement, - subItems: [ - ...steps.map((step) => ({ - path: step.id, - component: step.component, - })) - ] - }, - { - path: '/add/:step?', - component: ScorecardManagement, - }, - { - path: '/view/:id', - component: ScorecardView, - }, - { - path: '/', - component: Main, - }, + { + path: "/migrate", + component: ScorecardMigration, + }, + { + path: "/edit/:id", + component: ScorecardManagement, + subItems: [ + ...steps.map((step) => ({ + path: step.id, + component: step.component, + })), + ], + }, + { + path: "/add", + component: ScorecardManagement, + subItems: [ + ...steps.map((step) => ({ + path: step.id, + component: step.component, + })), + ], + }, + { + path: "/view/:id", + component: ScorecardView, + }, + { + path: "/", + component: Main, + }, ]; export default function Router() { - useRecoilValue(SystemSettingsState); + useRecoilValue(SystemSettingsState); - return ( - - - }> - - {pages.map(({path, component: Component, subItems}) => ( - - - - } - > - { - subItems?.map(({path, component: Component}) => ( - - - } key={path} path={path}/> - )) - } - - ))} - }/> - - - - - ); + return ( + + + }> + + {pages.map(({ path, component: Component, subItems }) => ( + + + + } + > + {subItems?.map(({ path, component: Component }) => { + return ( + + + + } + key={path} + path={path} + /> + ); + })} + + ))} + } /> + + + + + ); } diff --git a/packages/shared/package.json b/packages/shared/package.json index 00529b3ff..990cb002a 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,27 +1,27 @@ { - "name": "@scorecard/shared", - "version": "2.6.2", - "main": "./build/cjs/index.js", - "scripts": { - "build": "tsc && d2 app scripts build --verbose --no-verify", - "start": "d2 app scripts build --watch" - }, - "dependencies": { - "@dhis2/ui": "^9.10.2", - "jquery": "^3.6.4", - "react-hook-form": "^7.43.8", - "react-router-dom": "^6.25.1" - }, - "module": "./build/es/index.js", - "exports": { - "import": "./build/es/index.js", - "require": "./build/cjs/index.js", - "types": "./build/types/index.d.ts" - }, - "devDependencies": { - "@types/node": "^20.14.11", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "typescript": "^5.5.3" - } + "name": "@scorecard/shared", + "version": "2.6.2", + "main": "./build/cjs/index.js", + "scripts": { + "build": "tsc && d2 app scripts build --verbose --no-verify", + "start": "d2 app scripts build --watch" + }, + "dependencies": { + "@dhis2/ui": "^9.10.2", + "jquery": "^3.6.4", + "react-hook-form": "^7.43.8", + "react-router-dom": "^6.25.1" + }, + "module": "./build/es/index.js", + "exports": { + "import": "./build/es/index.js", + "require": "./build/cjs/index.js", + "types": "./build/types/index.d.ts" + }, + "devDependencies": { + "@types/node": "^20.14.11", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "typescript": "^5.5.3" + } } diff --git a/packages/shared/src/components/ScorecardView/components/ScorecardActions.tsx b/packages/shared/src/components/ScorecardView/components/ScorecardActions.tsx index ea899d6f5..a2b076559 100644 --- a/packages/shared/src/components/ScorecardView/components/ScorecardActions.tsx +++ b/packages/shared/src/components/ScorecardView/components/ScorecardActions.tsx @@ -63,9 +63,11 @@ export default function ScorecardActions({ }, serverVersion, ); - return window.parent.open(appUrl + "#/edit/" + scorecardId); + return window.parent.open( + appUrl + "#/edit/" + scorecardId + "/general", + ); } else { - navigate(`/edit/${scorecardId}`); + navigate(`/edit/${scorecardId}/general`); } } }; diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 5c2ec4b70..816dfc8e0 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -1,32 +1,22 @@ { - "compilerOptions": { - "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "declarationDir": "./build/types", - "declaration": true, - "allowJs": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": false, - "forceConsistentCasingInFileNames": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx" - }, - "include": [ - "src", - "../../type.d.ts" - ], - "exclude": [ - "node_modules", - "**/*.test.tsx" - ] + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "declarationDir": "./build/types", + "declaration": true, + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src", "../../type.d.ts"], + "exclude": ["node_modules", "**/*.test.tsx"] }