Skip to content

Commit 016df42

Browse files
authored
Scheduler: add today built-in button (DevExpress#29447)
Co-authored-by: Vladimir Bushmanov <[email protected]>
1 parent 6f1c0ef commit 016df42

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+187
-71
lines changed

e2e/testcafe-devextreme/tests/scheduler/common/header/customization.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,31 @@ const customToolbarItems = [
3131
test('Scheduler default toolbar should works', async (t) => {
3232
const scheduler = new Scheduler('#container');
3333

34-
await t.expect(await compareScreenshot(t, 'scheduler-default toolbar.png', scheduler.element)).ok();
34+
await t.expect(await compareScreenshot(t, 'scheduler-default toolbar.png', scheduler.toolbar.element)).ok();
3535
}).before(async () => createWidget('dxScheduler', {
36-
views: ['day', 'week', 'workWeek', 'month'],
37-
currentView: 'workWeek',
3836
currentDate: new Date(2021, 3, 27),
39-
height: 200,
37+
}));
38+
39+
test('Scheduler toolbar should be hided', async (t) => {
40+
const scheduler = new Scheduler('#container');
41+
42+
await t.expect(scheduler.toolbar.element.exists).notOk();
43+
}).before(async () => createWidget('dxScheduler', {
44+
currentDate: new Date(2021, 3, 27),
45+
toolbar: { visible: false },
4046
}));
4147

4248
[
4349
{ toolbar: { items: customToolbarItems }, description: 'custom toolbar' },
44-
{ toolbar: { visible: false }, description: 'hided toolbar' },
50+
{ toolbar: { items: ['today', 'dateNavigator', 'viewSwitcher'] }, description: 'toolbar with today' },
4551
{ toolbar: { disabled: true, items: customToolbarItems }, description: 'disabled toolbar' },
4652
].forEach(({ toolbar, description }) => {
4753
test(`Scheduler ${description} should works`, async (t) => {
4854
const scheduler = new Scheduler('#container');
4955

50-
await t.expect(await compareScreenshot(t, `scheduler-${description}.png`, scheduler.element)).ok();
56+
await t.expect(await compareScreenshot(t, `scheduler-${description}.png`, scheduler.toolbar.element)).ok();
5157
}).before(async () => createWidget('dxScheduler', {
52-
views: ['day', 'week', 'workWeek', 'month'],
53-
currentView: 'workWeek',
5458
currentDate: new Date(2021, 3, 27),
55-
height: 200,
5659
toolbar,
5760
}));
5861
});
-10.8 KB
Loading
-10.8 KB
Loading
-10.8 KB
Loading
5.89 KB
Loading
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import Scheduler from 'devextreme-testcafe-models/scheduler';
2+
import { createWidget } from '../../../../helpers/createWidget';
3+
import url from '../../../../helpers/getPageUrl';
4+
5+
fixture.disablePageReloads`Scheduler header today button`
6+
.page(url(__dirname, '../../../container.html'));
7+
8+
test('Scheduler today button should works', async (t) => {
9+
const scheduler = new Scheduler('#container');
10+
11+
await t.click(scheduler.toolbar.todayButton);
12+
13+
const currentDate = await scheduler.option('currentDate') as Date;
14+
const today = new Date();
15+
16+
currentDate.setHours(0, 0, 0, 0);
17+
today.setHours(0, 0, 0, 0);
18+
19+
await t.expect(currentDate).eql(today);
20+
}).before(async () => createWidget('dxScheduler', {
21+
currentDate: new Date(2021, 3, 27),
22+
toolbar: { items: ['today', 'dateNavigator', 'viewSwitcher'] },
23+
}));
24+
25+
const indicatorTime = new Date(2023, 3, 27);
26+
27+
test('Scheduler today button should use indicatorTime', async (t) => {
28+
const scheduler = new Scheduler('#container');
29+
30+
await t
31+
.click(scheduler.toolbar.todayButton)
32+
.expect(scheduler.option('currentDate'))
33+
.eql(indicatorTime);
34+
}).before(async () => createWidget('dxScheduler', {
35+
currentDate: new Date(2021, 3, 27),
36+
indicatorTime,
37+
toolbar: { items: ['today', 'dateNavigator', 'viewSwitcher'] },
38+
}));
Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,4 @@
1-
// DateNavigator
21
export enum Direction {
32
Left = -1,
43
Right = 1,
54
}
6-
7-
export const DATE_NAVIGATOR_CLASS = 'dx-scheduler-navigator';
8-
9-
export const PREVIOUS_BUTTON_CLASS = 'dx-scheduler-navigator-previous';
10-
export const CALENDAR_BUTTON_CLASS = 'dx-scheduler-navigator-caption';
11-
export const NEXT_BUTTON_CLASS = 'dx-scheduler-navigator-next';
12-
13-
export const PREVIOUS_BUTTON_NAME = 'prev';
14-
export const NEXT_BUTTON_NAME = 'next';
15-
export const CALENDAR_BUTTON_NAME = 'dateInterval';
16-
export const DEFAULT_ITEMS = [PREVIOUS_BUTTON_NAME, NEXT_BUTTON_NAME, CALENDAR_BUTTON_NAME];

packages/devextreme/js/__internal/scheduler/header/m_date_navigator.test.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ import {
33
} from '@jest/globals';
44

55
import {
6-
CALENDAR_BUTTON_NAME, DATE_NAVIGATOR_CLASS, DEFAULT_ITEMS, NEXT_BUTTON_NAME,
7-
} from './constants';
8-
import { getDateNavigator } from './m_date_navigator';
6+
CLASS, DEFAULT_ITEMS, getDateNavigator, ITEMS_NAME,
7+
} from './m_date_navigator';
98

109
describe('getDateNavigator', () => {
1110
it('should return default options in case of item is empty', () => {
1211
expect(getDateNavigator({} as any, {})).toEqual({
12+
location: 'before',
13+
name: 'dateNavigator',
1314
widget: 'dxButtonGroup',
14-
cssClass: DATE_NAVIGATOR_CLASS,
15+
cssClass: CLASS.container,
1516
options: {
1617
stylingMode: 'contained',
1718
selectionMode: 'none',
@@ -31,17 +32,19 @@ describe('getDateNavigator', () => {
3132
customOption: 'customOption',
3233
items: ['dateInterval', 'next', { key: 'customButton' }],
3334
},
34-
})).toEqual({
35+
} as any)).toEqual({
36+
location: 'before',
37+
name: 'dateNavigator',
3538
widget: 'dxButtonGroup',
36-
cssClass: DATE_NAVIGATOR_CLASS,
39+
cssClass: CLASS.container,
3740
customField: 'customField',
3841
options: {
3942
stylingMode: 'contained',
4043
selectionMode: 'none',
4144
customOption: 'customOption',
4245
items: [
43-
expect.objectContaining({ key: CALENDAR_BUTTON_NAME }),
44-
expect.objectContaining({ key: NEXT_BUTTON_NAME }),
46+
expect.objectContaining({ key: ITEMS_NAME.calendarButton }),
47+
expect.objectContaining({ key: ITEMS_NAME.nextButton }),
4548
expect.objectContaining({ key: 'customButton' }),
4649
],
4750
onItemClick: expect.any(Function),
@@ -60,8 +63,10 @@ describe('getDateNavigator', () => {
6063
expect(customClick).toHaveBeenCalledWith(event);
6164
expect(event.itemData.clickHandler).toHaveBeenCalledWith(event);
6265
expect(config).toEqual({
66+
location: 'before',
67+
name: 'dateNavigator',
6368
widget: 'dxButtonGroup',
64-
cssClass: DATE_NAVIGATOR_CLASS,
69+
cssClass: CLASS.container,
6570
options: {
6671
stylingMode: 'contained',
6772
selectionMode: 'none',

packages/devextreme/js/__internal/scheduler/header/m_date_navigator.ts

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,24 @@ import { dateUtilsTs } from '@ts/core/utils/date';
88
import { extend } from '@ts/core/utils/m_extend';
99
import type { SchedulerHeader } from '@ts/scheduler/header/m_header';
1010

11-
import {
12-
CALENDAR_BUTTON_CLASS,
13-
CALENDAR_BUTTON_NAME,
14-
DATE_NAVIGATOR_CLASS,
15-
DEFAULT_ITEMS,
16-
Direction,
17-
NEXT_BUTTON_CLASS,
18-
NEXT_BUTTON_NAME,
19-
PREVIOUS_BUTTON_CLASS,
20-
PREVIOUS_BUTTON_NAME,
21-
} from './constants';
11+
import { Direction } from './constants';
12+
13+
export const CLASS = {
14+
container: 'dx-scheduler-navigator',
15+
previousButton: 'dx-scheduler-navigator-previous',
16+
calendarButton: 'dx-scheduler-navigator-caption',
17+
nextButton: 'dx-scheduler-navigator-next',
18+
};
19+
export const ITEMS_NAME = {
20+
previousButton: 'prev',
21+
nextButton: 'next',
22+
calendarButton: 'dateInterval',
23+
};
24+
export const DEFAULT_ITEMS = [
25+
ITEMS_NAME.previousButton,
26+
ITEMS_NAME.nextButton,
27+
ITEMS_NAME.calendarButton,
28+
];
2229

2330
const { trimTime } = dateUtils;
2431

@@ -60,10 +67,10 @@ const getPreviousButtonOptions = (header: SchedulerHeader): DateNavigatorItem =>
6067
const ariaMessage = messageLocalization.format('dxScheduler-navigationPrevious');
6168

6269
return {
63-
key: PREVIOUS_BUTTON_NAME,
70+
key: ITEMS_NAME.previousButton,
6471
icon: 'chevronprev',
6572
elementAttr: {
66-
class: PREVIOUS_BUTTON_CLASS,
73+
class: CLASS.previousButton,
6774
'aria-label': ariaMessage,
6875
},
6976
clickHandler: () => header._updateDateByDirection(Direction.Left),
@@ -87,9 +94,9 @@ const getPreviousButtonOptions = (header: SchedulerHeader): DateNavigatorItem =>
8794
};
8895

8996
const getCalendarButtonOptions = (header: SchedulerHeader): DateNavigatorItem => ({
90-
key: CALENDAR_BUTTON_NAME,
97+
key: ITEMS_NAME.calendarButton,
9198
text: header.captionText,
92-
elementAttr: { class: CALENDAR_BUTTON_CLASS },
99+
elementAttr: { class: CLASS.calendarButton },
93100
clickHandler: (event) => header._showCalendar(event),
94101
onContentReady: (event): void => {
95102
const calendarButton = event.component;
@@ -120,10 +127,10 @@ const getNextButtonOptions = (header: SchedulerHeader): DateNavigatorItem => {
120127
const ariaMessage = messageLocalization.format('dxScheduler-navigationNext');
121128

122129
return {
123-
key: NEXT_BUTTON_NAME,
130+
key: ITEMS_NAME.nextButton,
124131
icon: 'chevronnext',
125132
elementAttr: {
126-
class: NEXT_BUTTON_CLASS,
133+
class: CLASS.nextButton,
127134
'aria-label': ariaMessage,
128135
},
129136
clickHandler: () => header._updateDateByDirection(Direction.Right),
@@ -147,12 +154,14 @@ const getNextButtonOptions = (header: SchedulerHeader): DateNavigatorItem => {
147154
};
148155
};
149156

150-
export const getDateNavigator = (header: SchedulerHeader, item): ToolbarItem => {
151-
// @ts-expect-error
157+
export const getDateNavigator = (header: SchedulerHeader, item: ToolbarItem): ToolbarItem => {
158+
// @ts-expect-error current theme used
152159
const stylingMode = isMaterialBased() ? 'text' : 'contained';
153160
const config: ToolbarItem = extend(true, {}, {
161+
location: 'before',
162+
name: 'dateNavigator',
154163
widget: 'dxButtonGroup',
155-
cssClass: DATE_NAVIGATOR_CLASS,
164+
cssClass: CLASS.container,
156165
options: {
157166
stylingMode,
158167
selectionMode: 'none',
@@ -163,11 +172,11 @@ export const getDateNavigator = (header: SchedulerHeader, item): ToolbarItem =>
163172

164173
options.items = (options.items ?? DEFAULT_ITEMS).map((groupItem) => {
165174
switch (groupItem) {
166-
case PREVIOUS_BUTTON_NAME:
175+
case ITEMS_NAME.previousButton:
167176
return getPreviousButtonOptions(header);
168-
case NEXT_BUTTON_NAME:
177+
case ITEMS_NAME.nextButton:
169178
return getNextButtonOptions(header);
170-
case CALENDAR_BUTTON_NAME:
179+
case ITEMS_NAME.calendarButton:
171180
return getCalendarButtonOptions(header);
172181
default:
173182
return groupItem;

packages/devextreme/js/__internal/scheduler/header/m_header.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ import {
3131
getDropDownViewSwitcher,
3232
getTabViewSwitcher,
3333
} from './m_view_switcher';
34+
import { getTodayButtonOptions } from './today';
3435

3536
const COMPONENT_CLASS = 'dx-scheduler-header';
36-
const DATE_NAVIGATOR_NAME = 'dateNavigator';
37-
const VIEW_SWITCHER_NAME = 'viewSwitcher';
38-
const TOOLBAR_ITEMS_MAP = {
39-
[DATE_NAVIGATOR_NAME]: { location: 'before', name: 'dateNavigator' },
40-
[VIEW_SWITCHER_NAME]: { location: 'after', name: 'viewSwitcher' },
37+
const ITEM_NAMES = {
38+
today: 'today',
39+
dateNavigator: 'dateNavigator',
40+
viewSwitcher: 'viewSwitcher',
4141
};
4242

4343
export class SchedulerHeader extends Widget<dxSchedulerOptions> {
@@ -91,6 +91,7 @@ export class SchedulerHeader extends Widget<dxSchedulerOptions> {
9191
['tabIndex', [this.repaint.bind(this)]],
9292
['focusStateEnabled', [this.repaint.bind(this)]],
9393
['useDropDownViewSwitcher', [this.repaint.bind(this)]],
94+
['indicatorTime', []],
9495
],
9596
);
9697
}
@@ -184,15 +185,17 @@ export class SchedulerHeader extends Widget<dxSchedulerOptions> {
184185

185186
_parseItem(item) {
186187
const itemName = typeof item === 'string' ? item : item.name;
187-
const itemOptions = { ...TOOLBAR_ITEMS_MAP[itemName], ...item };
188+
const itemOptions = typeof item === 'string' ? {} : item;
188189

189190
if (itemName) {
190191
switch (itemName) {
191-
case VIEW_SWITCHER_NAME:
192+
case ITEM_NAMES.today:
193+
return getTodayButtonOptions(this, itemOptions);
194+
case ITEM_NAMES.viewSwitcher:
192195
return this.option('useDropDownViewSwitcher')
193196
? getDropDownViewSwitcher(this, itemOptions)
194197
: getTabViewSwitcher(this, itemOptions);
195-
case DATE_NAVIGATOR_NAME:
198+
case ITEM_NAMES.dateNavigator:
196199
this._renderCalendar();
197200

198201
return getDateNavigator(this, itemOptions);

0 commit comments

Comments
 (0)