From 7cc9bf7ffb9bdac7f6f383bf0659c44b1c802807 Mon Sep 17 00:00:00 2001 From: Sean Fong Date: Tue, 25 Jul 2023 14:26:32 +0930 Subject: [PATCH 1/7] Render tabbed form for embedded browser differently --- .../Buttons/CreateNewResponseButton.tsx | 6 ++ .../components/PlaygroundRenderer.tsx | 2 - .../Collapsible/FormBodySingleCollapsible.tsx | 59 ++++++++++++ .../FormBodySingleCollapsibleWrapper.tsx | 76 +++++++++++++++ .../FormPage/FormBodyCollapsible.tsx | 96 +++++++++++++++++++ .../components/FormPage/FormTopLevelItem.tsx | 15 +++ .../src/stores/useConfigStore.ts | 4 + .../src/theme/overrides/Accordion.ts | 34 +++++++ .../src/theme/overrides/Overrides.ts | 2 + 9 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsible.tsx create mode 100644 apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsibleWrapper.tsx create mode 100644 apps/smart-forms-app/src/features/renderer/components/FormPage/FormBodyCollapsible.tsx create mode 100644 apps/smart-forms-app/src/theme/overrides/Accordion.ts diff --git a/apps/smart-forms-app/src/features/dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx b/apps/smart-forms-app/src/features/dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx index 44fd5dedd..b8cbc3fc8 100644 --- a/apps/smart-forms-app/src/features/dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx +++ b/apps/smart-forms-app/src/features/dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx @@ -28,6 +28,7 @@ import EditNoteIcon from '@mui/icons-material/EditNote'; function CreateNewResponseButton() { const smartClient = useConfigStore((state) => state.smartClient); + const setLaunchIntent = useConfigStore((state) => state.setLaunchIntent); const buildSourceQuestionnaire = useQuestionnaireStore((state) => state.buildSourceQuestionnaire); const buildSourceResponse = useQuestionnaireResponseStore((state) => state.buildSourceResponse); @@ -57,6 +58,11 @@ function CreateNewResponseButton() { const questionnaireResponse = createQuestionnaireResponse(questionnaire); buildSourceResponse(questionnaireResponse); + // FIXME this is a hack to test tabs rendering in an embedded browser + if (questionnaire.id === 'TestIntentCollapsible') { + setLaunchIntent('embedded-browser'); + } + navigate('/renderer'); setIsLoading(false); } diff --git a/apps/smart-forms-app/src/features/playground/components/PlaygroundRenderer.tsx b/apps/smart-forms-app/src/features/playground/components/PlaygroundRenderer.tsx index 031f55c58..56dd8de28 100644 --- a/apps/smart-forms-app/src/features/playground/components/PlaygroundRenderer.tsx +++ b/apps/smart-forms-app/src/features/playground/components/PlaygroundRenderer.tsx @@ -20,8 +20,6 @@ import { createQuestionnaireResponse } from '../../renderer/utils/qrItem.ts'; import useQuestionnaireStore from '../../../stores/useQuestionnaireStore.ts'; import useQuestionnaireResponseStore from '../../../stores/useQuestionnaireResponseStore.ts'; -// TODO this cant be used yet - function PlaygroundRenderer() { const sourceQuestionnaire = useQuestionnaireStore((state) => state.sourceQuestionnaire); diff --git a/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsible.tsx b/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsible.tsx new file mode 100644 index 000000000..1fd8c1613 --- /dev/null +++ b/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsible.tsx @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4'; +import GroupItem from '../QFormComponents/GroupItem/GroupItem.tsx'; +import FormBodySingleCollapsibleWrapper from './FormBodySingleCollapsibleWrapper.tsx'; +import type { PropsWithQrItemChangeHandler } from '../../../types/renderProps.interface.ts'; +import useHidden from '../../../hooks/useHidden.ts'; + +interface FormBodySingleCollapsibleProps + extends PropsWithQrItemChangeHandler { + qItem: QuestionnaireItem; + qrItem: QuestionnaireResponseItem; + index: number; + selectedIndex: number; + onToggleExpand: (index: number) => void; +} + +function FormBodySingleCollapsible(props: FormBodySingleCollapsibleProps) { + const { qItem, qrItem, index, selectedIndex, onToggleExpand, onQrItemChange } = props; + + const itemIsHidden = useHidden(qItem); + if (itemIsHidden) { + return null; + } + + return ( + + + + ); +} + +export default FormBodySingleCollapsible; diff --git a/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsibleWrapper.tsx b/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsibleWrapper.tsx new file mode 100644 index 000000000..77d040b7c --- /dev/null +++ b/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsibleWrapper.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2023 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ReactNode } from 'react'; +import { memo } from 'react'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Tooltip, + Typography +} from '@mui/material'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import { getContextDisplays } from '../../../utils/tabs.ts'; +import { QuestionnaireItem } from 'fhir/r4'; +import { getShortText } from '../../../utils/itemControl.ts'; +import GroupHeadingIcon from '../QFormComponents/GroupItem/GroupHeadingIcon.tsx'; + +interface FormBodySingleCollapsibleProps { + qItem: QuestionnaireItem; + index: number; + selectedIndex: number; + onToggleExpand: (index: number) => void; + children: ReactNode; +} + +const FormBodySingleCollapsibleWrapper = memo(function FormBodySingleCollapsible( + props: FormBodySingleCollapsibleProps +) { + const { qItem, index, selectedIndex, onToggleExpand, children } = props; + + const contextDisplayItems = getContextDisplays(qItem); + + const collapsibleLabel = getShortText(qItem) ?? qItem.text ?? ''; + + return ( + onToggleExpand(index)}> + + + + }> + + {collapsibleLabel} + + {contextDisplayItems.map((item) => { + return ; + })} + + + + {children} + + ); +}); + +export default FormBodySingleCollapsibleWrapper; diff --git a/apps/smart-forms-app/src/features/renderer/components/FormPage/FormBodyCollapsible.tsx b/apps/smart-forms-app/src/features/renderer/components/FormPage/FormBodyCollapsible.tsx new file mode 100644 index 000000000..622205f89 --- /dev/null +++ b/apps/smart-forms-app/src/features/renderer/components/FormPage/FormBodyCollapsible.tsx @@ -0,0 +1,96 @@ +/* + * Copyright 2023 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { useMemo } from 'react'; +import { Stack } from '@mui/material'; +import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4'; +import { getQrItemsIndex, mapQItemsIndex } from '../../utils'; +import { updateLinkedItem } from '../../utils/qrItem.ts'; +import type { PropsWithQrItemChangeHandler } from '../../types/renderProps.interface.ts'; +import useQuestionnaireStore from '../../../../stores/useQuestionnaireStore.ts'; +import FormBodySingleCollapsible from './Collapsible/FormBodySingleCollapsible.tsx'; + +interface FormBodyCollapsibleProps extends PropsWithQrItemChangeHandler { + topLevelQItem: QuestionnaireItem; + topLevelQRItem: QuestionnaireResponseItem; +} + +function FormBodyCollapsible(props: FormBodyCollapsibleProps) { + const { topLevelQItem, topLevelQRItem, onQrItemChange } = props; + + const currentTab = useQuestionnaireStore((state) => state.currentTabIndex); + const tabs = useQuestionnaireStore((state) => state.tabs); + + const switchTab = useQuestionnaireStore((state) => state.switchTab); + + const indexMap: Record = useMemo( + () => mapQItemsIndex(topLevelQItem), + [topLevelQItem] + ); + + const qItems = topLevelQItem.item; + const qrItems = topLevelQRItem.item; + + function handleQrGroupChange(qrItem: QuestionnaireResponseItem) { + updateLinkedItem(qrItem, null, topLevelQRItem, indexMap); + onQrItemChange(topLevelQRItem); + } + + if (!qItems || !qrItems) { + return <>Unable to load form; + } + + function handleToggleExpand(index: number) { + switchTab(currentTab === index ? -1 : index); + } + + if (!qItems || !qrItems) { + return <>Unable to load form; + } + + const qrItemsByIndex = getQrItemsIndex(qItems, qrItems, indexMap); + + return ( + + {qItems.map((qItem, i) => { + const qrItem = qrItemsByIndex[i]; + + const isNotRepeatGroup = !Array.isArray(qrItem); + const isTab = !!tabs[qItem.linkId]; + + if (!isTab || !isNotRepeatGroup) { + // Something has gone horribly wrong + return null; + } + + return ( + + ); + })} + + ); +} + +export default FormBodyCollapsible; diff --git a/apps/smart-forms-app/src/features/renderer/components/FormPage/FormTopLevelItem.tsx b/apps/smart-forms-app/src/features/renderer/components/FormPage/FormTopLevelItem.tsx index d110c7188..58757e3a6 100644 --- a/apps/smart-forms-app/src/features/renderer/components/FormPage/FormTopLevelItem.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/FormPage/FormTopLevelItem.tsx @@ -21,6 +21,8 @@ import { containsTabs, isTabContainer } from '../../utils/tabs.ts'; import GroupItem from './QFormComponents/GroupItem/GroupItem.tsx'; import SingleItem from './QFormComponents/SingleItem/SingleItem.tsx'; import type { PropsWithQrItemChangeHandler } from '../../types/renderProps.interface.ts'; +import useConfigStore from '../../../../stores/useConfigStore.ts'; +import FormBodyCollapsible from './FormBodyCollapsible.tsx'; interface FormTopLevelItemProps extends PropsWithQrItemChangeHandler { topLevelQItem: QuestionnaireItem; @@ -30,6 +32,8 @@ interface FormTopLevelItemProps extends PropsWithQrItemChangeHandler state.launchIntent); + const itemIsTabContainer = isTabContainer(topLevelQItem); const itemContainsTabs = containsTabs(topLevelQItem); @@ -37,6 +41,17 @@ function FormTopLevelItem(props: FormTopLevelItemProps) { // If form is tabbed, it is rendered as a tabbed form if (itemContainsTabs || itemIsTabContainer) { + if (launchIntent === 'embedded-browser') { + return ( + + ); + } + return ( void; setPatient: (patient: Patient) => void; setUser: (user: Practitioner) => void; setEncounter: (encounter: Encounter) => void; + setLaunchIntent: (launchIntent: string) => void; activateDebugMode: () => void; } @@ -20,11 +22,13 @@ const useConfigStore = create()((set) => ({ patient: null, user: null, encounter: null, + launchIntent: null, debugMode: false, setSmartClient: (client: Client) => set(() => ({ smartClient: client })), setPatient: (patient: Patient) => set(() => ({ patient: patient })), setUser: (user: Practitioner) => set(() => ({ user: user })), setEncounter: (encounter: Encounter) => set(() => ({ encounter: encounter })), + setLaunchIntent: (launchIntent: string) => set(() => ({ launchIntent: launchIntent })), activateDebugMode: () => set(() => ({ debugMode: true })) })); diff --git a/apps/smart-forms-app/src/theme/overrides/Accordion.ts b/apps/smart-forms-app/src/theme/overrides/Accordion.ts new file mode 100644 index 000000000..d040d4907 --- /dev/null +++ b/apps/smart-forms-app/src/theme/overrides/Accordion.ts @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Theme } from '@mui/material'; + +export default function Accordion(theme: Theme) { + return { + MuiAccordion: { + styleOverrides: { + root: { + boxShadow: theme.customShadows.z1, + borderRadius: Number(theme.shape.borderRadius) * 2, + '&:before': { + display: 'none' + } + } + } + } + }; +} diff --git a/apps/smart-forms-app/src/theme/overrides/Overrides.ts b/apps/smart-forms-app/src/theme/overrides/Overrides.ts index b480513ae..895674d29 100644 --- a/apps/smart-forms-app/src/theme/overrides/Overrides.ts +++ b/apps/smart-forms-app/src/theme/overrides/Overrides.ts @@ -23,10 +23,12 @@ import Button from './Button'; import Backdrop from './Backdrop'; import Typography from './Typography'; import Autocomplete from './Autocomplete'; +import Accordion from './Accordion'; import type { Theme } from '@mui/material'; function ComponentsOverrides(theme: Theme) { return Object.assign( + Accordion(theme), Card(theme), Table(theme), Input(theme), From 301bcd25f68a9b1dc9f9dc5f2478dbe9493f3f77 Mon Sep 17 00:00:00 2001 From: Sean Fong Date: Tue, 25 Jul 2023 14:53:42 +0930 Subject: [PATCH 2/7] Exchange collapsible component names --- .../Collapsible/FormBodySingleCollapsible.tsx | 75 ++++++++++++------- .../FormBodySingleCollapsibleWrapper.tsx | 75 +++++++------------ .../FormPage/FormBodyCollapsible.tsx | 8 +- 3 files changed, 79 insertions(+), 79 deletions(-) diff --git a/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsible.tsx b/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsible.tsx index 1fd8c1613..d0ebf499f 100644 --- a/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsible.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsible.tsx @@ -15,45 +15,62 @@ * limitations under the License. */ -import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4'; -import GroupItem from '../QFormComponents/GroupItem/GroupItem.tsx'; -import FormBodySingleCollapsibleWrapper from './FormBodySingleCollapsibleWrapper.tsx'; -import type { PropsWithQrItemChangeHandler } from '../../../types/renderProps.interface.ts'; -import useHidden from '../../../hooks/useHidden.ts'; +import type { ReactNode } from 'react'; +import { memo } from 'react'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Tooltip, + Typography +} from '@mui/material'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import { getContextDisplays } from '../../../utils/tabs.ts'; +import { QuestionnaireItem } from 'fhir/r4'; +import { getShortText } from '../../../utils/itemControl.ts'; +import GroupHeadingIcon from '../QFormComponents/GroupItem/GroupHeadingIcon.tsx'; -interface FormBodySingleCollapsibleProps - extends PropsWithQrItemChangeHandler { +interface FormBodySingleCollapsibleProps { qItem: QuestionnaireItem; - qrItem: QuestionnaireResponseItem; index: number; selectedIndex: number; onToggleExpand: (index: number) => void; + children: ReactNode; } -function FormBodySingleCollapsible(props: FormBodySingleCollapsibleProps) { - const { qItem, qrItem, index, selectedIndex, onToggleExpand, onQrItemChange } = props; +const FormBodySingleCollapsible = memo(function FormBodySingleCollapsible( + props: FormBodySingleCollapsibleProps +) { + const { qItem, index, selectedIndex, onToggleExpand, children } = props; - const itemIsHidden = useHidden(qItem); - if (itemIsHidden) { - return null; - } + const contextDisplayItems = getContextDisplays(qItem); + + const collapsibleLabel = getShortText(qItem) ?? qItem.text ?? ''; return ( - - - + onToggleExpand(index)}> + + + + }> + + {collapsibleLabel} + + {contextDisplayItems.map((item) => { + return ; + })} + + + + {children} + ); -} +}); export default FormBodySingleCollapsible; diff --git a/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsibleWrapper.tsx b/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsibleWrapper.tsx index 77d040b7c..54de1f892 100644 --- a/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsibleWrapper.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/FormPage/Collapsible/FormBodySingleCollapsibleWrapper.tsx @@ -15,62 +15,45 @@ * limitations under the License. */ -import type { ReactNode } from 'react'; -import { memo } from 'react'; -import { - Accordion, - AccordionDetails, - AccordionSummary, - Box, - Tooltip, - Typography -} from '@mui/material'; -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import { getContextDisplays } from '../../../utils/tabs.ts'; -import { QuestionnaireItem } from 'fhir/r4'; -import { getShortText } from '../../../utils/itemControl.ts'; -import GroupHeadingIcon from '../QFormComponents/GroupItem/GroupHeadingIcon.tsx'; +import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4'; +import GroupItem from '../QFormComponents/GroupItem/GroupItem.tsx'; +import FormBodySingleCollapsible from './FormBodySingleCollapsible.tsx'; +import type { PropsWithQrItemChangeHandler } from '../../../types/renderProps.interface.ts'; +import useHidden from '../../../hooks/useHidden.ts'; -interface FormBodySingleCollapsibleProps { +interface FormBodySingleCollapsibleProps + extends PropsWithQrItemChangeHandler { qItem: QuestionnaireItem; + qrItem: QuestionnaireResponseItem; index: number; selectedIndex: number; onToggleExpand: (index: number) => void; - children: ReactNode; } -const FormBodySingleCollapsibleWrapper = memo(function FormBodySingleCollapsible( - props: FormBodySingleCollapsibleProps -) { - const { qItem, index, selectedIndex, onToggleExpand, children } = props; +function FormBodySingleCollapsibleWrapper(props: FormBodySingleCollapsibleProps) { + const { qItem, qrItem, index, selectedIndex, onToggleExpand, onQrItemChange } = props; - const contextDisplayItems = getContextDisplays(qItem); - - const collapsibleLabel = getShortText(qItem) ?? qItem.text ?? ''; + const itemIsHidden = useHidden(qItem); + if (itemIsHidden) { + return null; + } return ( - onToggleExpand(index)}> - - - - }> - - {collapsibleLabel} - - {contextDisplayItems.map((item) => { - return ; - })} - - - - {children} - + + + ); -}); +} export default FormBodySingleCollapsibleWrapper; diff --git a/apps/smart-forms-app/src/features/renderer/components/FormPage/FormBodyCollapsible.tsx b/apps/smart-forms-app/src/features/renderer/components/FormPage/FormBodyCollapsible.tsx index 622205f89..0ceb33180 100644 --- a/apps/smart-forms-app/src/features/renderer/components/FormPage/FormBodyCollapsible.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/FormPage/FormBodyCollapsible.tsx @@ -22,14 +22,14 @@ import { getQrItemsIndex, mapQItemsIndex } from '../../utils'; import { updateLinkedItem } from '../../utils/qrItem.ts'; import type { PropsWithQrItemChangeHandler } from '../../types/renderProps.interface.ts'; import useQuestionnaireStore from '../../../../stores/useQuestionnaireStore.ts'; -import FormBodySingleCollapsible from './Collapsible/FormBodySingleCollapsible.tsx'; +import FormBodySingleCollapsibleWrapper from './Collapsible/FormBodySingleCollapsibleWrapper.tsx'; interface FormBodyCollapsibleProps extends PropsWithQrItemChangeHandler { topLevelQItem: QuestionnaireItem; topLevelQRItem: QuestionnaireResponseItem; } -function FormBodyCollapsible(props: FormBodyCollapsibleProps) { +function FormBodyCollapsibleWrapper(props: FormBodyCollapsibleProps) { const { topLevelQItem, topLevelQRItem, onQrItemChange } = props; const currentTab = useQuestionnaireStore((state) => state.currentTabIndex); @@ -78,7 +78,7 @@ function FormBodyCollapsible(props: FormBodyCollapsibleProps) { } return ( - Date: Tue, 25 Jul 2023 17:04:48 +0930 Subject: [PATCH 3/7] Add speed dial to embedded view --- .../components/RendererEmbeddedSpeedDial.tsx | 163 ++++++++++++++++++ .../renderer/components/RendererLayout.tsx | 22 ++- .../components/RendererNav/RendererNav.tsx | 78 ++------- .../RendererNav/RendererNavDrawer.tsx | 78 +++++++++ .../RendererNav/RendererNavWrapper.tsx | 57 ++++++ .../src/theme/overrides/Overrides.ts | 4 +- .../src/theme/overrides/SpeedDial.ts | 36 ++++ 7 files changed, 367 insertions(+), 71 deletions(-) create mode 100644 apps/smart-forms-app/src/features/renderer/components/RendererEmbeddedSpeedDial.tsx create mode 100644 apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavDrawer.tsx create mode 100644 apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavWrapper.tsx create mode 100644 apps/smart-forms-app/src/theme/overrides/SpeedDial.ts diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererEmbeddedSpeedDial.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererEmbeddedSpeedDial.tsx new file mode 100644 index 000000000..bcc9f01d6 --- /dev/null +++ b/apps/smart-forms-app/src/features/renderer/components/RendererEmbeddedSpeedDial.tsx @@ -0,0 +1,163 @@ +/* + * Copyright 2023 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { SpeedDial, SpeedDialAction } from '@mui/material'; +import BuildIcon from '@mui/icons-material/Build'; +import GradingIcon from '@mui/icons-material/Grading'; +import { useNavigate } from 'react-router-dom'; +import { useSnackbar } from 'notistack'; +import EditIcon from '@mui/icons-material/Edit'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import useConfigStore from '../../../stores/useConfigStore.ts'; +import useQuestionnaireStore from '../../../stores/useQuestionnaireStore.ts'; +import cloneDeep from 'lodash.clonedeep'; +import { removeHiddenAnswers, saveQuestionnaireResponse } from '../../save/api/saveQr.ts'; +import useQuestionnaireResponseStore from '../../../stores/useQuestionnaireResponseStore.ts'; +import SaveIcon from '@mui/icons-material/Save'; +import TaskAltIcon from '@mui/icons-material/TaskAlt'; +import { useState } from 'react'; +import RendererSaveAsFinalDialog from './RendererNav/SaveAsFinal/RendererSaveAsFinalDialog.tsx'; + +interface RendererEmbeddedSpeedDialProps { + isPopulating: boolean; +} +function RendererEmbeddedSpeedDial(props: RendererEmbeddedSpeedDialProps) { + const { isPopulating } = props; + + const smartClient = useConfigStore((state) => state.smartClient); + const patient = useConfigStore((state) => state.patient); + const user = useConfigStore((state) => state.user); + + const sourceQuestionnaire = useQuestionnaireStore((state) => state.sourceQuestionnaire); + const enableWhenIsActivated = useQuestionnaireStore((state) => state.enableWhenIsActivated); + const enableWhenItems = useQuestionnaireStore((state) => state.enableWhenItems); + const enableWhenExpressions = useQuestionnaireStore((state) => state.enableWhenExpressions); + + const updatableResponse = useQuestionnaireResponseStore((state) => state.updatableResponse); + const saveResponse = useQuestionnaireResponseStore((state) => state.saveResponse); + + const [saveAsFinalDialogOpen, setSaveAsFinalDialogOpen] = useState(false); + + const { enqueueSnackbar } = useSnackbar(); + + const navigate = useNavigate(); + const { closeSnackbar } = useSnackbar(); + + function handleViewResponses() { + closeSnackbar(); + navigate('/dashboard/responses'); + } + + function handlePreview() { + if (location.pathname === '/renderer/preview') { + navigate('/renderer'); + } else { + navigate('/renderer/preview'); + } + } + + function handleSaveAsDraft() { + if (!(smartClient && patient && user)) { + return; + } + + let responseToSave = cloneDeep(updatableResponse); + responseToSave = removeHiddenAnswers({ + questionnaire: sourceQuestionnaire, + questionnaireResponse: responseToSave, + enableWhenIsActivated, + enableWhenItems, + enableWhenExpressions + }); + + responseToSave.status = 'in-progress'; + saveQuestionnaireResponse(smartClient, patient, user, sourceQuestionnaire, responseToSave) + .then((savedResponse) => { + saveResponse(savedResponse); + enqueueSnackbar('Response saved as draft', { variant: 'success' }); + }) + .catch((error) => { + console.error(error); + enqueueSnackbar('An error occurred while saving. Try again later.', { + variant: 'error' + }); + }); + } + + function handleSaveAsFinal() { + if (smartClient) { + setSaveAsFinalDialogOpen(true); + } + } + + const showSaveButtons = smartClient && sourceQuestionnaire.item; + + if (isPopulating) { + return null; + } + + return ( + <> + }> + } + tooltipTitle="View Responses" + tooltipOpen + onClick={handleViewResponses} + /> + : } + tooltipTitle={location.pathname === '/renderer/preview' ? 'Editor' : 'Preview'} + tooltipOpen + onClick={handlePreview} + /> + + {showSaveButtons && ( + } + tooltipTitle={'Save as Draft'} + tooltipOpen + onClick={handleSaveAsDraft} + /> + )} + + {showSaveButtons && ( + } + tooltipTitle={'Save as Final'} + tooltipOpen + onClick={handleSaveAsFinal} + /> + )} + + setSaveAsFinalDialogOpen(false)} + /> + + ); +} + +export default RendererEmbeddedSpeedDial; diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererLayout.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererLayout.tsx index 7df4eed87..a053fb2cc 100644 --- a/apps/smart-forms-app/src/features/renderer/components/RendererLayout.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/RendererLayout.tsx @@ -17,7 +17,7 @@ import { useState } from 'react'; import RendererHeader from './RendererHeader/RendererHeader.tsx'; -import RendererNav from './RendererNav/RendererNav.tsx'; +import RendererNavWrapper from './RendererNav/RendererNavWrapper.tsx'; import { StyledRoot } from '../../../components/Layout/Layout.styles.ts'; import { Main } from './RendererLayout.styles.ts'; import { populateQuestionnaire } from '../../prepopulate/utils/populate.ts'; @@ -37,6 +37,7 @@ import useConfigStore from '../../../stores/useConfigStore.ts'; import useQuestionnaireResponseStore from '../../../stores/useQuestionnaireResponseStore.ts'; import useQuestionnaireStore from '../../../stores/useQuestionnaireStore.ts'; import _isEqual from 'lodash/isEqual'; +import RendererEmbeddedSpeedDial from './RendererEmbeddedSpeedDial.tsx'; function RendererLayout() { const sourceQuestionnaire = useQuestionnaireStore((state) => state.sourceQuestionnaire); @@ -53,6 +54,7 @@ function RendererLayout() { const patient = useConfigStore((state) => state.patient); const user = useConfigStore((state) => state.user); const encounter = useConfigStore((state) => state.encounter); + const launchIntent = useConfigStore((state) => state.launchIntent); const [open, setOpen] = useState(false); const [navIsCollapsed, collapseNav] = useState(false); @@ -128,11 +130,13 @@ function RendererLayout() { setSpinner({ ...spinner, isLoading: false }); } } + const isEmbeddedView = launchIntent === 'embedded-browser'; return ( setOpen(true)} navIsCollapsed={navIsCollapsed} /> - setOpen(false)} navCollapsed={navIsCollapsed} @@ -154,11 +158,15 @@ function RendererLayout() { collapseNav(false)} /> - - - - - + {isEmbeddedView ? ( + + ) : ( + + + + + + )} ); } diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNav.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNav.tsx index d1279cc51..bef8da833 100644 --- a/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNav.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNav.tsx @@ -15,38 +15,28 @@ * limitations under the License. */ -import { Box, Drawer, Grid, IconButton, Tooltip } from '@mui/material'; -import useResponsive from '../../../../hooks/useResponsive.ts'; +import { NavLogoWrapper } from '../../../../components/Logos/Logo.styles.ts'; import Logo from '../../../../components/Logos/Logo.tsx'; -import Scrollbar from '../../../../components/Scrollbar/Scrollbar.tsx'; import NavPatientDetails from '../../../../components/Nav/NavPatientDetails.tsx'; import RendererNavSection from './RendererNavSection.tsx'; import RendererOperationSection from './RendererOperationSection.tsx'; +import { Box, Grid, IconButton, Tooltip } from '@mui/material'; +import { NavErrorAlertWrapper } from '../../../../components/Nav/Nav.styles.ts'; import NavErrorAlert from '../../../../components/Nav/NavErrorAlert.tsx'; -import KeyboardDoubleArrowLeftIcon from '@mui/icons-material/KeyboardDoubleArrowLeft'; import CsiroLogo from '../../../../components/Logos/CsiroLogo.tsx'; -import { NavLogoWrapper } from '../../../../components/Logos/Logo.styles.ts'; -import { NavErrorAlertWrapper } from '../../../../components/Nav/Nav.styles.ts'; -import useConfigStore from '../../../../stores/useConfigStore.ts'; -import { NAV_WIDTH } from '../../../../components/Header/Header.styles.ts'; +import KeyboardDoubleArrowLeftIcon from '@mui/icons-material/KeyboardDoubleArrowLeft'; +import Scrollbar from '../../../../components/Scrollbar/Scrollbar.tsx'; -interface Props { - openNav: boolean; - navCollapsed: boolean; - onCloseNav: () => void; - setNavCollapsed: () => void; +interface RendererNavProps { + isNotLaunched: boolean; + navIsShown: boolean; + onCollapseNav: () => void; } -function RendererNav(props: Props) { - const { openNav, onCloseNav, navCollapsed, setNavCollapsed } = props; +function RendererNav(props: RendererNavProps) { + const { isNotLaunched, navIsShown, onCollapseNav } = props; - const smartClient = useConfigStore((state) => state.smartClient); - - const isDesktop = useResponsive('up', 'lg'); - - const isNotLaunched = !smartClient; - - const renderContent = ( + return ( - {navCollapsed || !isDesktop ? null : ( + {navIsShown ? ( - + - )} + ) : null} ); - - return ( - <> - - {isDesktop && !navCollapsed ? ( - - {renderContent} - - ) : ( - - {renderContent} - - )} - - - ); } export default RendererNav; diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavDrawer.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavDrawer.tsx new file mode 100644 index 000000000..2c220307e --- /dev/null +++ b/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavDrawer.tsx @@ -0,0 +1,78 @@ +/* + * Copyright 2023 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Drawer } from '@mui/material'; +import useConfigStore from '../../../../stores/useConfigStore.ts'; +import { NAV_WIDTH } from '../../../../components/Header/Header.styles.ts'; +import RendererNav from './RendererNav.tsx'; + +interface RendererNavShownProps { + openNav: boolean; + navCollapsed: boolean; + navIsShown: boolean; + onCloseNav: () => void; + setNavCollapsed: () => void; +} + +function RendererNavDrawer(props: RendererNavShownProps) { + const { openNav, navIsShown, onCloseNav, setNavCollapsed } = props; + + const smartClient = useConfigStore((state) => state.smartClient); + + const isNotLaunched = !smartClient; + + if (navIsShown) { + return ( + + + + ); + } + + return ( + + + + ); +} + +export default RendererNavDrawer; diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavWrapper.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavWrapper.tsx new file mode 100644 index 000000000..8bc933cf5 --- /dev/null +++ b/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavWrapper.tsx @@ -0,0 +1,57 @@ +/* + * Copyright 2023 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Box } from '@mui/material'; +import useResponsive from '../../../../hooks/useResponsive.ts'; +import { NAV_WIDTH } from '../../../../components/Header/Header.styles.ts'; +import RendererNavDrawer from './RendererNavDrawer.tsx'; + +interface Props { + openNav: boolean; + navCollapsed: boolean; + onCloseNav: () => void; + setNavCollapsed: () => void; +} + +function RendererNavWrapper(props: Props) { + const { openNav, onCloseNav, navCollapsed, setNavCollapsed } = props; + + const isDesktop = useResponsive('up', 'lg'); + + const navIsShown = isDesktop && !navCollapsed; + + return ( + <> + + + + + ); +} + +export default RendererNavWrapper; diff --git a/apps/smart-forms-app/src/theme/overrides/Overrides.ts b/apps/smart-forms-app/src/theme/overrides/Overrides.ts index 895674d29..82954a7d8 100644 --- a/apps/smart-forms-app/src/theme/overrides/Overrides.ts +++ b/apps/smart-forms-app/src/theme/overrides/Overrides.ts @@ -25,6 +25,7 @@ import Typography from './Typography'; import Autocomplete from './Autocomplete'; import Accordion from './Accordion'; import type { Theme } from '@mui/material'; +import SpeedDial from './SpeedDial.ts'; function ComponentsOverrides(theme: Theme) { return Object.assign( @@ -36,7 +37,8 @@ function ComponentsOverrides(theme: Theme) { Button(theme), Backdrop(theme), Typography(theme), - Autocomplete(theme) + Autocomplete(theme), + SpeedDial(theme) ); } diff --git a/apps/smart-forms-app/src/theme/overrides/SpeedDial.ts b/apps/smart-forms-app/src/theme/overrides/SpeedDial.ts new file mode 100644 index 000000000..1b568b53d --- /dev/null +++ b/apps/smart-forms-app/src/theme/overrides/SpeedDial.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2023 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Theme } from '@mui/material'; + +export default function SpeedDial(theme: Theme) { + return { + MuiSpeedDialAction: { + styleOverrides: { + staticTooltipLabel: { + backgroundColor: theme.palette.grey[600], + color: theme.palette.common.white, + fontSize: theme.typography.subtitle2.fontSize, + fontWeight: theme.typography.subtitle2.fontWeight, + boxShadow: theme.customShadows.z8, + maxWidth: 150, + whiteSpace: 'nowrap' + } + } + } + }; +} From d3f007d9bd75c57af7b106ab166e47134ca43124 Mon Sep 17 00:00:00 2001 From: Sean Fong Date: Tue, 25 Jul 2023 17:28:10 +0930 Subject: [PATCH 4/7] Clean up launch intent related components --- .../src/components/Header/GenericHeader.tsx | 2 +- .../src/components/Header/HeaderIcons.tsx | 8 +++-- .../src/components/Logos/Logo.tsx | 7 ++-- .../Buttons/CreateNewResponseButton.tsx | 2 ++ .../components/RendererEmbeddedSpeedDial.tsx | 9 +++++ .../RendererHeader/RendererHeader.tsx | 33 +++++++++++-------- .../renderer/components/RendererLayout.tsx | 7 +++- .../RendererNav/RendererNavWrapper.tsx | 7 ++-- .../src/stores/useConfigStore.ts | 4 +-- 9 files changed, 54 insertions(+), 25 deletions(-) diff --git a/apps/smart-forms-app/src/components/Header/GenericHeader.tsx b/apps/smart-forms-app/src/components/Header/GenericHeader.tsx index e1a7ebfc5..747212b19 100644 --- a/apps/smart-forms-app/src/components/Header/GenericHeader.tsx +++ b/apps/smart-forms-app/src/components/Header/GenericHeader.tsx @@ -28,7 +28,7 @@ interface DashboardHeaderProps { onOpenNav: () => void; } -const GenericHeader = memo(function DashboardHeader(props: DashboardHeaderProps) { +const GenericHeader = memo(function GenericHeader(props: DashboardHeaderProps) { const { onOpenNav } = props; const isDesktop = useResponsive('up', 'lg'); diff --git a/apps/smart-forms-app/src/components/Header/HeaderIcons.tsx b/apps/smart-forms-app/src/components/Header/HeaderIcons.tsx index 044369956..a3996c16a 100644 --- a/apps/smart-forms-app/src/components/Header/HeaderIcons.tsx +++ b/apps/smart-forms-app/src/components/Header/HeaderIcons.tsx @@ -21,13 +21,17 @@ import { Stack } from '@mui/material'; import { useTheme } from '@mui/material/styles'; import useResponsive from '../../hooks/useResponsive.ts'; -function HeaderIcons() { +interface HeaderIconsProps { + isEmbeddedView?: boolean; +} +function HeaderIcons(props: HeaderIconsProps) { + const { isEmbeddedView } = props; const theme = useTheme(); const isDesktop = useResponsive('up', 'lg'); return ( - {isDesktop ? : } + {isDesktop && !isEmbeddedView ? : } ); } diff --git a/apps/smart-forms-app/src/components/Logos/Logo.tsx b/apps/smart-forms-app/src/components/Logos/Logo.tsx index 36680a05b..827c93b90 100644 --- a/apps/smart-forms-app/src/components/Logos/Logo.tsx +++ b/apps/smart-forms-app/src/components/Logos/Logo.tsx @@ -22,17 +22,20 @@ import useResponsive from '../../hooks/useResponsive.ts'; interface LogoProps { isNav?: boolean; + isEmbeddedView?: boolean; } const Logo = memo(function Logo(props: LogoProps) { - const { isNav } = props; + const { isNav, isEmbeddedView } = props; const isDesktop = useResponsive('up', 'lg'); return ( - {isDesktop || isNav ? Smart Forms : null} + {(isDesktop || isNav) && !isEmbeddedView ? ( + Smart Forms + ) : null} ); }); diff --git a/apps/smart-forms-app/src/features/dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx b/apps/smart-forms-app/src/features/dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx index b8cbc3fc8..9b129e4c6 100644 --- a/apps/smart-forms-app/src/features/dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx +++ b/apps/smart-forms-app/src/features/dashboard/components/DashboardPages/QuestionnairePage/Buttons/CreateNewResponseButton.tsx @@ -61,6 +61,8 @@ function CreateNewResponseButton() { // FIXME this is a hack to test tabs rendering in an embedded browser if (questionnaire.id === 'TestIntentCollapsible') { setLaunchIntent('embedded-browser'); + } else { + setLaunchIntent(null); } navigate('/renderer'); diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererEmbeddedSpeedDial.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererEmbeddedSpeedDial.tsx index bcc9f01d6..1739a4020 100644 --- a/apps/smart-forms-app/src/features/renderer/components/RendererEmbeddedSpeedDial.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/RendererEmbeddedSpeedDial.tsx @@ -31,6 +31,7 @@ import SaveIcon from '@mui/icons-material/Save'; import TaskAltIcon from '@mui/icons-material/TaskAlt'; import { useState } from 'react'; import RendererSaveAsFinalDialog from './RendererNav/SaveAsFinal/RendererSaveAsFinalDialog.tsx'; +import HomeIcon from '@mui/icons-material/Home'; interface RendererEmbeddedSpeedDialProps { isPopulating: boolean; @@ -121,6 +122,14 @@ function RendererEmbeddedSpeedDial(props: RendererEmbeddedSpeedDialProps) { '& .MuiFab-primary': { width: 46, height: 46 } }} icon={}> + } + tooltipTitle="Back to Home (Debug)" + tooltipOpen + onClick={() => { + navigate('/dashboard/questionnaires'); + }} + /> } tooltipTitle="View Responses" diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererHeader/RendererHeader.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererHeader/RendererHeader.tsx index 198e41259..1f315de3c 100644 --- a/apps/smart-forms-app/src/features/renderer/components/RendererHeader/RendererHeader.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/RendererHeader/RendererHeader.tsx @@ -29,35 +29,40 @@ import HeaderIcons from '../../../../components/Header/HeaderIcons.tsx'; interface RendererHeaderProps { navIsCollapsed: boolean; + isEmbeddedView: boolean; onOpenNav: () => void; } const RendererHeader = memo(function RendererHeader(props: RendererHeaderProps) { - const { navIsCollapsed, onOpenNav } = props; + const { navIsCollapsed, isEmbeddedView, onOpenNav } = props; const sourceQuestionnaire = useQuestionnaireStore((state) => state.sourceQuestionnaire); const theme = useTheme(); const isDesktop = useResponsive('up', 'lg'); - const navIsExpanded = !navIsCollapsed; + const navIsExpanded = !navIsCollapsed && !isEmbeddedView; return ( - + - - - + {isEmbeddedView ? null : ( + + + + )} {isDesktop && navIsExpanded ? null : ( - + )} @@ -70,7 +75,7 @@ const RendererHeader = memo(function RendererHeader(props: RendererHeaderProps) - + ); diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererLayout.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererLayout.tsx index a053fb2cc..9289e188d 100644 --- a/apps/smart-forms-app/src/features/renderer/components/RendererLayout.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/RendererLayout.tsx @@ -134,13 +134,18 @@ function RendererLayout() { return ( - setOpen(true)} navIsCollapsed={navIsCollapsed} /> + setOpen(true)} + navIsCollapsed={navIsCollapsed} + isEmbeddedView={isEmbeddedView} + /> setOpen(false)} navCollapsed={navIsCollapsed} setNavCollapsed={() => collapseNav(true)} + isEmbeddedView={isEmbeddedView} />
diff --git a/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavWrapper.tsx b/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavWrapper.tsx index 8bc933cf5..63d13e28a 100644 --- a/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavWrapper.tsx +++ b/apps/smart-forms-app/src/features/renderer/components/RendererNav/RendererNavWrapper.tsx @@ -23,16 +23,17 @@ import RendererNavDrawer from './RendererNavDrawer.tsx'; interface Props { openNav: boolean; navCollapsed: boolean; + isEmbeddedView: boolean; onCloseNav: () => void; setNavCollapsed: () => void; } function RendererNavWrapper(props: Props) { - const { openNav, onCloseNav, navCollapsed, setNavCollapsed } = props; + const { openNav, navCollapsed, isEmbeddedView, onCloseNav, setNavCollapsed } = props; const isDesktop = useResponsive('up', 'lg'); - const navIsShown = isDesktop && !navCollapsed; + const navIsShown = isDesktop && !navCollapsed && !isEmbeddedView; return ( <> @@ -40,7 +41,7 @@ function RendererNavWrapper(props: Props) { component="nav" sx={{ flexShrink: { lg: 0 }, - width: { lg: navCollapsed ? 0 : NAV_WIDTH } + width: { lg: navCollapsed || isEmbeddedView ? 0 : NAV_WIDTH } }}> void; setUser: (user: Practitioner) => void; setEncounter: (encounter: Encounter) => void; - setLaunchIntent: (launchIntent: string) => void; + setLaunchIntent: (launchIntent: string | null) => void; activateDebugMode: () => void; } @@ -28,7 +28,7 @@ const useConfigStore = create()((set) => ({ setPatient: (patient: Patient) => set(() => ({ patient: patient })), setUser: (user: Practitioner) => set(() => ({ user: user })), setEncounter: (encounter: Encounter) => set(() => ({ encounter: encounter })), - setLaunchIntent: (launchIntent: string) => set(() => ({ launchIntent: launchIntent })), + setLaunchIntent: (launchIntent: string | null) => set(() => ({ launchIntent: launchIntent })), activateDebugMode: () => set(() => ({ debugMode: true })) })); From 4e64e885028ab127f5055b7c831010009258ec9d Mon Sep 17 00:00:00 2001 From: Sean Fong Date: Tue, 25 Jul 2023 17:46:03 +0930 Subject: [PATCH 5/7] Add NotFound route --- .../Button/ReauthenticateButton.tsx | 20 ++++++++ .../components/Button/UnlaunchedButton.tsx | 2 +- .../src/features/notfound/NotFound.tsx | 46 +++++++++++++++++++ apps/smart-forms-app/src/router/Router.tsx | 7 ++- 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 apps/smart-forms-app/src/components/Button/ReauthenticateButton.tsx create mode 100644 apps/smart-forms-app/src/features/notfound/NotFound.tsx diff --git a/apps/smart-forms-app/src/components/Button/ReauthenticateButton.tsx b/apps/smart-forms-app/src/components/Button/ReauthenticateButton.tsx new file mode 100644 index 000000000..63b2ac57e --- /dev/null +++ b/apps/smart-forms-app/src/components/Button/ReauthenticateButton.tsx @@ -0,0 +1,20 @@ +import { Button } from '@mui/material'; +import { useNavigate } from 'react-router-dom'; + +function ReauthenticateButton() { + const navigate = useNavigate(); + + return ( + + ); +} + +export default ReauthenticateButton; diff --git a/apps/smart-forms-app/src/components/Button/UnlaunchedButton.tsx b/apps/smart-forms-app/src/components/Button/UnlaunchedButton.tsx index 8768c139f..a465b21cd 100644 --- a/apps/smart-forms-app/src/components/Button/UnlaunchedButton.tsx +++ b/apps/smart-forms-app/src/components/Button/UnlaunchedButton.tsx @@ -8,7 +8,7 @@ function UnlaunchedButton() {