Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { PopupModel } from '@ts/ui/__tests__/__mock__/model/popup';
import { TreeViewModel } from '@ts/ui/__tests__/__mock__/model/tree_view';

const CLASSES = {
filterBuilder: 'dx-filterbuilder',
groupOperation: 'dx-filterbuilder-group-operation',
treeView: 'dx-treeview',
popupWrapper: 'dx-popup-wrapper',
itemField: 'dx-filterbuilder-item-field',
itemOperation: 'dx-filterbuilder-item-operation',
};

export class FilterBuilderModel extends PopupModel {
public getElement(): HTMLElement {
const content = this.getOverlayContent();
return content?.querySelector<HTMLElement>(`.${CLASSES.filterBuilder}`) as HTMLElement;
}

public getGroupOperationButton(): HTMLElement {
const element = this.getElement();
return element.querySelector<HTMLElement>(`.${CLASSES.groupOperation}`) as HTMLElement;
}

public getFieldButton(): HTMLElement {
const element = this.getElement();
return element.querySelector<HTMLElement>(`.${CLASSES.itemField}`) as HTMLElement;
}

public getOperationButton(): HTMLElement {
const element = this.getElement();
return element.querySelector<HTMLElement>(`.${CLASSES.itemOperation}`) as HTMLElement;
}

public getTreeView(): TreeViewModel {
const popups = Array.from(document.body.querySelectorAll<HTMLElement>(`.${CLASSES.popupWrapper}`));
const treeViewPopup = popups.find((popup) => popup.querySelector(`.${CLASSES.treeView}`));
const treeViewElement = treeViewPopup?.querySelector<HTMLElement>(`.${CLASSES.treeView}`);

return new TreeViewModel(treeViewElement as HTMLElement);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,12 @@ class FilterBuilder extends Widget<any> {

_getGroupOperations(criteria) {
let groupOperations = this.option('groupOperations');
const groupOperationDescriptions = this.option('groupOperationDescriptions');
const groupOperationDescriptions = {
and: this.option('groupOperationDescriptions.and') ?? messageLocalization.format('dxFilterBuilder-and'),
or: this.option('groupOperationDescriptions.or') ?? messageLocalization.format('dxFilterBuilder-or'),
notAnd: this.option('groupOperationDescriptions.notAnd') ?? messageLocalization.format('dxFilterBuilder-notAnd'),
notOr: this.option('groupOperationDescriptions.notOr') ?? messageLocalization.format('dxFilterBuilder-notOr'),
};

if (!groupOperations || !groupOperations.length) {
groupOperations = [getGroupValue(criteria).replace('!', 'not')];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import type { Column } from '@js/ui/data_grid';
import DataGrid from '@js/ui/data_grid';
import { DataGridBaseModel } from '@ts/grids/grid_core/__tests__/__mock__/model/data_grid_base';

import { GridCoreModel } from '../../../../grid_core/__tests__/__mock__/model/grid_core';

export class DataGridModel extends GridCoreModel<DataGrid> {
export class DataGridModel extends DataGridBaseModel<DataGrid> {
protected NAME = 'dxDataGrid';

public getInstance(): DataGrid {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,22 @@
import { PopupModel } from '@ts/ui/__tests__/__mock__/model/popup';
import { TreeViewModel } from '@ts/ui/__tests__/__mock__/model/tree_view';

const CLASSES = {
columnChooser: 'dx-datagrid-column-chooser',
columnChooserList: 'dx-datagrid-column-chooser-list',
popupWrapper: 'dx-popup-wrapper',
};
export class ColumnChooserModel extends PopupModel {
private readonly columnChooserListClass: string;

export class ColumnChooserModel {
constructor(protected readonly root: HTMLElement) {}

private getPopupWrapper(): HTMLElement | null {
return document.body.querySelector(`.${CLASSES.popupWrapper}.${CLASSES.columnChooser}`);
}

private getOverlay(): HTMLElement | null {
const wrapper = this.getPopupWrapper();
return wrapper?.querySelector('.dx-overlay-content') ?? null;
constructor(widgetName: string) {
super();
this.columnChooserListClass = `dx-${widgetName}-column-chooser-list`;
}

private getTreeView(): TreeViewModel | null {
const overlay = this.getOverlay();
const overlay = this.getOverlayContent();
if (!overlay) return null;

const treeViewElement = overlay.querySelector(`.${CLASSES.columnChooserList}`) as HTMLElement;
const treeViewElement = overlay.querySelector(`.${this.columnChooserListClass}`) as HTMLElement;
return treeViewElement ? new TreeViewModel(treeViewElement) : null;
}

public isVisible(): boolean {
return this.getOverlay() !== null;
}

public searchColumn(text: string): void {
const treeView = this.getTreeView();
treeView?.setSearchValue(text);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PopupModel } from '@ts/ui/__tests__/__mock__/model/popup';

const SELECTORS = {
dialogMessage: 'dx-dialog-message',
cancelButton: '[aria-label="No"]',
};

export class ConfirmationDialogModel extends PopupModel {
public getMessage(): string {
const overlay = this.getOverlayContent();
const messageElement = overlay.querySelector(`.${SELECTORS.dialogMessage}`) as HTMLElement;
return messageElement.textContent ?? '';
}

public getCancelButton(): HTMLElement {
const element = this.getElement();
return element.querySelector(SELECTORS.cancelButton) as HTMLElement;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { GridBase } from '@js/common/grids';

import { GridCoreModel } from './grid_core';

export abstract class DataGridBaseModel<
TInstance extends GridBase = GridBase,
> extends GridCoreModel<TInstance> {
public apiColumnOption(id: string, name?: string, value?: any): any {
const instance = this.getInstance();

switch (arguments.length) {
case 1:
return instance.columnOption(id);
case 2:
return instance.columnOption(id, name);
default:
instance.columnOption(id, name as string, value);
return undefined;
}
}

public async apiRefresh(): Promise<void> {
await this.getInstance().refresh();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { PopupModel } from '../../../../../ui/__tests__/__mock__/model/popup';

const SELECTORS = {
textEditorInput: 'dx-texteditor-input',
item: 'dx-item',
toolbar: 'dx-toolbar',
saveButton: '[aria-label*="Save"]',
};

export class EditFormModel extends PopupModel {
constructor(protected readonly root: HTMLElement | null) {
super();
}

public getSaveButton(): HTMLElement {
const overlay = this.getOverlayContent();
const toolbar = overlay?.querySelector(`.${SELECTORS.toolbar}`);
return toolbar?.querySelector(SELECTORS.saveButton) as HTMLElement;
}

public getItem(id: string): HTMLElement | null {
return this.root?.querySelector(`.${SELECTORS.textEditorInput}[id*=_${id}]`) ?? null;
}

public getItems(): NodeListOf<HTMLElement> | null {
return this.root?.querySelectorAll(`.${SELECTORS.item}`) ?? null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { CheckBoxModel } from '../../../../../ui/__tests__/__mock__/model/checkbox';

export class FilterPanelModel {
private readonly filterPanelClass: string;

private readonly filterPanelTextClass: string;

private readonly filterPanelClearFilterClass: string;

private readonly filterPanelCheckboxClass: string;

private readonly root: HTMLElement;

constructor(root: HTMLElement, prefix: string) {
this.filterPanelClass = `dx-${prefix}-filter-panel`;
this.filterPanelTextClass = `dx-${prefix}-filter-panel-text`;
this.filterPanelClearFilterClass = `dx-${prefix}-filter-panel-clear-filter`;
this.filterPanelCheckboxClass = `dx-${prefix}-filter-panel-checkbox`;
this.root = root;
}

public getElement(): HTMLElement {
return this.root.querySelector(`.${this.filterPanelClass}`) as HTMLElement;
}

public getCreateFilterButton(): HTMLElement {
return this.getElement().querySelector(`.${this.filterPanelTextClass}`) as HTMLElement;
}

public getClearFilterButton(): HTMLElement {
return this.getElement().querySelector(`.${this.filterPanelClearFilterClass}`) as HTMLElement;
}

public getEnableFilterCheckbox(): CheckBoxModel {
const checkboxElement = this.getElement().querySelector(`.${this.filterPanelCheckboxClass}`) as HTMLElement;
return new CheckBoxModel(checkboxElement);
}

public isVisible(): boolean {
const element = this.getElement();
return element !== null && element.style.display !== 'none';
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,43 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { GridBase } from '@js/common/grids';
import type { dxElementWrapper } from '@js/core/renderer';
import $ from '@js/core/renderer';
import type CardView from '@js/ui/card_view';
import { FilterBuilderModel } from '@ts/filter_builder/__tests__/__mock__/model/filter_builder';
import { PagerModel } from '@ts/pagination/__tests__/__mock__/model/pager';
import { LoadPanelModel } from '@ts/ui/__tests__/__mock__/model/load_panel';

import { DataCellModel } from './cell/data_cell';
import { HeaderCellModel } from './cell/header_cell';
import { ColumnChooserModel } from './column_chooser';
import { ConfirmationDialogModel } from './confirmation_dialog';
import { EditFormModel } from './edit_form';
import { FilterPanelModel } from './filter_panel';
import { DataRowModel } from './row/data_row';

const SELECTORS = {
headerRowClass: 'dx-header-row',
dataRowClass: 'dx-data-row',
groupRowClass: 'dx-group-row',
loadPanel: 'dx-loadpanel',
editForm: 'edit-form',
headerCellIndicators: 'dx-column-indicators',
headerCellFilter: 'dx-header-filter',
revertButton: 'dx-revert-button',
};

export abstract class GridCoreModel<TInstance extends GridBase = GridBase> {
export abstract class GridCoreModel<TInstance = GridBase | CardView> {
protected abstract NAME: string;

constructor(protected readonly root: HTMLElement) {}

private getWidgetName(): string {
return this.NAME.slice(2).toLowerCase();
}

protected getFilterPanelPrefix(): string {
return this.getWidgetName();
}

public getHeaderCells(): NodeListOf<HTMLElement> {
return this.root.querySelectorAll(`.${SELECTORS.headerRowClass} > td`);
}
Expand All @@ -39,18 +54,6 @@ export abstract class GridCoreModel<TInstance extends GridBase = GridBase> {
return this.root.querySelectorAll(`.${SELECTORS.groupRowClass}`);
}

public apiColumnOption(id: string, name?: string, value?: any): any {
switch (arguments.length) {
case 1:
return this.getInstance().columnOption(id);
case 2:
return this.getInstance().columnOption(id, name);
default:
this.getInstance().columnOption(id, name as string, value);
return undefined;
}
}

public getHeaderByText(text: string): dxElementWrapper {
return $(Array.from(this.getHeaderCells()).find((el) => $(el).text().includes(text)));
}
Expand Down Expand Up @@ -79,13 +82,50 @@ export abstract class GridCoreModel<TInstance extends GridBase = GridBase> {
}

public addWidgetPrefix(classNames: string): string {
const componentName = this.NAME;
const widgetName = this.getWidgetName();
return `dx-${widgetName}${classNames ? `-${classNames}` : ''}`;
}

public getLoadPanel(): LoadPanelModel {
return new LoadPanelModel(document.body.querySelector(`.${SELECTORS.loadPanel}`));
}

return `dx-${componentName.slice(2).toLowerCase()}${classNames ? `-${classNames}` : ''}`;
public getEditForm(): EditFormModel {
return new EditFormModel(this.root.querySelector(`.${this.addWidgetPrefix(SELECTORS.editForm)}`));
}

public getColumnChooser(): ColumnChooserModel {
return new ColumnChooserModel(this.root);
return new ColumnChooserModel(this.getWidgetName());
}

public getFilterPanel(): FilterPanelModel {
return new FilterPanelModel(this.root, this.getFilterPanelPrefix());
}

public getFilterBuilder(): FilterBuilderModel {
return new FilterBuilderModel();
}

public getPager(): PagerModel {
return new PagerModel(this.root);
}

public getConfirmationDialog(): ConfirmationDialogModel {
return new ConfirmationDialogModel();
}

public apiOption(name: string): unknown;
public apiOption(name: string, value: unknown): void;
public apiOption(name: string, value?: unknown): unknown {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const instance = this.getInstance() as any;

if (arguments.length === 1) {
return instance.option(name);
}

instance.option(name, value);
return undefined;
}

public getHeaderCellFilter(columnIndex: number): dxElementWrapper {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { PopupModel } from '@ts/ui/__tests__/__mock__/model/popup';

const CLASSES = {
headerFilterMenu: 'dx-header-filter-menu',
listItemContent: 'dx-list-item-content',
};

const SELECTORS = {
okButton: '[role="button"][aria-label*="OK"]',
};

export class HeaderFilterModel extends PopupModel {
public getOKButton(): HTMLElement {
const popup = this.getPopupWrapper();
return popup?.querySelector(SELECTORS.okButton) as HTMLElement;
}

public getListItems(): HTMLElement[] {
const popup = this.getPopupWrapper();
const listItems = popup?.querySelectorAll(`.${CLASSES.listItemContent}`);
return Array.from(listItems ?? []) as HTMLElement[];
}

public getListItem(index: number): HTMLElement {
const listItems = this.getListItems();
return listItems[index];
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import messageLocalization from '@js/common/core/localization/message';
import type { ColumnChooser } from '@js/common/grids';
import messageLocalization from '@js/localization/message';

export const defaultOptions = {
columnChooser: {
Expand Down
Loading
Loading