From 525c4fd005967283f634834dce2da9679dd5efe7 Mon Sep 17 00:00:00 2001 From: Roman Semenov Date: Sat, 7 Dec 2024 20:10:00 +0400 Subject: [PATCH] inprogress --- .../content_view/content/card/card.tsx | 11 +- .../new/card_view/content_view/options.ts | 7 + .../grids/new/card_view/content_view/view.tsx | 24 ++- .../data_controller/data_controller.ts | 13 +- .../new/grid_core/data_controller/utils.ts | 20 ++ .../options_controller_base.ts | 11 +- packages/devextreme/playground/jquery.html | 188 ++++++++++++++---- 7 files changed, 220 insertions(+), 54 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/new/card_view/content_view/content/card/card.tsx b/packages/devextreme/js/__internal/grids/new/card_view/content_view/content/card/card.tsx index e2a771d89f0b..c8fd437b7f6d 100644 --- a/packages/devextreme/js/__internal/grids/new/card_view/content_view/content/card/card.tsx +++ b/packages/devextreme/js/__internal/grids/new/card_view/content_view/content/card/card.tsx @@ -2,6 +2,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { DataRow } from '@ts/grids/new/grid_core/columns_controller/types'; import { PureComponent } from '@ts/grids/new/grid_core/core/pure_component'; +import type { DataObject } from '@ts/grids/new/grid_core/data_controller/types'; import { CollectionController } from '@ts/grids/new/grid_core/keyboard_navigation/collection_controller'; import type { InfernoNode, RefObject } from 'inferno'; import { createRef } from 'inferno'; @@ -34,9 +35,9 @@ export interface CardProps { row: DataRow; cover?: { - imageExpr?: string; + imageExpr?: (data: DataObject) => string; - altExpr?: string; + altExpr?: (data: DataObject) => string; }; elementRef?: RefObject; @@ -99,8 +100,8 @@ export class Card extends PureComponent { hoverStateEnabled ? CLASSES.cardHover : '', ].filter(Boolean).join(' '); - const imageSrc = cover?.imageExpr && this.props.row.data[cover.imageExpr] as string; - const alt = cover?.altExpr && this.props.row.data[cover.altExpr] as string; + const imageSrc = cover?.imageExpr?.(this.props.row.data); + const alt = cover?.altExpr?.(this.props.row.data); return (
{ + {imageSrc && ( + )} {this.props.row.cells.map((cell, index) => ( ; + + cardCover?: { + imageExpr: string | ((data: DataObject) => string); + altExpr: string | ((data: DataObject) => string); + }; } export const defaultOptions = { diff --git a/packages/devextreme/js/__internal/grids/new/card_view/content_view/view.tsx b/packages/devextreme/js/__internal/grids/new/card_view/content_view/view.tsx index 5ef8f2d36366..6249d9fb336f 100644 --- a/packages/devextreme/js/__internal/grids/new/card_view/content_view/view.tsx +++ b/packages/devextreme/js/__internal/grids/new/card_view/content_view/view.tsx @@ -1,6 +1,8 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable spellcheck/spell-checker */ +import { compileGetter } from '@js/core/utils/data'; +import { isDefined } from '@js/core/utils/type'; import type dxScrollable from '@js/ui/scroll_view/ui.scrollable'; import type { ScrollEventInfo } from '@js/ui/scroll_view/ui.scrollable'; import { combined, computed, state } from '@ts/core/reactive/index'; @@ -12,6 +14,7 @@ import { DataController } from '@ts/grids/new/grid_core/data_controller'; import { ErrorController } from '@ts/grids/new/grid_core/error_controller/error_controller'; import { createRef } from 'inferno'; +import type { DataObject } from '../../grid_core/data_controller/types'; import type { ContentViewProps } from './content_view'; import { ContentView as ContentViewComponent } from './content_view'; @@ -144,7 +147,16 @@ export class ContentView extends View { onDblClick: this.options.action('onCardDblClick'), onHoverChanged: this.options.action('onCardHoverChanged'), onPrepared: this.options.action('onCardPrepared'), - cover: this.options.oneWay('cardCover'), + cover: combined({ + imageExpr: computed( + (imageExpr) => this.processExpr(imageExpr), + [this.options.oneWay('cardCover.imageExpr')], + ), + altExpr: computed( + (altExpr) => this.processExpr(altExpr), + [this.options.oneWay('cardCover.altExpr')], + ), + }), // eslint-disable-next-line @typescript-eslint/no-explicit-any toolbar: this.options.oneWay('cardHeader.items') as any, }), @@ -173,6 +185,16 @@ export class ContentView extends View { }); } + private processExpr( + expr: T | ((data: DataObject) => T) | undefined, + ): ((data: DataObject) => T) | undefined { + if (!isDefined(expr)) { + return undefined; + } + // @ts-expect-error + return compileGetter(expr); + } + private onScroll(e: ScrollEventInfo): void { this.scrollTop.update(e.scrollOffset.top); } diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/data_controller/data_controller.ts b/packages/devextreme/js/__internal/grids/new/grid_core/data_controller/data_controller.ts index d4f23dcc8e0a..343ebf5cf465 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/data_controller/data_controller.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/data_controller/data_controller.ts @@ -10,7 +10,7 @@ import { // import type { Change } from '../editing/types'; import { OptionsController } from '../options_controller/options_controller'; import type { DataObject } from './types'; -import { normalizeDataSource } from './utils'; +import { normalizeDataSource, updateItemsImmutable } from './utils'; export class DataController { private readonly dataSourceConfiguration = this.options.oneWay('dataSource'); @@ -61,8 +61,15 @@ export class DataController { ) { effect( (dataSource) => { - const changedCallback = (): void => { - this._items.update(dataSource.items()); + const changedCallback = (e?): void => { + let items = dataSource.items() as DataObject[]; + + if (e?.changes) { + items = this._items.unreactive_get(); + items = updateItemsImmutable(items, e.changes, dataSource.store()); + } + + this._items.update(items); this.pageIndex.update(dataSource.pageIndex()); this.pageSize.update(dataSource.pageSize()); this._totalCount.update(dataSource.totalCount()); diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/data_controller/utils.ts b/packages/devextreme/js/__internal/grids/new/grid_core/data_controller/utils.ts index f0365867d31f..4fa3c0239553 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/data_controller/utils.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/data_controller/utils.ts @@ -1,6 +1,12 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ import type { DataSourceLike } from '@js/data/data_source'; import DataSource from '@js/data/data_source'; import { normalizeDataSourceOptions } from '@js/data/data_source/utils'; +import { applyBatch } from '@ts/data/m_array_utils'; + +import type { DataObject } from './types'; export function normalizeDataSource( dataSourceLike: DataSourceLike | null | undefined, @@ -24,3 +30,17 @@ export function normalizeDataSource( // TODO: research making second param not required return new DataSource(normalizeDataSourceOptions(dataSourceLike, undefined)); } + +export function updateItemsImmutable( + data: DataObject[], + changes: any[], + keyInfo: any, +): DataObject[] { + // @ts-expect-error + return applyBatch({ + keyInfo, + data, + changes, + immutable: true, + }); +} diff --git a/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/options_controller_base.ts b/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/options_controller_base.ts index e558af583d2e..4f8cb64fe4ad 100644 --- a/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/options_controller_base.ts +++ b/packages/devextreme/js/__internal/grids/new/grid_core/options_controller/options_controller_base.ts @@ -111,10 +111,12 @@ export class OptionsController { const obs = computed( (props) => { const value = getValue(props, name); - // NOTE: it is better not to use '??' operator, - // because result will be different if value is 'null'. - // Some code works differently if undefined is passed instead of null, - // for example dataSource getter-setter .filter() + /* + NOTE: it is better not to use '??' operator, + because result will be different if value is 'null'. + Some code works differently if undefined is passed instead of null, + for example dataSource's getter-setter `.filter()` + */ return value !== undefined ? value : getValue(this.defaults, name); }, [this.props], @@ -125,7 +127,6 @@ export class OptionsController { public twoWay( name: TProp, - // eslint-disable-next-line max-len ): SubsGetsUpd> { const obs = state(this.component.option(name)); this.oneWay(name).subscribe(obs.update.bind(obs) as any); diff --git a/packages/devextreme/playground/jquery.html b/packages/devextreme/playground/jquery.html index 37c66c90874b..d6710a2aec96 100644 --- a/packages/devextreme/playground/jquery.html +++ b/packages/devextreme/playground/jquery.html @@ -59,6 +59,107 @@

Te