Skip to content

Commit

Permalink
Merge branch 'main' into nic/fix/3461-changes_in_meeting_details_upda…
Browse files Browse the repository at this point in the history
…tes_other_widgets
  • Loading branch information
nurjinjafar authored Sep 22, 2023
2 parents 0d7e625 + 90e1af5 commit 02fa859
Show file tree
Hide file tree
Showing 20 changed files with 1,448 additions and 187 deletions.
5 changes: 5 additions & 0 deletions .changeset/nervous-crabs-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@nordeck/matrix-meetings-widget': minor
---

Support deleting a single occurrence of a recurring meeting.
8 changes: 6 additions & 2 deletions e2e/src/pages/meetingCardPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,17 @@ export class MeetingCardPage {
return new MoreSettingsMenuPage(this.widget.getByRole('menu'));
}

async deleteMeeting() {
async deleteMeeting(buttonLabel: string = 'Delete') {
const menu = await this.openMoreSettingsMenu();
await menu.deleteMenuItem.click();
await this.widget
.getByRole('dialog', { name: 'Delete meeting' })
.getByRole('button', { name: 'Delete' })
.getByRole('button', { name: buttonLabel })
.click();

await this.widget
.getByRole('dialog', { name: 'Delete meeting' })
.waitFor({ state: 'hidden' });
}

async editMeeting(): Promise<ScheduleMeetingWidgetPage> {
Expand Down
37 changes: 35 additions & 2 deletions e2e/src/recurringMeetings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,14 +364,47 @@ test.describe('Recurring Meetings', () => {
await expect(meeting.meetingTimeRangeText).toHaveText(
'10:30 AM – 11:30 AM. Recurrence: Every day for 5 times',
);
await meeting.deleteMeeting();
await meeting.deleteMeeting('Delete series');

await expect(
aliceMeetingsWidgetPage.getMeeting('My Meeting').card,
).toHaveCount(0);
});

// TODO: Delete single meeting
test('should delete a single recurring meeting', async ({
aliceMeetingsWidgetPage,
}) => {
await aliceMeetingsWidgetPage.setDateFilter([2040, 10, 1], [2040, 10, 9]);

const aliceScheduleMeetingWidgetPage =
await aliceMeetingsWidgetPage.scheduleMeeting();

await aliceScheduleMeetingWidgetPage.titleTextbox.fill('My Meeting');
await aliceScheduleMeetingWidgetPage.descriptionTextbox.fill(
'My Description',
);
await aliceScheduleMeetingWidgetPage.setStart([2040, 10, 3], '10:30 AM');
await aliceScheduleMeetingWidgetPage.selectRecurrence('daily');
await aliceScheduleMeetingWidgetPage.setEndAfterMeetingCount(5);
await aliceScheduleMeetingWidgetPage.submit();

const meeting = aliceMeetingsWidgetPage.getMeeting(
'My Meeting',
'10/03/2040',
);
await expect(meeting.meetingTimeRangeText).toHaveText(
'10:30 AM – 11:30 AM. Recurrence: Every day for 5 times',
);
await meeting.deleteMeeting('Delete meeting');

await expect(
aliceMeetingsWidgetPage.getMeeting('My Meeting', '10/03/2040').card,
).toHaveCount(0);

await expect(
aliceMeetingsWidgetPage.getMeeting('My Meeting').card,
).toHaveCount(4);
});

// TODO: Delete starting from
});
6 changes: 3 additions & 3 deletions matrix-meetings-bot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"i18next": "^23.4.5",
"i18next-fs-backend": "^2.1.5",
"i18next-http-middleware": "^3.3.2",
"joi": "^17.10.1",
"joi": "^17.10.2",
"lodash": "^4.17.20",
"luxon": "^3.3.0",
"matrix-bot-sdk": "^0.6.6",
Expand All @@ -61,7 +61,7 @@
"rfc4648": "^1.5.2",
"rrule": "^2.7.2",
"rxjs": "^7.8.0",
"uuid": "^9.0.0"
"uuid": "^9.0.1"
},
"devDependencies": {
"@nestjs/cli": "^10.1.14",
Expand All @@ -72,7 +72,7 @@
"@types/mustache": "^4.2.2",
"@types/node": "^16.18.44",
"@types/node-fetch": "^2.6.4",
"@types/uuid": "^9.0.2",
"@types/uuid": "^9.0.4",
"copyfiles": "^2.4.1",
"depcheck": "^1.4.5",
"dotenv-cli": "^7.3.0",
Expand Down
2 changes: 1 addition & 1 deletion matrix-meetings-widget/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"i18next-chained-backend": "^4.4.0",
"i18next-http-backend": "^2.2.2",
"ical-generator": "^5.0.1",
"joi": "^17.10.1",
"joi": "^17.10.2",
"lodash": "^4.17.20",
"luxon": "^3.3.0",
"matrix-widget-api": "^1.5.0",
Expand Down
8 changes: 3 additions & 5 deletions matrix-meetings-widget/public/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,6 @@
},
"meetingCard": {
"actions": "Aktionen",
"deleteConfirmButton": "Löschen",
"deleteConfirmHeader": "Besprechung löschen",
"deleteConfirmMessage": "Du bist dabei die Besprechung „{{title}}“ am {{startTime, datetime}} und alles darin zu löschen. Bist du sicher?",
"deleteFailed": "Bitte versuche es erneut.",
"deleteFailedTitle": "Fehler beim Löschen der Besprechung",
"deleteInOpenXchangeMenu": "Besprechung in Open-Xchange löschen",
"deleteMenu": "Besprechung löschen",
"durationSubheader_default": "{{startDate, datetime}} – {{endDate, datetime}}",
Expand Down Expand Up @@ -160,7 +155,10 @@
"deleteFailed": "Bitte versuche es erneut.",
"deleteFailedTitle": "Fehler beim Löschen der Besprechung",
"deleteInOpenXchangeMenu": "Besprechung in Open-Xchange löschen",
"deleteMeetingConfirmButton": "Besprechung löschen",
"deleteMenu": "Löschen",
"deleteSeriesConfirmButton": "Besprechungsserie löschen",
"deleteSeriesConfirmMessage": "Du bist dabei die Besprechung oder die Besprechungsserie „{{title}}“ am {{startTime, datetime}} und alles darin zu löschen. Bist du sicher?",
"editInOpenXchangeMenu": "Besprechung in Open-Xchange bearbeiten",
"editMenu": "Bearbeiten",
"join": "Beitreten",
Expand Down
8 changes: 3 additions & 5 deletions matrix-meetings-widget/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,6 @@
},
"meetingCard": {
"actions": "Actions",
"deleteConfirmButton": "Delete",
"deleteConfirmHeader": "Delete meeting",
"deleteConfirmMessage": "Are you sure you want to delete the meeting “{{title}}” on {{startTime, datetime}} and every content related to it?",
"deleteFailed": "Please try again.",
"deleteFailedTitle": "Failed to delete the meeting",
"deleteInOpenXchangeMenu": "Delete meeting in Open-Xchange",
"deleteMenu": "Delete meeting",
"durationSubheader_default": "{{startDate, datetime}} – {{endDate, datetime}}",
Expand Down Expand Up @@ -160,7 +155,10 @@
"deleteFailed": "Please try again.",
"deleteFailedTitle": "Failed to delete the meeting",
"deleteInOpenXchangeMenu": "Delete meeting in Open-Xchange",
"deleteMeetingConfirmButton": "Delete meeting",
"deleteMenu": "Delete",
"deleteSeriesConfirmButton": "Delete series",
"deleteSeriesConfirmMessage": "Are you sure you want to delete the meeting or the meeting series “{{title}}” on {{startTime, datetime}} and every content related to it?",
"editInOpenXchangeMenu": "Edit meeting in Open-Xchange",
"editMenu": "Edit",
"join": "Join",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { render, screen, within } from '@testing-library/react';
import { render, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { axe } from 'jest-axe';
import { ConfirmDeleteDialog } from './ConfirmDeleteDialog';
Expand Down Expand Up @@ -140,4 +140,77 @@ describe('<ConfirmDeleteDialog/>', () => {
expect(onConfirm).not.toBeCalled();
expect(onCancel).toBeCalledTimes(1);
});

it('should render additional buttons', async () => {
render(
<ConfirmDeleteDialog
confirmTitle="Confirm"
description="The description of the modal"
onCancel={onCancel}
onConfirm={onConfirm}
open
title="Confirm the deletion"
additionalButtons={<button>Example</button>}
/>,
);

const deleteModal = screen.getByRole('dialog', {
name: 'Confirm the deletion',
});

expect(
within(deleteModal).getByRole('button', { name: 'Example' }),
).toBeInTheDocument();
});

it('should call onEnter every time the dialog is displayed', async () => {
const onEnter = jest.fn();

const { rerender } = render(
<ConfirmDeleteDialog
open
confirmTitle="Confirm"
description="The description of the modal"
onCancel={onCancel}
onConfirm={onConfirm}
onEnter={onEnter}
title="Confirm the deletion"
/>,
);

expect(screen.getByRole('dialog')).toBeInTheDocument();
expect(onEnter).toBeCalledTimes(1);

rerender(
<ConfirmDeleteDialog
open={false}
confirmTitle="Confirm"
description="The description of the modal"
onCancel={onCancel}
onConfirm={onConfirm}
onEnter={onEnter}
title="Confirm the deletion"
/>,
);

await waitFor(() => {
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
expect(onEnter).toBeCalledTimes(1);

rerender(
<ConfirmDeleteDialog
open
confirmTitle="Confirm"
description="The description of the modal"
onCancel={onCancel}
onConfirm={onConfirm}
onEnter={onEnter}
title="Confirm the deletion"
/>,
);

expect(screen.getByRole('dialog')).toBeInTheDocument();
expect(onEnter).toBeCalledTimes(2);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ import {
DialogTitle,
} from '@mui/material';
import { unstable_useId as useId } from '@mui/utils';
import React, { DispatchWithoutAction, PropsWithChildren } from 'react';
import React, {
DispatchWithoutAction,
PropsWithChildren,
ReactElement,
} from 'react';
import { useTranslation } from 'react-i18next';

type ConfirmDeleteDialogProps = PropsWithChildren<{
Expand All @@ -33,8 +37,10 @@ type ConfirmDeleteDialogProps = PropsWithChildren<{
description: string;
confirmTitle: string;
loading?: boolean;
additionalButtons?: ReactElement;
onCancel: DispatchWithoutAction;
onConfirm: DispatchWithoutAction;
onEnter?: DispatchWithoutAction;
}>;

export function ConfirmDeleteDialog({
Expand All @@ -43,8 +49,10 @@ export function ConfirmDeleteDialog({
description,
confirmTitle,
loading,
additionalButtons,
onCancel,
onConfirm,
onEnter,
children,
}: ConfirmDeleteDialogProps) {
const { t } = useTranslation();
Expand All @@ -58,6 +66,7 @@ export function ConfirmDeleteDialog({
aria-labelledby={dialogTitleId}
onClose={onCancel}
open={open}
onTransitionEnter={onEnter}
>
<DialogTitle id={dialogTitleId}>{title}</DialogTitle>

Expand All @@ -75,6 +84,9 @@ export function ConfirmDeleteDialog({
<Button autoFocus onClick={onCancel} variant="outlined">
{t('cancel', 'Cancel')}
</Button>

{additionalButtons}

<LoadingButton
color="error"
loading={loading}
Expand Down
Loading

0 comments on commit 02fa859

Please sign in to comment.