Skip to content

Commit 3f94a19

Browse files
authored
Scheduler: fix appointment color for remote data source (T1300252) (DevExpress#30469)
Co-authored-by: Vladimir Bushmanov <[email protected]>
1 parent 1a1e60d commit 3f94a19

File tree

8 files changed

+127
-25
lines changed

8 files changed

+127
-25
lines changed

apps/demos/Demos/Scheduler/Resources/jQuery/index.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@ $(() => {
3232
onValueChanged(e) {
3333
const resources = scheduler.option('resources');
3434

35-
for (let i = 0; i < resources.length; i += 1) {
36-
resources[i].useColorAsDefault = resources[i].label === e.value;
37-
}
38-
39-
scheduler.repaint();
35+
scheduler.option('resources', resources.map((resource) => ({
36+
...resource,
37+
useColorAsDefault: resource.label === e.value,
38+
})));
4039
},
4140
});
4241
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
3+
import {
4+
describe, expect, it,
5+
} from '@jest/globals';
6+
import { DataSource } from '@ts/data/data_source/m_data_source';
7+
import CustomStore from '@ts/data/m_custom_store';
8+
9+
import Scheduler from '../m_scheduler';
10+
import { setupSchedulerTestEnvironment } from './__mock__/m_mock_scheduler';
11+
12+
const dataSource = [
13+
{
14+
startDate: new Date(2024, 8, 7, 0, 0),
15+
endDate: new Date(2024, 8, 7, 8, 0),
16+
roomId: 1,
17+
priorityId: 1,
18+
text: 'Install New Database',
19+
},
20+
];
21+
const rooms = [
22+
{ id: 1, text: 'Room 2', color: 'rgb(142, 205, 60)' },
23+
];
24+
const getAppointmentColor = (container: HTMLDivElement): string => {
25+
const appointment = container.querySelector('.dx-scheduler-appointment') as HTMLDivElement;
26+
return appointment.style.backgroundColor;
27+
};
28+
29+
describe('Resources', () => {
30+
it('should render correct appointment color for remote datasource (T1300252)', async () => {
31+
setupSchedulerTestEnvironment();
32+
33+
const dataPromise = new Promise((resolve) => {
34+
setTimeout(resolve, 100, rooms);
35+
});
36+
const container = document.createElement('div');
37+
const scheduler = new Scheduler(container, {
38+
views: ['month'],
39+
currentView: 'month',
40+
currentDate: new Date(2024, 8, 8),
41+
dataSource,
42+
resources: [{
43+
fieldExpr: 'roomId',
44+
label: 'Room',
45+
dataSource: new DataSource({
46+
store: new CustomStore({
47+
load: () => dataPromise,
48+
}),
49+
paginate: false,
50+
}),
51+
}],
52+
} as any);
53+
await dataPromise;
54+
await new Promise(process.nextTick);
55+
56+
expect(getAppointmentColor(container)).toBe(rooms[0].color);
57+
});
58+
59+
it('should render correct appointment color for local datasource (T1300252)', async () => {
60+
setupSchedulerTestEnvironment();
61+
62+
const container = document.createElement('div');
63+
const scheduler = new Scheduler(container, {
64+
views: ['month'],
65+
currentView: 'month',
66+
currentDate: new Date(2024, 8, 8),
67+
dataSource,
68+
resources: [{
69+
fieldExpr: 'roomId',
70+
label: 'Room',
71+
dataSource: rooms,
72+
}],
73+
} as any);
74+
await new Promise(process.nextTick);
75+
76+
expect(getAppointmentColor(container)).toBe(rooms[0].color);
77+
});
78+
});

packages/devextreme/js/__internal/scheduler/utils/loader/loader.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ export abstract class Loader<T, Data, Config extends BaseConfig<T> = BaseConfig<
7171
this.loadingStatePromise = this.loadingStatePromise && !forceReload
7272
? this.loadingStatePromise
7373
: loadResource(this.dataSource, forceReload);
74-
await this.loadingStatePromise;
7574
}
75+
76+
await this.loadingStatePromise;
7677
}
7778

7879
protected abstract onLoadTransform(items: T[]): Data[];

packages/devextreme/js/__internal/scheduler/utils/resource_manager/appointment_color_utils.test.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
import {
55
complexIdResourceMock,
66
getResourceManagerMock,
7+
resourceConfigMock,
78
resourceIndexesMock,
89
resourceItemsByIdMock,
910
} from '@ts/scheduler/__mock__/resourceManager.mock';
@@ -41,8 +42,11 @@ const customResourceConfig = [
4142
describe('appointment color utils', () => {
4243
describe('getPaintedResources', () => {
4344
it('should return useColorAsDefault resource', () => {
44-
const manager = getResourceManagerMock();
45-
manager.resources[1].useColorAsDefault = true;
45+
const manager = getResourceManagerMock([
46+
{ ...resourceConfigMock[0] },
47+
{ ...resourceConfigMock[1], useColorAsDefault: true },
48+
{ ...resourceConfigMock[2] },
49+
]);
4650

4751
expect(
4852
getPaintedResource(manager.resources, resourceIndexesMock, resourceIndexesMock),
@@ -82,8 +86,11 @@ describe('appointment color utils', () => {
8286
});
8387

8488
it('should return last resource filtered by appointment groups that exclude useColorAsDefault resource', () => {
85-
const manager = getResourceManagerMock();
86-
manager.resources[1].useColorAsDefault = true;
89+
const manager = getResourceManagerMock([
90+
{ ...resourceConfigMock[0] },
91+
{ ...resourceConfigMock[1], useColorAsDefault: true },
92+
{ ...resourceConfigMock[2] },
93+
]);
8794

8895
expect(
8996
getPaintedResource(
@@ -138,9 +145,12 @@ describe('appointment color utils', () => {
138145
});
139146

140147
it('should return color of default resource', async () => {
141-
const manager = getResourceManagerMock();
148+
const manager = getResourceManagerMock([
149+
{ ...resourceConfigMock[0] },
150+
{ ...resourceConfigMock[1], useColorAsDefault: true },
151+
{ ...resourceConfigMock[2] },
152+
]);
142153
await manager.loadGroupResources(['roomId', 'nested.priorityId']);
143-
manager.resources[1].useColorAsDefault = true;
144154

145155
expect(
146156
await getAppointmentColor(

packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/appointment.week.based.views.tests.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
createWrapper,
1818
supportedScrollingModes, createWrapperFakeClock
1919
} from '../../helpers/scheduler/helpers.js';
20-
import { waitAsync } from '../../helpers/scheduler/waitForAsync.js';
20+
import { waitAsync, waitForAsync } from '../../helpers/scheduler/waitForAsync.js';
2121

2222
import '__internal/scheduler/m_scheduler';
2323
import 'ui/switch';
@@ -414,6 +414,7 @@ module('Integration: Appointment Day, Week views', {
414414

415415
const tasks = scheduler.instance.$element().find('.' + APPOINTMENT_CLASS);
416416

417+
await waitForAsync(() => getAppointmentColor(tasks.eq(0)) === '#cb2824');
417418
assert.equal(getAppointmentColor(tasks.eq(0)), '#cb2824', 'Color is OK');
418419
assert.equal(getAppointmentColor(tasks.eq(1)), '#cb7d7b', 'Color is OK');
419420
assert.equal(getAppointmentColor(tasks.eq(2)), '#cb2824', 'Color is OK');
@@ -442,6 +443,7 @@ module('Integration: Appointment Day, Week views', {
442443
});
443444

444445
const tasks = scheduler.instance.$element().find('.' + APPOINTMENT_CLASS);
446+
await waitForAsync(() => getAppointmentColor(tasks.eq(0)) === '#0000ff');
445447
assert.equal(getAppointmentColor(tasks.eq(0)), '#0000ff', 'Color is OK');
446448
assert.equal($.inArray(getAppointmentColor(tasks.eq(1)), ['#ff0000', '#0000ff']), -1, 'Color is OK');
447449
} finally {

packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.recurringAppointments.tests.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
isDesktopEnvironment,
1414
supportedScrollingModes
1515
} from '../../helpers/scheduler/helpers.js';
16+
import { waitForAsync } from '../../helpers/scheduler/waitForAsync.js';
1617
import dateUtils from 'core/utils/date';
1718
import timeZoneUtils from '__internal/scheduler/m_utils_time_zone';
1819

@@ -112,8 +113,10 @@ supportedScrollingModes.forEach(scrollingMode => {
112113
}
113114
]
114115
});
116+
const appointments = $(scheduler.instance.$element()).find('.dx-scheduler-appointment');
115117

116-
$(scheduler.instance.$element()).find('.dx-scheduler-appointment').each(function() {
118+
await waitForAsync(() => getAppointmentColor($(appointments).last()) === '#ff0000');
119+
appointments.each(function() {
117120
assert.equal(getAppointmentColor($(this)), '#ff0000', 'Color is OK');
118121
});
119122

packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.resources.tests.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import translator from 'common/core/animation/translator';
1212
import '__internal/scheduler/m_scheduler';
1313

1414
import { createWrapper, initTestMarkup } from '../../helpers/scheduler/helpers.js';
15-
import { waitAsync } from '../../helpers/scheduler/waitForAsync.js';
15+
import { waitAsync, waitForAsync } from '../../helpers/scheduler/waitForAsync.js';
16+
17+
const getHexColor = ($appointment) => new Color($appointment.css('backgroundColor')).toHex();
1618

1719
QUnit.testStart(() => initTestMarkup());
1820

@@ -464,8 +466,9 @@ QUnit.module('Integration: Resources', moduleConfig, () => {
464466

465467
const $appointments = scheduler.instance.$element().find('.dx-scheduler-appointment');
466468

467-
assert.equal(new Color($appointments.eq(0).css('backgroundColor')).toHex(), '#ff0000', 'Color is OK');
468-
assert.equal(new Color($appointments.eq(1).css('backgroundColor')).toHex(), '#0000ff', 'Color is OK');
469+
await waitForAsync(() => getHexColor($appointments.eq(0)) === '#ff0000');
470+
assert.equal(getHexColor($appointments.eq(0)), '#ff0000', 'Color is OK');
471+
assert.equal(getHexColor($appointments.eq(1)), '#0000ff', 'Color is OK');
469472
});
470473

471474
QUnit.test('Resources should not be reloaded when details popup is opening', async function(assert) {
@@ -560,7 +563,8 @@ QUnit.module('Integration: Resources', moduleConfig, () => {
560563
await waitAsync(0);
561564

562565
const $appointments = scheduler.instance.$element().find('.dx-scheduler-appointment');
563-
assert.equal(new Color($appointments.eq(0).css('backgroundColor')).toHex(), '#ff0000', 'Color is OK');
566+
await waitForAsync(() => getHexColor($appointments.eq(0)) === '#ff0000');
567+
assert.equal(getHexColor($appointments.eq(0)), '#ff0000', 'Color is OK');
564568
});
565569
});
566570

packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/perfomance.tests.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { DataSource } from 'common/data/data_source/data_source';
77
import { CustomStore } from 'common/data/custom_store';
88
import pointerMock from '../../helpers/pointerMock.js';
99
import { createWrapper } from '../../helpers/scheduler/helpers.js';
10-
import { waitAsync } from '../../helpers/scheduler/waitForAsync.js';
10+
import { waitForAsync } from '../../helpers/scheduler/waitForAsync.js';
1111

1212
QUnit.testStart(function() {
1313
$('#qunit-fixture').html('<div id="scheduler"></div>');
@@ -398,15 +398,20 @@ QUnit.module('Render layout', renderLayoutModuleOptions, function() {
398398
label: 'Resource'
399399
}]
400400
});
401-
let appointmentFirst = this.scheduler.appointments.getAppointment(0);
402-
assert.notEqual(appointmentFirst.css('backgroundColor'), 'rgb(0, 255, 0)', 'Appointment background color is not changed');
401+
const getAppointmentColor = () => {
402+
const appointmentFirst = this.scheduler.appointments.getAppointment(0);
403+
return appointmentFirst.css('backgroundColor');
404+
};
405+
assert.notEqual(getAppointmentColor(), 'rgb(0, 255, 0)', 'Appointment background color is not changed');
403406

404407
const resources = this.instance.option('resources');
405-
resources[0].dataSource[0].color = '#00ff00';
408+
resources[0].dataSource = [
409+
{ ...resourcesData[0], color: '#00ff00' },
410+
resourcesData[1],
411+
];
406412
this.instance.option('resources', resources);
407-
await waitAsync(0);
413+
await waitForAsync(() => getAppointmentColor() === 'rgb(0, 255, 0)');
408414

409-
appointmentFirst = this.scheduler.appointments.getAppointment(0);
410-
assert.equal(appointmentFirst.css('backgroundColor'), 'rgb(0, 255, 0)', 'Appointment background color is changed');
415+
assert.equal(getAppointmentColor(), 'rgb(0, 255, 0)', 'Appointment background color is changed');
411416
});
412417
});

0 commit comments

Comments
 (0)