Skip to content

Commit 573c6ff

Browse files
committed
feat: enhance event edit permissions and streamline delete action handling
1 parent 25ff87e commit 573c6ff

4 files changed

Lines changed: 34 additions & 89 deletions

File tree

i18n/en.pot

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ msgstr ""
55
"Content-Type: text/plain; charset=utf-8\n"
66
"Content-Transfer-Encoding: 8bit\n"
77
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
8-
"POT-Creation-Date: 2026-08-14T17:05:09.479Z\n"
9-
"PO-Revision-Date: 2026-08-14T17:05:09.479Z\n"
8+
"POT-Creation-Date: 2026-08-14T19:00:38.850Z\n"
9+
"PO-Revision-Date: 2026-08-14T19:00:38.851Z\n"
1010

1111
msgid "The application could not be loaded."
1212
msgstr "The application could not be loaded."
@@ -461,15 +461,6 @@ msgstr "Are you sure you want to delete this event?"
461461
msgid "Yes, delete event"
462462
msgstr "Yes, delete event"
463463

464-
msgid "{{occurredAt}} belongs to an expired period. Event cannot be deleted"
465-
msgstr "{{occurredAt}} belongs to an expired period. Event cannot be deleted"
466-
467-
msgid "This event has been completed"
468-
msgstr "This event has been completed"
469-
470-
msgid "This event is outside the edit period"
471-
msgstr "This event is outside the edit period"
472-
473464
msgid "Delete"
474465
msgstr "Delete"
475466

@@ -1128,6 +1119,9 @@ msgstr "You only have view access to this program stage"
11281119
msgid "This event is outside the editing period"
11291120
msgstr "This event is outside the editing period"
11301121

1122+
msgid "This event has been completed"
1123+
msgstr "This event has been completed"
1124+
11311125
msgid "This {{trackedEntityName}} is deactivated"
11321126
msgstr "This {{trackedEntityName}} is deactivated"
11331127

@@ -1962,6 +1956,9 @@ msgstr "Program stage name"
19621956
msgid "Working list could not be loaded"
19631957
msgstr "Working list could not be loaded"
19641958

1959+
msgid "{{occurredAt}} belongs to an expired period. Event cannot be deleted"
1960+
msgstr "{{occurredAt}} belongs to an expired period. Event cannot be deleted"
1961+
19651962
msgid "Download data..."
19661963
msgstr "Download data..."
19671964

src/core_modules/capture-core/components/EventOverflowMenu/MenuItems/DeleteMenuItem.tsx

Lines changed: 13 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,25 @@ import {
55
IconDelete16,
66
MenuItem,
77
} from '@dhis2/ui';
8-
import { ConditionalTooltip } from '../../Tooltips/ConditionalTooltip';
9-
import { convertClientToView, convertServerToClient } from '../../../converters';
10-
import { dataElementTypes, type ProgramStage } from '../../../metaData';
11-
import { useEventEditPermissions, useProgramExpiryForUser } from '../../../hooks';
12-
import { isValidPeriod } from '../../../utils/validation/validators/form';
138

149
type Props = {
1510
setActionsOpen: (open: boolean) => void;
1611
setDeleteModalOpen: (open: boolean) => void;
17-
occurredAt: string;
18-
completedAt?: string;
19-
eventStatus?: string;
20-
programId: string;
21-
programStage?: ProgramStage | null;
2212
};
2313

2414
export const DeleteActionButton = ({
2515
setActionsOpen,
2616
setDeleteModalOpen,
27-
occurredAt,
28-
completedAt,
29-
eventStatus,
30-
programId,
31-
programStage,
32-
}: Props) => {
33-
const occurredAtClient = convertServerToClient(occurredAt, dataElementTypes.DATE) as string;
34-
const occurredAtClientView = convertClientToView(occurredAtClient, dataElementTypes.DATE);
35-
const expiryPeriod = useProgramExpiryForUser(programId);
36-
const { isWithinValidPeriod: isEventWithinValidPeriod } = isValidPeriod(occurredAtClient, expiryPeriod ?? null);
37-
38-
const {
39-
isFormBlockedByCompletion,
40-
isEventReadOnly,
41-
} = useEventEditPermissions({
42-
programId,
43-
stage: programStage,
44-
eventStatus,
45-
occurredAtClient,
46-
completedAtClient: convertServerToClient(completedAt, dataElementTypes.DATE) as string,
47-
});
48-
49-
const getDisabledMessage = (): string => {
50-
if (!isEventWithinValidPeriod) {
51-
return i18n.t('{{occurredAt}} belongs to an expired period. Event cannot be deleted', {
52-
occurredAt: occurredAtClientView,
53-
interpolation: { escapeValue: false },
54-
});
55-
}
56-
if (isFormBlockedByCompletion) {
57-
return i18n.t('This event has been completed');
58-
}
59-
return i18n.t('This event is outside the edit period');
60-
};
61-
62-
return (
63-
<ConditionalTooltip
64-
content={getDisabledMessage()}
65-
enabled={isEventReadOnly}
66-
>
67-
<MenuItem
68-
dense
69-
disabled={isEventReadOnly}
70-
icon={<IconDelete16 color={colors.red600} />}
71-
label={i18n.t('Delete')}
72-
dataTest="stages-and-events-delete"
73-
onClick={() => {
74-
setDeleteModalOpen(true);
75-
setActionsOpen(false);
76-
}}
77-
suffix=""
78-
/>
79-
</ConditionalTooltip>
80-
);
81-
};
17+
}: Props) => (
18+
<MenuItem
19+
dense
20+
icon={<IconDelete16 color={colors.red600} />}
21+
label={i18n.t('Delete')}
22+
dataTest="stages-and-events-delete"
23+
onClick={() => {
24+
setDeleteModalOpen(true);
25+
setActionsOpen(false);
26+
}}
27+
suffix=""
28+
/>
29+
);

src/core_modules/capture-core/components/WidgetStagesAndEvents/Stages/Stage/StageDetail/EventRow/EventRow.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
rollbackEnrollmentEvent,
2323
} from '../../../../../Pages/common/EnrollmentOverviewDomain';
2424

25+
2526
const styles: Readonly<any> = {
2627
row: {
2728
maxWidth: '100%',
@@ -34,6 +35,9 @@ const styles: Readonly<any> = {
3435
},
3536
};
3637

38+
const isSkippableStatus = (status?: string) =>
39+
status === eventStatuses.SCHEDULE || status === eventStatuses.SKIPPED;
40+
3741
const EventRowPlain = ({
3842
id,
3943
pendingApiResponse,
@@ -51,7 +55,7 @@ const EventRowPlain = ({
5155
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
5256
const dispatch = useDispatch();
5357

54-
const { canUncompleteEvent } = useEventEditPermissions({
58+
const { canUncompleteEvent, isEventReadOnly } = useEventEditPermissions({
5559
programId,
5660
stage: programStage,
5761
eventStatus: eventDetails.status,
@@ -82,9 +86,9 @@ const EventRowPlain = ({
8286
<DataTableCell>
8387
{stageWriteAccess && (
8488
<>
85-
{pendingApiResponse ? (
86-
<CircularLoader small dataTest={'event-row-saving-loader'} />
87-
) : (
89+
{pendingApiResponse && <CircularLoader small dataTest={'event-row-saving-loader'} />}
90+
91+
{!pendingApiResponse && (!isEventReadOnly || canUncompleteEvent) && (
8892
<OverflowButton
8993
open={actionsOpen}
9094
onClick={() => setActionsOpen(prev => !prev)}
@@ -97,8 +101,7 @@ const EventRowPlain = ({
97101
dense
98102
dataTest={'overflow-menu'}
99103
>
100-
{(eventDetails.status === eventStatuses.SCHEDULE ||
101-
eventDetails.status === eventStatuses.SKIPPED) && (
104+
{isSkippableStatus(eventDetails.status) && (
102105
<SkipAction
103106
eventId={id}
104107
eventDetails={eventDetails}
@@ -122,11 +125,6 @@ const EventRowPlain = ({
122125
<DeleteActionButton
123126
setActionsOpen={setActionsOpen}
124127
setDeleteModalOpen={setDeleteModalOpen}
125-
occurredAt={eventDetails.occurredAt}
126-
completedAt={eventDetails.completedAt}
127-
eventStatus={eventDetails.status}
128-
programId={programId}
129-
programStage={programStage}
130128
/>
131129
</FlyoutMenu>
132130
)}

src/core_modules/capture-core/hooks/useEventEditPermissions.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const useEventEditPermissions = ({
4040
const isWithinCompleteExpiry = isWithinCompleteEventsExpiry(completedAtClient, completeEventsExpiryDays);
4141
const isExpired = !isWithinValidPeriod || !isWithinCompleteExpiry;
4242

43-
const isFormBlockedByCompletion = !!(stage?.blockEntryForm && eventStatus === eventStatuses.COMPLETED);
43+
const isCompletedAndBlockingForm = !!(stage?.blockEntryForm && eventStatus === eventStatuses.COMPLETED);
4444
const isEventBlockedByExpiry = isExpired && !hasEditExpiredAuthority;
4545

4646
const canUncompleteEvent = computeCanChangeCompletionStatus({
@@ -51,9 +51,11 @@ export const useEventEditPermissions = ({
5151
hasEditExpiredAuthority,
5252
});
5353

54+
const isFormBlockedByCompletion = isCompletedAndBlockingForm;
55+
5456
const isEventReadOnly = !eventAccess?.write
5557
|| isEventBlockedByExpiry
56-
|| isFormBlockedByCompletion;
58+
|| isCompletedAndBlockingForm;
5759

5860
return {
5961
isEventBlockedByExpiry,

0 commit comments

Comments
 (0)