diff --git a/apps/demos/Demos/PivotGrid/StandaloneFieldChooser/Angular/app/app.component.ts b/apps/demos/Demos/PivotGrid/StandaloneFieldChooser/Angular/app/app.component.ts
index 9b0bcfb6a7c5..1079a7780bf7 100644
--- a/apps/demos/Demos/PivotGrid/StandaloneFieldChooser/Angular/app/app.component.ts
+++ b/apps/demos/Demos/PivotGrid/StandaloneFieldChooser/Angular/app/app.component.ts
@@ -1,20 +1,111 @@
import { bootstrapApplication } from '@angular/platform-browser';
-import { Component } from '@angular/core';
-
-// TODO: restore the original demo (see git history for this file, app.component.html,
-// app.component.css, app.service.ts). Disabled because combining DxPivotGridModule and
-// DxPivotGridFieldChooserModule here reproducibly triggers, in CI only (not locally, likely a
-// devextreme-angular artifacts staleness difference between environments):
-// NG8023: Multiple components match node with tagname dxo-pivot-grid-field-chooser-texts:
-// 'DxoPivotGridFieldChooserTextsComponent', 'DxoPivotGridFieldChooserTextsComponent'.
-// Both modules generate their own nested-options component for that tag name, and combining
-// them in one standalone component's imports puts both in scope at once. Needs a real fix in
-// devextreme-angular's generated wrappers (or dropping one of the two imports if one turns out
-// to be redundant here) rather than a demo-side workaround.
+import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
+import {
+ DxRadioGroupComponent,
+ DxButtonComponent,
+ DxSelectBoxComponent,
+} from 'devextreme-angular';
+import PivotGridDataSource from 'devextreme/ui/pivot_grid/data_source';
+import {
+ DxPivotGridComponent,
+ DxoPivotGridFieldChooserComponent,
+ DxPivotGridTypes,
+} from 'devextreme-angular/ui/pivot-grid';
+import {
+ DxPivotGridFieldChooserComponent,
+ DxoPivotGridFieldChooserTextsComponent,
+} from 'devextreme-angular/ui/pivot-grid-field-chooser';
+import { Service, Layout, Sale } from './app.service';
+
+if (!/localhost/.test(document.location.host)) {
+ enableProdMode();
+}
+
@Component({
selector: 'demo-app',
- template: '
This demo is temporarily disabled. See the TODO in app.component.ts.
',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css'],
+ providers: [Service],
+ preserveWhitespaces: true,
+ imports: [
+ DxPivotGridComponent,
+ DxoPivotGridFieldChooserComponent,
+ DxRadioGroupComponent,
+ DxPivotGridFieldChooserComponent,
+ DxoPivotGridFieldChooserTextsComponent,
+ DxSelectBoxComponent,
+ DxButtonComponent,
+ ],
})
-export class AppComponent {}
+export class AppComponent {
+ pivotGridDataSource: PivotGridDataSource;
+
+ layouts: Layout[];
+
+ layout = 0;
+
+ applyChangesModes: DxPivotGridTypes.ApplyChangesMode[] = ['instantly', 'onDemand'];
+
+ applyChangesMode = this.applyChangesModes[0];
+
+ state: Record;
+
+ constructor(service: Service) {
+ this.pivotGridDataSource = new PivotGridDataSource({
+ fields: [{
+ caption: 'Region',
+ width: 120,
+ dataField: 'region',
+ area: 'row',
+ headerFilter: {
+ search: {
+ enabled: true,
+ },
+ },
+ }, {
+ caption: 'City',
+ dataField: 'city',
+ width: 150,
+ area: 'row',
+ headerFilter: {
+ search: {
+ enabled: true,
+ },
+ },
+ selector(data: Sale) {
+ return `${data.city} (${data.country})`;
+ },
+ }, {
+ dataField: 'date',
+ dataType: 'date',
+ area: 'column',
+ }, {
+ caption: 'Sales',
+ dataField: 'amount',
+ dataType: 'number',
+ summaryType: 'sum',
+ format: 'currency',
+ area: 'data',
+ }],
+ store: service.getSales(),
+ });
+
+ this.state = this.pivotGridDataSource.state();
+
+ this.layouts = service.getLayouts();
+ }
+
+ applyClick() {
+ this.pivotGridDataSource.state(this.state);
+ }
+
+ cancelClick() {
+ this.state = this.pivotGridDataSource.state();
+ }
+}
-bootstrapApplication(AppComponent);
+bootstrapApplication(AppComponent, {
+ providers: [
+ provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }),
+ ],
+});
diff --git a/apps/demos/testing/skipped-tests.js b/apps/demos/testing/skipped-tests.js
index 52bd9f86578d..cdd9e5ce7dcf 100644
--- a/apps/demos/testing/skipped-tests.js
+++ b/apps/demos/testing/skipped-tests.js
@@ -6,8 +6,6 @@ export const skippedTests = {
Angular: {
// WebGL initialization error at the provider. There is no point in adding a mask
Map: ['ProvidersAndTypes', 'Markers', 'Routes'],
- // Demo is stubbed out (see the TODO in its app.component.ts) pending a devextreme-angular fix
- PivotGrid: ['StandaloneFieldChooser'],
},
React: {
// WebGL initialization error at the provider. There is no point in adding a mask
diff --git a/apps/demos/testing/widgets/scheduler/etalons/scheduler_ResolveTimeConflicts_appointment-popup_recurrence-group_conflict-informer (material.blue.light)_mask.png b/apps/demos/testing/widgets/scheduler/etalons/scheduler_ResolveTimeConflicts_appointment-popup_recurrence-group_conflict-informer (material.blue.light)_mask.png
new file mode 100644
index 000000000000..bf66555a7025
Binary files /dev/null and b/apps/demos/testing/widgets/scheduler/etalons/scheduler_ResolveTimeConflicts_appointment-popup_recurrence-group_conflict-informer (material.blue.light)_mask.png differ
diff --git a/apps/demos/utils/server/csp-bundle-angular.js b/apps/demos/utils/server/csp-bundle-angular.js
index b6104c09749d..e28b2b36ad53 100644
--- a/apps/demos/utils/server/csp-bundle-angular.js
+++ b/apps/demos/utils/server/csp-bundle-angular.js
@@ -179,11 +179,6 @@ function findAngularEntry(srcDir) {
return null;
}
-// TODO: remove once PivotGrid/StandaloneFieldChooser/Angular renders reliably (times out in csp-check.js)
-const SKIPPED_DEMOS = new Set([
- 'PivotGrid/StandaloneFieldChooser/Angular',
-]);
-
function findDemos() {
const out = [];
if (!fs.existsSync(SRC_DEMOS_DIR)) return out;
@@ -194,7 +189,6 @@ function findDemos() {
const demos = fs.readdirSync(widgetDir, { withFileTypes: true }).filter((d) => d.isDirectory());
for (const demo of demos) {
const key = `${widget.name}/${demo.name}`;
- if (SKIPPED_DEMOS.has(`${key}/${FRAMEWORK}`)) continue; // eslint-disable-line no-continue
const fwDir = path.join(widgetDir, demo.name, FRAMEWORK);
const matchesFilter = !FILTER || key.includes(FILTER);
if (matchesFilter && fs.existsSync(path.join(fwDir, 'index.html'))) {
diff --git a/apps/demos/utils/server/csp-check.js b/apps/demos/utils/server/csp-check.js
index b3a8afdfac4a..0e19d27275fa 100644
--- a/apps/demos/utils/server/csp-check.js
+++ b/apps/demos/utils/server/csp-check.js
@@ -176,11 +176,6 @@ function applyShard(demos) {
return applyShardGeneric(demos, (d) => `${d.widget}/${d.demo}`, { SHARD_TOTAL, SHARD_INDEX });
}
-// TODO: remove once PivotGrid/StandaloneFieldChooser/Angular renders reliably (times out here)
-const SKIPPED_DEMOS = new Set([
- 'PivotGrid/StandaloneFieldChooser/Angular',
-]);
-
function findDemos() {
const demosDirName = 'Demos';
const demosDir = join(DEMO_ROOT, demosDirName);
@@ -202,7 +197,6 @@ function findDemos() {
.filter((d) => d.isDirectory());
for (const demo of demos) {
- if (SKIPPED_DEMOS.has(`${widget.name}/${demo.name}/${FRAMEWORK}`)) continue; // eslint-disable-line no-continue
const fwDir = join(widgetDir, demo.name, FRAMEWORK);
if (existsSync(join(fwDir, 'index.html'))) {
result.push({