Skip to content

Commit fe04654

Browse files
committed
refactor(scheduler): address KBN review feedback for appointments_new
1 parent b6f5f24 commit fe04654

6 files changed

Lines changed: 199 additions & 61 deletions

File tree

packages/devextreme/js/__internal/scheduler/__tests__/appointments_new.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,7 @@ describe('New Appointments', () => {
771771
const appointment = POM.getAppointments()[0];
772772
appointment.element.focus();
773773
fireEvent.keyDown(appointment.element, { key: 'Delete' });
774+
await new Promise(process.nextTick);
774775

775776
expect(POM.getAppointments().length).toBe(0);
776777
});
@@ -792,8 +793,52 @@ describe('New Appointments', () => {
792793
const appointment = POM.getAppointments()[0];
793794
appointment.element.focus();
794795
fireEvent.keyDown(appointment.element, { key: 'Delete' });
796+
await new Promise(process.nextTick);
795797

796798
expect(POM.getAppointments().length).toBe(2);
797799
});
800+
801+
it.each([
802+
{ editing: true },
803+
{ editing: { allowDeleting: true } },
804+
{ editing: { allowDeleting: true, allowUpdating: false } },
805+
])('should delete appointment when editing=$editing', async ({ editing }) => {
806+
const { POM } = await createScheduler({
807+
dataSource: [{
808+
startDate: new Date(2015, 1, 9, 8),
809+
endDate: new Date(2015, 1, 9, 9),
810+
}],
811+
currentDate: new Date(2015, 1, 9, 8),
812+
editing,
813+
});
814+
815+
const appointment = POM.getAppointments()[0];
816+
appointment.element.focus();
817+
fireEvent.keyDown(appointment.element, { key: 'Delete' });
818+
await new Promise(process.nextTick);
819+
820+
expect(POM.getAppointments().length).toBe(0);
821+
});
822+
823+
it.each([
824+
{ editing: { allowDeleting: false } },
825+
{ editing: false },
826+
])('should NOT delete appointment when editing=$editing', async ({ editing }) => {
827+
const { POM } = await createScheduler({
828+
dataSource: [{
829+
startDate: new Date(2015, 1, 9, 8),
830+
endDate: new Date(2015, 1, 9, 9),
831+
}],
832+
currentDate: new Date(2015, 1, 9, 8),
833+
editing,
834+
});
835+
836+
const appointment = POM.getAppointments()[0];
837+
appointment.element.focus();
838+
fireEvent.keyDown(appointment.element, { key: 'Delete' });
839+
await new Promise(process.nextTick);
840+
841+
expect(POM.getAppointments().length).toBe(1);
842+
});
798843
});
799844
});

packages/devextreme/js/__internal/scheduler/appointments_new/appointment/base_appointment.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ export interface BaseAppointmentViewProperties
3838
export class BaseAppointmentView<
3939
TProperties extends BaseAppointmentViewProperties = BaseAppointmentViewProperties,
4040
> extends ViewItem<TProperties> {
41-
get targetedAppointmentData(): TargetedAppointment {
41+
public get targetedAppointmentData(): TargetedAppointment {
4242
return this.option().targetedAppointmentData;
4343
}
4444

45-
get appointmentData(): SafeAppointment {
45+
public get appointmentData(): SafeAppointment {
4646
return this.option().appointmentData;
4747
}
4848

packages/devextreme/js/__internal/scheduler/appointments_new/appointments.focus_controller.ts

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { focus } from '@ts/events/m_short';
55

66
import { getRawAppointmentGroupValues } from '../utils/resource_manager/appointment_groups_utils';
77
import type { SortedEntity } from '../view_model/types';
8+
import type { BaseAppointmentView } from './appointment/base_appointment';
9+
import { AppointmentCollector } from './appointment_collector';
810
import type { Appointments } from './appointments';
911
import type { ViewItem } from './view_item';
1012

@@ -14,7 +16,7 @@ export class AppointmentsFocusController {
1416
private needRestoreFocusIndex = -1;
1517

1618
private get sortedAppointments(): SortedEntity[] {
17-
return this.appointments.option().getSortedAppointments();
19+
return this.appointments.option().getSortedItems();
1820
}
1921

2022
private get isVirtualScrolling(): boolean {
@@ -55,19 +57,19 @@ export class AppointmentsFocusController {
5557
this.handleTabKeyDown(e, viewItem.option().sortedIndex);
5658
break;
5759
case e.key === 'Delete':
58-
this.handleDeleteKeyDown(viewItem.option().sortedIndex);
60+
this.handleDeleteKeyDown(viewItem);
5961
break;
6062
case e.key === 'Home':
61-
this.handleHomeKeyDown();
63+
this.handleHomeKeyDown(e);
6264
break;
6365
case e.key === 'End':
64-
this.handleEndKeyDown();
66+
this.handleEndKeyDown(e);
6567
break;
6668
case e.key === 'Enter':
67-
this.handleEnterKeyDown(viewItem.option().sortedIndex);
69+
this.handleEnterKeyDown(viewItem, e);
6870
break;
6971
case e.key === ' ':
70-
this.handleEnterKeyDown(viewItem.option().sortedIndex);
72+
this.handleEnterKeyDown(viewItem, e);
7173
break;
7274
default:
7375
break;
@@ -108,49 +110,64 @@ export class AppointmentsFocusController {
108110
}
109111

110112
e.originalEvent.preventDefault();
111-
this.focusByItemData(nextItemData);
113+
this.focusBySortedItem(nextItemData);
112114
}
113115

114-
private handleDeleteKeyDown(sortedIndex: number): void {
115-
const { allowDelete, onDeleteKeyPress, getDataAccessor } = this.appointments.option();
116-
if (!allowDelete) { return; }
116+
private handleDeleteKeyDown(viewItem: ViewItem): void {
117+
if (viewItem instanceof AppointmentCollector) { return; }
117118

118-
const entity = this.sortedAppointments[sortedIndex];
119-
if (!entity) { return; }
119+
const { allowDelete, onDeleteKeyPress } = this.appointments.option();
120+
if (!allowDelete) { return; }
120121

121-
const occurrence = { ...entity.itemData };
122-
getDataAccessor().set('startDate', occurrence, new Date(entity.source.startDate));
122+
const sortedItem = this.sortedAppointments[viewItem.option().sortedIndex];
123+
if (!sortedItem) { return; }
123124

124-
onDeleteKeyPress({ appointment: entity.itemData, occurrence });
125+
const appointmentViewItem = viewItem as BaseAppointmentView;
126+
onDeleteKeyPress({
127+
appointmentData: sortedItem.itemData,
128+
targetedAppointmentData: appointmentViewItem.targetedAppointmentData,
129+
});
125130
}
126131

127-
private handleHomeKeyDown(): void {
128-
const firstAppointment = this.sortedAppointments[0];
129-
if (firstAppointment) { this.focusByItemData(firstAppointment); }
132+
private handleHomeKeyDown(e: KeyboardKeyDownEvent): void {
133+
const firstSortedItem = this.sortedAppointments[0];
134+
if (firstSortedItem) {
135+
e.originalEvent.preventDefault();
136+
this.focusBySortedItem(firstSortedItem);
137+
}
130138
}
131139

132-
private handleEndKeyDown(): void {
133-
const lastAppointment = this.sortedAppointments[this.sortedAppointments.length - 1];
134-
if (lastAppointment) { this.focusByItemData(lastAppointment); }
140+
private handleEndKeyDown(e: KeyboardKeyDownEvent): void {
141+
const lastSortedItem = this.sortedAppointments[this.sortedAppointments.length - 1];
142+
if (lastSortedItem) {
143+
e.originalEvent.preventDefault();
144+
this.focusBySortedItem(lastSortedItem);
145+
}
135146
}
136147

137-
private handleEnterKeyDown(sortedIndex: number): void {
148+
private handleEnterKeyDown(viewItem: ViewItem, e: KeyboardKeyDownEvent): void {
138149
const { onItemActivate } = this.appointments.option();
139-
const entity = this.sortedAppointments[sortedIndex];
140-
onItemActivate({ data: entity?.itemData, target: null });
150+
const sortedItem = this.sortedAppointments[viewItem.option().sortedIndex];
151+
if (!sortedItem) { return; }
152+
e.originalEvent.preventDefault();
153+
const appointmentViewItem = viewItem as BaseAppointmentView;
154+
onItemActivate({
155+
data: sortedItem.itemData,
156+
targetedAppointmentData: appointmentViewItem.targetedAppointmentData,
157+
});
141158
}
142159

143-
private focusByItemData(itemData: SortedEntity): void {
160+
private focusBySortedItem(sortedItem: SortedEntity): void {
144161
if (this.isVirtualScrolling) {
145-
this.scrollToItem(itemData);
162+
this.scrollToItem(sortedItem);
146163
}
147164

148-
const viewItem = this.appointments.getViewItemBySortedIndex(itemData.sortedIndex);
165+
const viewItem = this.appointments.getViewItemBySortedIndex(sortedItem.sortedIndex);
149166

150167
if (viewItem) {
151168
this.focusViewItem(viewItem);
152169
} else if (this.isVirtualScrolling) {
153-
this.needRestoreFocusIndex = itemData.sortedIndex;
170+
this.needRestoreFocusIndex = sortedItem.sortedIndex;
154171
}
155172
}
156173

@@ -159,19 +176,19 @@ export class AppointmentsFocusController {
159176
focus.trigger(viewItem?.$element());
160177
}
161178

162-
private scrollToItem(itemData: SortedEntity): void {
179+
private scrollToItem(sortedItem: SortedEntity): void {
163180
const { getStartViewDate, getResourceManager, scrollTo } = this.appointments.option();
164181

165182
const date = new Date(Math.max(
166183
getStartViewDate().getTime(),
167-
itemData.source.startDate,
184+
sortedItem.source.startDate,
168185
));
169186

170187
const group = getRawAppointmentGroupValues(
171-
itemData.itemData,
188+
sortedItem.itemData,
172189
getResourceManager().resources,
173190
);
174191

175-
scrollTo(date, { group, allDay: itemData.allDay });
192+
scrollTo(date, { group, allDay: sortedItem.allDay });
176193
}
177194
}

0 commit comments

Comments
 (0)