Skip to content

Commit b1370cf

Browse files
Scheduler - Add CreateFromSelection demo, touch fix, declarations
1 parent 5ee32cb commit b1370cf

File tree

7 files changed

+366
-2
lines changed

7 files changed

+366
-2
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
const data = [
2+
{
3+
text: 'Website Re-Design Plan',
4+
priorityId: 2,
5+
startDate: new Date('2021-04-19T16:30:00.000Z'),
6+
endDate: new Date('2021-04-19T18:30:00.000Z'),
7+
}, {
8+
text: 'Book Flights to San Fran for Sales Trip',
9+
priorityId: 1,
10+
startDate: new Date('2021-04-22T17:00:00.000Z'),
11+
endDate: new Date('2021-04-22T19:00:00.000Z'),
12+
}, {
13+
text: 'Install New Router in Dev Room',
14+
priorityId: 1,
15+
startDate: new Date('2021-04-19T20:00:00.000Z'),
16+
endDate: new Date('2021-04-19T22:30:00.000Z'),
17+
}, {
18+
text: 'Approve Personal Computer Upgrade Plan',
19+
priorityId: 2,
20+
startDate: new Date('2021-04-20T17:00:00.000Z'),
21+
endDate: new Date('2021-04-20T18:00:00.000Z'),
22+
}, {
23+
text: 'Final Budget Review',
24+
priorityId: 2,
25+
startDate: new Date('2021-04-20T19:00:00.000Z'),
26+
endDate: new Date('2021-04-20T20:35:00.000Z'),
27+
}, {
28+
text: 'New Brochures',
29+
priorityId: 2,
30+
startDate: new Date('2021-04-19T20:00:00.000Z'),
31+
endDate: new Date('2021-04-19T22:15:00.000Z'),
32+
}, {
33+
text: 'Install New Database',
34+
priorityId: 1,
35+
startDate: new Date('2021-04-20T16:00:00.000Z'),
36+
endDate: new Date('2021-04-20T19:15:00.000Z'),
37+
}, {
38+
text: 'Approve New Online Marketing Strategy',
39+
priorityId: 2,
40+
startDate: new Date('2021-04-21T19:00:00.000Z'),
41+
endDate: new Date('2021-04-21T21:00:00.000Z'),
42+
}, {
43+
text: 'Upgrade Personal Computers',
44+
priorityId: 1,
45+
startDate: new Date('2021-04-19T16:00:00.000Z'),
46+
endDate: new Date('2021-04-19T18:30:00.000Z'),
47+
}, {
48+
text: 'Prepare 2021 Marketing Plan',
49+
priorityId: 2,
50+
startDate: new Date('2021-04-22T18:00:00.000Z'),
51+
endDate: new Date('2021-04-22T20:30:00.000Z'),
52+
}, {
53+
text: 'Brochure Design Review',
54+
priorityId: 1,
55+
startDate: new Date('2021-04-21T18:00:00.000Z'),
56+
endDate: new Date('2021-04-21T20:30:00.000Z'),
57+
}, {
58+
text: 'Create Icons for Website',
59+
priorityId: 2,
60+
startDate: new Date('2021-04-23T17:00:00.000Z'),
61+
endDate: new Date('2021-04-23T18:30:00.000Z'),
62+
}, {
63+
text: 'Upgrade Server Hardware',
64+
priorityId: 1,
65+
startDate: new Date('2021-04-23T16:00:00.000Z'),
66+
endDate: new Date('2021-04-23T22:00:00.000Z'),
67+
}, {
68+
text: 'Submit New Website Design',
69+
priorityId: 2,
70+
startDate: new Date('2021-04-23T23:30:00.000Z'),
71+
endDate: new Date('2021-04-24T01:00:00.000Z'),
72+
}, {
73+
text: 'Launch New Website',
74+
priorityId: 2,
75+
startDate: new Date('2021-04-23T19:20:00.000Z'),
76+
endDate: new Date('2021-04-23T21:00:00.000Z'),
77+
}, {
78+
text: 'Google AdWords Strategy',
79+
priorityId: 1,
80+
startDate: new Date('2021-04-26T16:00:00.000Z'),
81+
endDate: new Date('2021-04-26T19:00:00.000Z'),
82+
}, {
83+
text: 'Rollout of New Website and Marketing Brochures',
84+
priorityId: 1,
85+
startDate: new Date('2021-04-26T20:00:00.000Z'),
86+
endDate: new Date('2021-04-26T22:30:00.000Z'),
87+
}, {
88+
text: 'Non-Compete Agreements',
89+
priorityId: 2,
90+
startDate: new Date('2021-04-27T20:00:00.000Z'),
91+
endDate: new Date('2021-04-27T22:45:00.000Z'),
92+
}, {
93+
text: 'Approve Hiring of John Jeffers',
94+
priorityId: 2,
95+
startDate: new Date('2021-04-27T16:00:00.000Z'),
96+
endDate: new Date('2021-04-27T19:00:00.000Z'),
97+
}, {
98+
text: 'Update NDA Agreement',
99+
priorityId: 1,
100+
startDate: new Date('2021-04-27T18:00:00.000Z'),
101+
endDate: new Date('2021-04-27T21:15:00.000Z'),
102+
}, {
103+
text: 'Update Employee Files with New NDA',
104+
priorityId: 1,
105+
startDate: new Date('2021-04-30T16:00:00.000Z'),
106+
endDate: new Date('2021-04-30T18:45:00.000Z'),
107+
}, {
108+
text: 'Submit Questions Regarding New NDA',
109+
priorityId: 1,
110+
startDate: new Date('2021-04-28T17:00:00.000Z'),
111+
endDate: new Date('2021-04-28T18:30:00.000Z'),
112+
}, {
113+
text: 'Submit Signed NDA',
114+
priorityId: 1,
115+
startDate: new Date('2021-04-28T20:00:00.000Z'),
116+
endDate: new Date('2021-04-28T22:00:00.000Z'),
117+
}, {
118+
text: 'Review Revenue Projections',
119+
priorityId: 2,
120+
startDate: new Date('2021-04-28T18:00:00.000Z'),
121+
endDate: new Date('2021-04-28T21:00:00.000Z'),
122+
}, {
123+
text: 'Comment on Revenue Projections',
124+
priorityId: 2,
125+
startDate: new Date('2021-04-26T17:00:00.000Z'),
126+
endDate: new Date('2021-04-26T20:00:00.000Z'),
127+
}, {
128+
text: 'Provide New Health Insurance Docs',
129+
priorityId: 2,
130+
startDate: new Date('2021-04-30T19:00:00.000Z'),
131+
endDate: new Date('2021-04-30T22:00:00.000Z'),
132+
}, {
133+
text: 'Review Changes to Health Insurance Coverage',
134+
priorityId: 2,
135+
startDate: new Date('2021-04-29T16:00:00.000Z'),
136+
endDate: new Date('2021-04-29T20:00:00.000Z'),
137+
}, {
138+
text: 'Review Training Course for any Omissions',
139+
priorityId: 1,
140+
startDate: new Date('2021-04-29T18:00:00.000Z'),
141+
endDate: new Date('2021-04-29T21:00:00.000Z'),
142+
},
143+
];
144+
145+
const priorityData = [
146+
{
147+
text: 'Low Priority',
148+
id: 1,
149+
color: '#1D90FF',
150+
}, {
151+
text: 'High Priority',
152+
id: 2,
153+
color: '#FF9747',
154+
},
155+
];
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!DOCTYPE html>
2+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
3+
<head>
4+
<title>DevExtreme Demo</title>
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
8+
<script src="../../../../node_modules/jquery/dist/jquery.min.js"></script>
9+
<link rel="stylesheet" type="text/css" href="../../../../node_modules/devextreme-dist/css/dx.light.css" />
10+
<script src="../../../../node_modules/devextreme-dist/js/dx.all.js"></script>
11+
<script src="data.js"></script>
12+
<script src="index.js"></script>
13+
<style>
14+
.popover-content { padding: 12px; }
15+
.popover-buttons { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }
16+
</style>
17+
</head>
18+
<body class="dx-viewport">
19+
<div class="demo-container">
20+
<div id="scheduler"></div>
21+
<div id="creation-tooltip"></div>
22+
</div>
23+
</body>
24+
</html>
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
$(() => {
2+
let selectionData = null;
3+
let $overlay = null;
4+
5+
function showSelectionOverlay($cells) {
6+
removeOverlay();
7+
if (!$cells.length) return;
8+
9+
const rects = [];
10+
$cells.each(function () {
11+
rects.push(this.getBoundingClientRect());
12+
});
13+
14+
const minX = Math.min(...rects.map((r) => r.x));
15+
const minY = Math.min(...rects.map((r) => r.y));
16+
const maxX = Math.max(...rects.map((r) => r.x + r.width));
17+
const maxY = Math.max(...rects.map((r) => r.y + r.height));
18+
19+
$overlay = $('<div>').css({
20+
position: 'fixed',
21+
left: `${minX}px`,
22+
top: `${minY}px`,
23+
width: `${maxX - minX}px`,
24+
height: `${maxY - minY}px`,
25+
backgroundColor: 'rgba(0, 120, 215, 0.2)',
26+
borderRadius: '2px',
27+
pointerEvents: 'none',
28+
zIndex: 100,
29+
}).appendTo('body');
30+
}
31+
32+
function removeOverlay() {
33+
if ($overlay) {
34+
$overlay.remove();
35+
$overlay = null;
36+
}
37+
}
38+
39+
const tooltip = $('#creation-tooltip').dxTooltip({
40+
width: 260,
41+
height: 'auto',
42+
shading: false,
43+
position: 'right',
44+
hideOnOutsideClick: true,
45+
hideOnParentScroll: false,
46+
contentTemplate() {
47+
const $content = $('<div>').addClass('popover-content');
48+
49+
$('<div id="appointment-subject">').appendTo($content);
50+
51+
const $buttons = $('<div>').addClass('popover-buttons');
52+
$('<div id="create-btn">').appendTo($buttons);
53+
$('<div id="cancel-btn">').appendTo($buttons);
54+
$buttons.appendTo($content);
55+
56+
return $content;
57+
},
58+
onShown() {
59+
$('#appointment-subject').dxTextBox({
60+
placeholder: 'Enter appointment name',
61+
stylingMode: 'outlined',
62+
}).dxTextBox('instance').focus();
63+
64+
$('#create-btn').dxButton({
65+
text: 'Create',
66+
type: 'default',
67+
onClick() {
68+
if (!selectionData) return;
69+
70+
const subject = $('#appointment-subject').dxTextBox('instance').option('value');
71+
if (!subject) return;
72+
73+
scheduler.addAppointment({
74+
text: subject,
75+
startDate: selectionData.startDate,
76+
endDate: selectionData.endDate,
77+
...selectionData.groups,
78+
});
79+
80+
tooltip.hide();
81+
},
82+
});
83+
84+
$('#cancel-btn').dxButton({
85+
text: 'Cancel',
86+
onClick() {
87+
tooltip.hide();
88+
},
89+
});
90+
},
91+
onHidden() {
92+
removeOverlay();
93+
const subjectBox = $('#appointment-subject').data('dxTextBox');
94+
if (subjectBox) {
95+
subjectBox.option('value', '');
96+
}
97+
},
98+
}).dxTooltip('instance');
99+
100+
const scheduler = $('#scheduler').dxScheduler({
101+
timeZone: 'America/Los_Angeles',
102+
dataSource: data,
103+
views: [{
104+
type: 'workWeek',
105+
groupOrientation: 'horizontal',
106+
cellDuration: 30,
107+
}],
108+
currentView: 'workWeek',
109+
currentDate: new Date(2021, 3, 21),
110+
startDayHour: 9,
111+
endDayHour: 16,
112+
groups: ['priorityId'],
113+
resources: [{
114+
fieldExpr: 'priorityId',
115+
allowMultiple: false,
116+
dataSource: priorityData,
117+
label: 'Priority',
118+
}],
119+
showCurrentTimeIndicator: false,
120+
allDayPanelMode: 'allDay',
121+
onSelectionEnd(e) {
122+
const cells = e.selectedCellData;
123+
if (cells.length <= 1) {
124+
return;
125+
}
126+
127+
const startDate = cells[0].startDateUTC || cells[0].startDate;
128+
const endDate = cells[cells.length - 1].endDateUTC || cells[cells.length - 1].endDate;
129+
130+
selectionData = {
131+
startDate,
132+
endDate,
133+
groups: cells[0].groups || {},
134+
};
135+
136+
const $focused = e.component.$element().find('.dx-scheduler-date-table-cell.dx-state-focused');
137+
showSelectionOverlay($focused);
138+
139+
setTimeout(() => {
140+
if ($overlay) {
141+
tooltip.option('target', $overlay);
142+
tooltip.show();
143+
}
144+
}, 50);
145+
},
146+
}).dxScheduler('instance');
147+
});

apps/demos/menuMeta.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3649,6 +3649,12 @@
36493649
"/Models/Scheduler/ResolveTimeConflicts.cs"
36503650
],
36513651
"DemoType": "Web"
3652+
},
3653+
{
3654+
"Title": "Create from Selection",
3655+
"Name": "CreateFromSelection",
3656+
"Widget": "Scheduler",
3657+
"DemoType": "Web"
36523658
}
36533659
]
36543660
},

packages/devextreme/js/__internal/scheduler/workspaces/m_work_space.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,7 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
12441244
(eventsEngine.off as any)(element, SCHEDULER_CELL_DXPOINTERDOWN_EVENT_NAME);
12451245

12461246
eventsEngine.on(element, SCHEDULER_CELL_DXPOINTERDOWN_EVENT_NAME, DRAG_AND_DROP_SELECTOR, (e) => {
1247-
if (isMouseEvent(e) && e.which === 1) {
1247+
if ((isMouseEvent(e) || e.pointerType === 'mouse') && e.which === 1) {
12481248
isPointerDown = true;
12491249
(this.$element() as any).addClass(WORKSPACE_WITH_MOUSE_SELECTION_CLASS);
12501250
(eventsEngine.off as any)(domAdapter.getDocument(), SCHEDULER_CELL_DXPOINTERUP_EVENT_NAME);
@@ -1256,7 +1256,7 @@ class SchedulerWorkSpace extends Widget<WorkspaceOptionsInternal> {
12561256
});
12571257

12581258
eventsEngine.on(element, SCHEDULER_CELL_DXPOINTERMOVE_EVENT_NAME, DRAG_AND_DROP_SELECTOR, (e) => {
1259-
if (isPointerDown && this._dateTableScrollable && !this._dateTableScrollable.option('scrollByContent')) {
1259+
if (isPointerDown && this._dateTableScrollable) {
12601260
e.preventDefault();
12611261
e.stopPropagation();
12621262
this.moveToCell($(e.target), true);

packages/devextreme/js/ui/scheduler.d.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,16 @@ export type InitializedEvent = InitializedEventInfo<dxScheduler>;
368368
*/
369369
export type OptionChangedEvent = EventInfo<dxScheduler> & ChangedOptionInfo;
370370

371+
/**
372+
* @docid _ui_scheduler_SelectionEndEvent
373+
* @public
374+
* @type object
375+
* @inherits EventInfo
376+
*/
377+
export type SelectionEndEvent = EventInfo<dxScheduler> & {
378+
readonly selectedCellData: Array<any>;
379+
};
380+
371381
/** @public */
372382
export type AppointmentDraggingAddEvent = AppointmentDraggingEvent & {
373383
readonly fromComponent?: dxSortable | dxDraggable;
@@ -850,6 +860,15 @@ export interface dxSchedulerOptions extends WidgetOptions<dxScheduler> {
850860
* @public
851861
*/
852862
onCellClick?: ((e: CellClickEvent) => void) | string;
863+
/**
864+
* @docid
865+
* @default null
866+
* @type function
867+
* @type_function_param1 e:{ui/scheduler:SelectionEndEvent}
868+
* @action
869+
* @public
870+
*/
871+
onSelectionEnd?: ((e: SelectionEndEvent) => void);
853872
/**
854873
* @docid
855874
* @default null

0 commit comments

Comments
 (0)