Scheduler: Multilevel grouping - #34753
Merged
aleksei-semikozov merged 12 commits intoAug 20, 2026
Merged
Conversation
Co-authored-by: Sergei Burkatskii <5622446+sjbur@users.noreply.github.com>
Co-authored-by: Sergio Bur <noreply@github.com>
Co-authored-by: Sergio Bur <noreply@github.com>
Co-authored-by: Sergio Bur <noreply@github.com>
…34605) Co-authored-by: Sergio Bur <noreply@github.com>
… group panel (#34648) Co-authored-by: Aleksey Semikozov <aleksei.semikozov@devexpress.com>
Co-authored-by: Sergio Bur <noreply@github.com>
Co-authored-by: Aleksey Semikozov <aleksei.semikozov@devexpress.com>
sjbur
approved these changes
Aug 20, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates DevExtreme Scheduler to support multilevel (hierarchical) resource grouping by introducing a parentIdExpr resource option, building resource hierarchy/leaf grouping structures, and updating group panel rendering and styling across views (including timeline/vertical/horizontal layouts). It also adds/updates unit, integration, and E2E tests plus new demos to validate the hierarchical grouping behavior and layout.
Changes:
- Add
resources.parentIdExprto the public Scheduler API and framework wrappers to enable hierarchical resource definitions. - Implement hierarchy-aware resource loading/grouping (tree + leaf collection) and propagate it into group panel data/rendering.
- Update Scheduler styles, tests, and add new demos/E2E coverage for hierarchical grouping scenarios.
Reviewed changes
Copilot reviewed 90 out of 230 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/devextreme/ts/dx.all.d.ts | Adds parentIdExpr to aggregated Scheduler typings. |
| packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/view_data_provider.tests.js | Updates expected group panel data shape to include tree/hierarchy metadata. |
| packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/timeline.markup.tests.js | Removes legacy assertion tied to group-count CSS class behavior. |
| packages/devextreme/testing/tests/DevExpress.ui.widgets.scheduler/integration.resources.tests.js | Adjusts expected appointment positioning after layout/grouping changes. |
| packages/devextreme/js/ui/scheduler.d.ts | Exposes resources.parentIdExpr in public Scheduler API. |
| packages/devextreme/js/__internal/scheduler/workspaces/work_space.ts | Removes group-count class toggling; updates group panel rendering path. |
| packages/devextreme/js/__internal/scheduler/workspaces/work_space_grouped_strategy_vertical.ts | Removes vertical grouped strategy group-count class helper. |
| packages/devextreme/js/__internal/scheduler/workspaces/work_space_grouped_strategy_vertical.test.ts | Updates mocks after removing group-count helper export. |
| packages/devextreme/js/__internal/scheduler/workspaces/work_space_grouped_strategy_horizontal.ts | Removes unused horizontal grouped strategy group-count stub. |
| packages/devextreme/js/__internal/scheduler/workspaces/view_model/view_data_provider.ts | Switches group panel data source to groupsTree and adds hasHierarchy flag. |
| packages/devextreme/js/__internal/scheduler/workspaces/agenda.ts | Removes group-count class behavior from Agenda workspace. |
| packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/split_by_group_index.test.ts | Adds Jest coverage for hierarchical resource grouping index assignment. |
| packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_attributes/is_appointment_matched_resources.ts | Ensures resource matching uses leaf items for hierarchical resources. |
| packages/devextreme/js/__internal/scheduler/view_model/filtration/utils/filter_by_attributes/is_appointment_matched_resources.test.ts | Adds tests for matching behavior with hierarchical resources (leaf vs parent ids). |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/types.ts | Extends group node typing with id/color/raw resource data. |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/resource_manager.ts | Adds APIs to query hierarchy/leaf data for resources. |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/resource_manager.test.ts | Adds tests verifying hierarchy tree + leaf items exposure. |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/hierarchy_tree_utils.ts | Introduces hierarchy tree builder + leaf collector with cycle protection. |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/hierarchy_tree_utils.test.ts | Adds unit tests for hierarchy building/leaves/cycles/object ids. |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/group_utils.ts | Reworks grouping tree construction to support hierarchical resources. |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/appointment_groups_utils.ts | Compares group ids by value (supports non-primitive ids) and uses shared matcher. |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/appointment_groups_utils.test.ts | Adds hierarchical resource group index regression/coverage tests. |
| packages/devextreme/js/__internal/scheduler/utils/resource_manager/agenda_group_utils.test.ts | Updates expected reduced tree data; strips resourceData for comparisons. |
| packages/devextreme/js/__internal/scheduler/utils/loader/types.ts | Adds parentIdExpr to resource config; extends raw/resource data to include parentId. |
| packages/devextreme/js/__internal/scheduler/utils/loader/resource_loader.ts | Builds/maintains hierarchy tree + leaf items/data on load/change/dispose. |
| packages/devextreme/js/__internal/scheduler/utils/loader/resource_loader.test.ts | Adds tests for hierarchy tree/leaf data behavior (loaded + lazy). |
| packages/devextreme/js/__internal/scheduler/utils/data_accessor/resource_data_accessor.ts | Adds parentId expression support; supports function-based expressions. |
| packages/devextreme/js/__internal/scheduler/utils/data_accessor/resource_data_accessor.test.ts | Adds tests for function expressions and parentId get/set behavior. |
| packages/devextreme/js/__internal/scheduler/types.ts | Extends group-related types for hierarchy (path, leaf flags, tree nodes, metadata). |
| packages/devextreme/js/__internal/scheduler/r1/utils/index.ts | Re-exports new group panel tree utilities; removes vertical group count helper export. |
| packages/devextreme/js/__internal/scheduler/r1/utils/group_panel_tree.ts | Adds utilities to build/flatten group panel tree and template data. |
| packages/devextreme/js/__internal/scheduler/r1/utils/base.ts | Replaces group panel data building with tree-based approach; adds timeline row helper. |
| packages/devextreme/js/__internal/scheduler/r1/components/types.ts | Extends resource cell template data (resourceIndex, level, path, leaf flags). |
| packages/devextreme/js/__internal/scheduler/r1/components/timeline/header_panel_timeline.test.tsx | Adds tests ensuring timeline header panel delegates group panel data correctly. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel.tsx | Simplifies prop plumbing; passes actual groupByDate through. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_vertical.tsx | Renders hierarchical/flat layouts; supports timeline-specific row derivation. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_vertical_row.tsx | Removes per-row height styling and passes hierarchy info to cells. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_vertical_row.test.tsx | Updates test to validate structure rather than inline style. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_vertical_node.tsx | New recursive component for hierarchical vertical group headers. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_vertical_node.test.tsx | Adds tests for flexGrow, leaf behavior, accessibility attrs, template data. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_vertical_cell.tsx | Uses shared template data builder with hierarchy/path metadata. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_props.ts | Updates group panel props/types/defaults for tree-based data + elementRef. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_horizontal.tsx | Removes legacy colSpan recomputation cache; relies on tree flattening output. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_horizontal_row.tsx | Passes rowSpan/isLastColumn/hierarchy path info into cells. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_horizontal_cell.tsx | Adds rowSpan/title/scope/role and hierarchy-aware template data. |
| packages/devextreme/js/__internal/scheduler/r1/components/base/group_panel_horizontal_cell.test.tsx | Adds unit tests for rowSpan/scope/title/border class + template data. |
| packages/devextreme/js/__internal/scheduler/classes.ts | Removes exported vertical group count class list. |
| packages/devextreme/js/__internal/scheduler/appointment_popup/form.ts | Supplies leaf-only resource items to editors for hierarchical resources. |
| packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts | Adds coverage for hierarchical resource editors (loaded + lazy). |
| packages/devextreme/js/__internal/scheduler/tests/hierarchical_grouping.test.ts | Adds end-to-end-like Jest coverage for hierarchical grouping behavior + templates. |
| packages/devextreme/js/__internal/scheduler/tests/mock/create_appointment_popup.ts | Adds preloadResources option to allow testing lazy resource loading. |
| packages/devextreme/js/__internal/scheduler/mock/resource_manager.mock.ts | Adds hierarchical rooms mock/config used across tests. |
| packages/devextreme-vue/src/scheduler.ts | Adds parentIdExpr prop + update event for Vue Scheduler resource config. |
| packages/devextreme-scss/scss/widgets/material/scheduler/_index.scss | Updates borders/width logic and adds hierarchical timeline layout rules. |
| packages/devextreme-scss/scss/widgets/generic/scheduler/_index.scss | Adjusts grouping borders/shadows; updates last-child border handling. |
| packages/devextreme-scss/scss/widgets/fluent/scheduler/_index.scss | Updates borders/width logic and adds hierarchical timeline layout rules. |
| packages/devextreme-scss/scss/widgets/base/scheduler/views/timelines/_index.scss | Tweaks timeline group header border rules for updated markup/structure. |
| packages/devextreme-scss/scss/widgets/base/scheduler/views/_index.scss | Adds hierarchical flex-container layout rules and refines border logic. |
| packages/devextreme-react/src/scheduler.ts | Adds parentIdExpr to React Scheduler resource prop types. |
| packages/devextreme-metadata/make-angular-metadata.ts | Excludes resources.parentIdExpr from Angular metadata generation set. |
| packages/devextreme-angular/src/ui/scheduler/nested/resource-dxi.ts | Adds @Input() parentIdExpr to Angular nested resource component. |
| packages/devextreme-angular/src/ui/scheduler/index.ts | Extends Angular Scheduler resources typing/events to include parentIdExpr. |
| e2e/testcafe-devextreme/tests/scheduler/common/grouping/hierarchicalGrouping.ts | Adds visual regression coverage for hierarchical grouping across views/orientations/RTL. |
| e2e/testcafe-devextreme/tests/scheduler/common/grouping/hierarchicalGrouping.data.ts | Adds hierarchical rooms/appointments datasets for E2E tests. |
| e2e/testcafe-devextreme/tests/accessibility/scheduler/scheduler.ts | Adds a11y checks for flat vs hierarchical grouping across several views. |
| apps/demos/menuMeta.json | Registers new Scheduler demo entry: “Multilevel Grouping”. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Vue/index.ts | Vue demo bootstrap. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Vue/index.html | Vue demo HTML host page. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Vue/data.ts | Vue demo hierarchical resource + appointment datasets. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Vue/App.vue | Vue demo implementing multilevel grouping and appointment form customization. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/ReactJs/styles.css | ReactJS demo styling for header/group sizing and backgrounds. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/ReactJs/index.js | ReactJS demo bootstrap. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/ReactJs/index.html | ReactJS demo HTML host page. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/ReactJs/data.js | ReactJS demo hierarchical resource + appointment datasets. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/ReactJs/App.js | ReactJS demo implementing multilevel grouping and form customization. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/React/styles.css | React (TS) demo styling for header/group sizing and backgrounds. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/React/index.tsx | React (TS) demo bootstrap. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/React/index.html | React (TS) demo HTML host page. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/React/data.ts | React (TS) demo datasets and types. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/React/App.tsx | React (TS) demo implementing multilevel grouping and form customization. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/jQuery/styles.css | jQuery demo styling for header/group sizing and backgrounds. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/jQuery/index.js | jQuery demo implementing multilevel grouping and form customization. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/jQuery/index.html | jQuery demo HTML host page. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/jQuery/data.js | jQuery demo hierarchical resource + appointment datasets. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Angular/index.html | Angular demo HTML host page. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Angular/app/app.service.ts | Angular demo data service for resources/appointments. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Angular/app/app.component.ts | Angular demo component implementing multilevel grouping and form customization. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Angular/app/app.component.html | Angular demo template wiring Scheduler views/resources with parentIdExpr. |
| apps/demos/Demos/Scheduler/MultilevelGrouping/Angular/app/app.component.css | Angular demo styling overrides for group headers and workspace backgrounds. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
2389
to
2392
|
|
||
| if (this.option().groups?.length) { | ||
| this.attachGroupCountClass(); | ||
| const $groupHeaderContainer = this.getGroupHeaderContainer(); | ||
| if ($groupHeaderContainer) { |
aleksei-semikozov
deleted the
feature/scheduler-multilevel-grouping/main
branch
August 20, 2026 17:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.