Skip to content

Commit

Permalink
feat: add validation
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikmv committed Nov 4, 2024
1 parent e39d360 commit 4cd3f98
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 51 deletions.
30 changes: 22 additions & 8 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2024-10-30T12:38:53.423Z\n"
"PO-Revision-Date: 2024-10-30T12:38:53.423Z\n"
"POT-Creation-Date: 2024-11-04T17:57:57.557Z\n"
"PO-Revision-Date: 2024-11-04T17:57:57.557Z\n"

msgid "Choose one or more dates..."
msgstr "Choose one or more dates..."
Expand Down Expand Up @@ -1493,30 +1493,44 @@ msgid "An error occurred while unlinking and deleting the event."
msgstr "An error occurred while unlinking and deleting the event."

msgid ""
"Are you sure you want to unlink and delete the event? This will permanently "
"remove the event and all related data."
"Are you sure you want delete the relationsship and the related event? This "
"will permanently remove the event and all related data."
msgstr ""
"Are you sure you want to unlink and delete the event? This will permanently "
"remove the event and all related data."
"Are you sure you want delete the relationsship and the related event? This "
"will permanently remove the event and all related data."

msgid "Yes, unlink and delete event"
msgstr "Yes, unlink and delete event"

msgid "Unlink relationship"
msgstr "Unlink relationship"

msgid "Are you sure you want to unlink this relationship?"
msgstr "Are you sure you want to unlink this relationship?"
msgid ""
"Are you sure you want to delete the relationship between these two events? "
"This will only delete the relationship, not the other event"
msgstr ""
"Are you sure you want to delete the relationship between these two events? "
"This will only delete the relationship, not the other event"

msgid "Yes, unlink relationship"
msgstr "Yes, unlink relationship"

msgid "View linked event"
msgstr "View linked event"

msgid "You do not have access to remove the relationship between these two events"
msgstr "You do not have access to remove the relationship between these two events"

msgid "Unlink event"
msgstr "Unlink event"

msgid ""
"You do not have access remove the relationship between these two events and "
"delete the other event"
msgstr ""
"You do not have access remove the relationship between these two events and "
"delete the other event"

msgid "Unlink and delete event"
msgstr "Unlink and delete event"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const UnlinkAndDeleteModal = ({
<ModalContent>
<p>
{i18n.t(
'Are you sure you want to unlink and delete the event? This will permanently remove the event and all related data.',
'Are you sure you want delete the relationsship and the related event? This will permanently remove the event and all related data.',
)}
</p>
</ModalContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const UnlinkModal = ({
{i18n.t('Unlink relationship')}
</ModalTitle>
<ModalContent>
<p>{i18n.t('Are you sure you want to unlink this relationship?')}</p>
<p>{i18n.t('Are you sure you want to delete the relationship between these two events? This will only delete the relationship, not the other event')}</p>
</ModalContent>
<ModalActions>
<ButtonStrip end>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,81 +11,100 @@ import {
MenuItem,
} from '@dhis2/ui';
import i18n from '@dhis2/d2-i18n';
import { ConditionalTooltip } from '../../Tooltips/ConditionalTooltip';
import { OverflowButton } from '../../Buttons';
import { UnlinkModal, UnlinkAndDeleteModal } from './Modal';
import { buildUrlQueryString } from '../../../utils/routing';
import type { Props } from './OverflowMenu.types';
import { useRelationshipTypeAccess } from '../hooks';

export const OverflowMenuComponent = ({
linkedEvent,
relationshipId,
orgUnitId,
originEventId,
stageWriteAccess,
relationshipType,
}: Props) => {
const { push } = useHistory();
const [isActionsOpen, setIsActionsOpen] = useState(false);
const [isUnlinkModalOpen, setIsUnlinkModalOpen] = useState(false);
const [isUnlinkAndDeleteModalOpen, setIsUnlinkAndDeleteModalOpen] = useState(false);
const { relationshipTypeWriteAccess } = useRelationshipTypeAccess(relationshipType);

const [actionsIsOpen, setActionsIsOpen] = useState(false);
const [unlinkModalIsOpen, setUnlinkModalIsOpen] = useState(false);
const [unlinkAndDeleteModalIsOpen, setUnlinkAndDeleteModalIsOpen] = useState(false);
const handleViewLinkedEvent = () => {
push(`/enrollmentEventEdit?${buildUrlQueryString({ eventId: linkedEvent.event, orgUnitId })}`);
setIsActionsOpen(false);
};

const handleUnlinkEvent = () => {
setIsUnlinkModalOpen(true);
setIsActionsOpen(false);
};

const handleUnlinkAndDeleteEvent = () => {
setIsUnlinkAndDeleteModalOpen(true);
setIsActionsOpen(false);
};

return (
<>
<OverflowButton
open={actionsIsOpen}
onClick={() => setActionsIsOpen(prev => !prev)}
open={isActionsOpen}
onClick={() => setIsActionsOpen(prev => !prev)}
icon={<IconMore16 />}
small
secondary
dataTest={'widget-linked-event-overflow-menu'}
dataTest="widget-linked-event-overflow-menu"
component={
<FlyoutMenu dense maxWidth="250px">
<MenuItem
label={i18n.t('View linked event')}
icon={<IconView16 />}
dataTest={'event-overflow-view-linked-event'}
onClick={() => {
push(
`/enrollmentEventEdit?${buildUrlQueryString({
eventId: linkedEvent.event,
orgUnitId,
})}`,
);
setActionsIsOpen(false);
}}
dataTest="event-overflow-view-linked-event"
onClick={handleViewLinkedEvent}
/>
<Divider />
<MenuItem
label={i18n.t('Unlink event')}
icon={<IconLink16 />}
dataTest={'event-overflow-unlink-event'}
onClick={() => {
setUnlinkModalIsOpen(true);
setActionsIsOpen(false);
}}
/>
<MenuItem
label={i18n.t('Unlink and delete event')}
icon={<IconDelete16 />}
dataTest={'event-overflow-unlink-and-delete-event'}
destructive
onClick={() => {
setUnlinkAndDeleteModalIsOpen(true);
setActionsIsOpen(false);
}}
/>
<ConditionalTooltip
content={i18n.t('You do not have access to remove the relationship between these two events')}
enabled={!relationshipTypeWriteAccess}
>
<MenuItem
label={i18n.t('Unlink event')}
icon={<IconLink16 />}
disabled={!relationshipTypeWriteAccess}
dense
dataTest="event-overflow-unlink-event"
onClick={handleUnlinkEvent}
/>
</ConditionalTooltip>
<ConditionalTooltip
content={i18n.t('You do not have access remove the relationship between these two events and delete the other event')}
enabled={!stageWriteAccess || !relationshipTypeWriteAccess}
>
<MenuItem
label={i18n.t('Unlink and delete event')}
icon={<IconDelete16 />}
disabled={!stageWriteAccess || !relationshipTypeWriteAccess}
dense
destructive
dataTest="event-overflow-unlink-and-delete-event"
onClick={handleUnlinkAndDeleteEvent}
/>
</ConditionalTooltip>
</FlyoutMenu>
}
/>
{unlinkModalIsOpen && (
{isUnlinkModalOpen && (
<UnlinkModal
setOpenModal={setUnlinkModalIsOpen}
setOpenModal={setIsUnlinkModalOpen}
relationshipId={relationshipId}
originEventId={originEventId}
/>
)}
{unlinkAndDeleteModalIsOpen && (
{isUnlinkAndDeleteModalOpen && (
<UnlinkAndDeleteModal
setOpenModal={setUnlinkAndDeleteModalIsOpen}
setOpenModal={setIsUnlinkAndDeleteModalOpen}
eventId={linkedEvent.event}
originEventId={originEventId}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ export type Props = {
relationshipId: string,
orgUnitId: string,
originEventId: string,
stageWriteAccess: boolean,
relationshipType: string,
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import { withStyles } from '@material-ui/core/';
import type { Props } from './WidgetTwoEventWorkspace.types';
import { useMetadataForProgramStage } from '../DataEntries/common/ProgramStage/useMetadataForProgramStage';
import { Widget } from '../Widget';
import { useLinkedEventByOriginId } from './hooks/useLinkedEventByOriginId';
import { useLinkedEventByOriginId, useClientDataValues } from './hooks';
import { WidgetTwoEventWorkspaceComponent } from './WidgetTwoEventWorkspace.component';
import { OverflowMenuComponent } from './OverflowMenu';
import {
EnrollmentPageKeys,
} from '../Pages/common/EnrollmentOverviewDomain/EnrollmentPageLayout/DefaultEnrollmentLayout.constants';
import { NonBundledDhis2Icon } from '../NonBundledDhis2Icon';
import { useClientDataValues } from './hooks/useClientDataValues';

const styles = {
menu: {
Expand Down Expand Up @@ -50,6 +49,7 @@ const WidgetTwoEventWorkspacePlain = ({
linkedEvent,
relationship,
dataValues,
relationshipType,
isError: isLinkedEventError,
isLoading: isLinkedEventLoading,
} = useLinkedEventByOriginId({ originEventId: eventId });
Expand Down Expand Up @@ -97,8 +97,10 @@ const WidgetTwoEventWorkspacePlain = ({
<OverflowMenuComponent
linkedEvent={linkedEvent}
relationshipId={relationship}
relationshipType={relationshipType}
orgUnitId={orgUnitId}
originEventId={eventId}
stageWriteAccess={stage?.access?.data?.write}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { useClientDataValues } from './useClientDataValues';
export { useLinkedEventByOriginId } from './useLinkedEventByOriginId';
export { useRelationshipTypeAccess } from './useRelationshipTypeAccess';
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @flow
import { useIndexedDBQuery } from '../../../utils/reactQueryHelpers';
import { getUserStorageController } from '../../../storageControllers';
import { userStores } from '../../../storageControllers/stores';

export const useRelationshipTypeAccess = (relationshipTypeId: string) => {
const storageController = getUserStorageController();
console.log('relationshipTypeId', relationshipTypeId);

const { data, error, isLoading } = useIndexedDBQuery(
['relationshipTypeAccess', relationshipTypeId],
() =>
storageController.get(userStores.RELATIONSHIP_TYPES, relationshipTypeId, {
project: ({ access }) => ({
hasWriteAccess: access?.write ?? false,
}),
}),
{
enabled: !!relationshipTypeId,
},
);

return {
relationshipTypeWriteAccess: data?.hasWriteAccess,
isLoading,
error,
};
};
2 changes: 2 additions & 0 deletions src/core_modules/capture-core/dataQueries/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export { useOrganisationUnit } from './useOrganisationUnit';
export { useOrganisationUnits } from './useOrganisationUnits';

export { useOrgUnitAutoSelect } from './useOrgUnitsForAutoSelect';
25 changes: 25 additions & 0 deletions src/core_modules/capture-core/dataQueries/useOrganisationUnits.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// @flow
import { useApiMetadataQuery } from '../utils/reactQueryHelpers';

export const useOrganisationUnits = (customQueryOptions: Object) => {
const queryKey = ['organisationUnits'];
const queryFn = {
resource: 'organisationUnits',
params: {
fields: ['id, displayName~rename(name), path'],
withinUserHierarchy: true,
},
};
const defaultQueryOptions = {
select: ({ organisationUnits }) => organisationUnits,
};

const queryOptions = { ...defaultQueryOptions, ...customQueryOptions };

const { data, isLoading } = useApiMetadataQuery(queryKey, queryFn, queryOptions);

return {
isLoading,
data,
};
};

0 comments on commit 4cd3f98

Please sign in to comment.