From df86941ac2148e6a940325a051c4382c9959a4d9 Mon Sep 17 00:00:00 2001 From: huanhuanwa <2323666215@qq.com> Date: Mon, 29 Jul 2024 17:09:15 +0800 Subject: [PATCH 1/4] feat(core): add set_field action #WIK-16194 --- .../field-menu/field-menu.component.ts | 9 +++--- .../field-property-editor.component.html | 2 +- .../field-property-editor.component.ts | 7 +++-- packages/grid/src/constants/field.ts | 7 +++-- packages/grid/src/core/action/field.ts | 30 ++++++++++++++++++- packages/grid/src/core/action/general.ts | 11 +++++++ packages/grid/src/core/types/action.ts | 16 ++++++++-- packages/grid/src/core/utils/queries.ts | 7 +++++ packages/grid/src/grid.component.html | 4 +-- packages/grid/src/types/field.ts | 2 +- 10 files changed, 79 insertions(+), 16 deletions(-) diff --git a/packages/grid/src/components/field-menu/field-menu.component.ts b/packages/grid/src/components/field-menu/field-menu.component.ts index fd49f9de..5c99b46e 100644 --- a/packages/grid/src/components/field-menu/field-menu.component.ts +++ b/packages/grid/src/components/field-menu/field-menu.component.ts @@ -1,6 +1,6 @@ -import { Component, ChangeDetectionStrategy, Input, ElementRef, signal } from '@angular/core'; +import { Component, ChangeDetectionStrategy, Input, ElementRef, signal, Signal } from '@angular/core'; import { AITableFieldMenu } from '../../types/field'; -import { AITableField, AITable } from '../../core'; +import { AITable } from '../../core'; import { ThyDropdownMenuItemDirective, ThyDropdownMenuItemNameDirective, @@ -9,6 +9,7 @@ import { } from 'ngx-tethys/dropdown'; import { ThyIcon } from 'ngx-tethys/icon'; import { ThyDivider } from 'ngx-tethys/divider'; +import { AITableField, getRecordOrField } from '@ai-table/grid'; @Component({ selector: 'field-menu', @@ -25,7 +26,7 @@ import { ThyDivider } from 'ngx-tethys/divider'; ] }) export class FieldMenu { - @Input({ required: true }) field!: AITableField; + @Input({ required: true }) fieldId!: string; @Input({ required: true }) aiTable!: AITable; @@ -34,7 +35,7 @@ export class FieldMenu { @Input() origin!: HTMLElement | ElementRef; execute(menu: AITableFieldMenu) { - const field = signal({ ...this.field }); + const field = getRecordOrField(this.aiTable.fields, this.fieldId) as Signal; menu.exec && menu.exec(this.aiTable, field, this.origin); } } diff --git a/packages/grid/src/components/field-property-editor/field-property-editor.component.html b/packages/grid/src/components/field-property-editor/field-property-editor.component.html index aa8370fb..23316f8f 100644 --- a/packages/grid/src/components/field-property-editor/field-property-editor.component.html +++ b/packages/grid/src/components/field-property-editor/field-property-editor.component.html @@ -3,7 +3,7 @@ item.id === this.aiField().id); + Actions.setField(this.aiTable, this.aiField(), [path]); } else { Actions.addField(this.aiTable, this.aiField(), [this.aiTable.fields().length]); } diff --git a/packages/grid/src/constants/field.ts b/packages/grid/src/constants/field.ts index 44d9cec6..6e3f69a3 100644 --- a/packages/grid/src/constants/field.ts +++ b/packages/grid/src/constants/field.ts @@ -1,7 +1,7 @@ import { AITable, AITableField } from '../core'; import { AITableFieldMenu } from '../types/field'; import { AI_TABLE_GRID_FIELD_SERVICE_MAP } from '../services/field.service'; -import { ElementRef, WritableSignal } from '@angular/core'; +import { ElementRef, signal, Signal, WritableSignal } from '@angular/core'; export const DividerMenuItem = { id: 'divider' @@ -11,9 +11,10 @@ export const EditFieldPropertyItem = { id: 'editFieldProperty', name: '编辑列', icon: 'edit', - exec: (aiTable: AITable, field: WritableSignal, origin?: HTMLElement | ElementRef) => { + exec: (aiTable: AITable, field: Signal, origin?: HTMLElement | ElementRef) => { const fieldService = AI_TABLE_GRID_FIELD_SERVICE_MAP.get(aiTable); - origin && fieldService?.editFieldProperty(origin, aiTable, field, true); + const copyField: WritableSignal = signal(JSON.parse(JSON.stringify(field()))); + origin && fieldService?.editFieldProperty(origin, aiTable, copyField, true); } }; diff --git a/packages/grid/src/core/action/field.ts b/packages/grid/src/core/action/field.ts index 83e9b66d..b9d3238d 100644 --- a/packages/grid/src/core/action/field.ts +++ b/packages/grid/src/core/action/field.ts @@ -1,4 +1,5 @@ import { ActionName, AddFieldAction, AIFieldPath, AITable, AITableField } from '../types'; +import { AITableQueries } from '../utils'; export function addField(aiTable: AITable, field: AITableField, path: AIFieldPath) { const operation: AddFieldAction = { @@ -9,6 +10,33 @@ export function addField(aiTable: AITable, field: AITableField, path: AIFieldPat aiTable.apply(operation); } +export function setField(aiTable: AITable, value: Partial, path: AIFieldPath) { + const node = AITableQueries.getField(aiTable, path); + if (node) { + const field: Partial = {}; + const newField: Partial = {}; + for (const k in value) { + if (node[k] !== value[k]) { + if (node.hasOwnProperty(k)) { + field[k] = node[k]; + } + newField[k] = value[k]; + } + } + + const operation: SetFieldAction = { + type: ActionName.SetField, + field, + newField, + path + }; + + aiTable.apply(operation); + } +} + + export const FieldActions = { - addField + addField, + setField }; diff --git a/packages/grid/src/core/action/general.ts b/packages/grid/src/core/action/general.ts index a789381d..1028850b 100644 --- a/packages/grid/src/core/action/general.ts +++ b/packages/grid/src/core/action/general.ts @@ -28,6 +28,17 @@ const apply = (aiTable: AITable, records: AITableRecords, fields: AITableFields, }; }); } + + case ActionName.SetField: { + const [fieldIndex] = options.path; + if (fieldIndex > -1) { + fields.splice(fieldIndex, 1, { + ...fields[fieldIndex], + ...options.newField + }); + } + break; + } } return { records, diff --git a/packages/grid/src/core/types/action.ts b/packages/grid/src/core/types/action.ts index 0444151a..a5f6819e 100644 --- a/packages/grid/src/core/types/action.ts +++ b/packages/grid/src/core/types/action.ts @@ -11,7 +11,8 @@ export type Path = AIRecordPath | AIFieldPath | AIFieldValuePath; export enum ActionName { UpdateFieldValue = 'update_field_value', AddRecord = 'add_record', - AddField = 'add_field' + AddField = 'add_field', + SetField = 'set_field' } export enum ExecuteType { @@ -39,4 +40,15 @@ export type AddFieldAction = { field: AITableField; }; -export type AITableAction = UpdateFieldValueAction | AddRecordAction | AddFieldAction; +export type SetFieldAction = { + type: ActionName.SetField; + path: AIFieldPath; + field: Partial; + newField: Partial; +}; + +export type AITableAction = + | UpdateFieldValueAction + | AddRecordAction + | AddFieldAction + | SetFieldAction; diff --git a/packages/grid/src/core/utils/queries.ts b/packages/grid/src/core/utils/queries.ts index ae96d4bc..8df4a198 100644 --- a/packages/grid/src/core/utils/queries.ts +++ b/packages/grid/src/core/utils/queries.ts @@ -32,5 +32,12 @@ export const AITableQueries = { throw new Error(`can not find field at path [${path}]`); } return aiTable.records()[path[0]].value[field.id]; + }, + + getField(aiTable: AITable, path: AIFieldPath): AITableField { + if (!aiTable) { + throw new Error(`aiTable does not exist [${path}]`); + } + return aiTable.fields()[path[0]]; } }; diff --git a/packages/grid/src/grid.component.html b/packages/grid/src/grid.component.html index 9ee30bb3..7977947a 100644 --- a/packages/grid/src/grid.component.html +++ b/packages/grid/src/grid.component.html @@ -10,13 +10,13 @@ [ngClass]="{ highlight: aiTable.selection().selectedFields.has(field.id) }" [ngStyle]="{ width: field.width + 'px' }" > - + {{ field.name }} - + diff --git a/packages/grid/src/types/field.ts b/packages/grid/src/types/field.ts index c6881034..c8a24304 100644 --- a/packages/grid/src/types/field.ts +++ b/packages/grid/src/types/field.ts @@ -5,7 +5,7 @@ export interface AITableFieldMenu { id: string; name?: string; icon?: string; - exec?: (aiTable: AITable, field: WritableSignal, origin?: HTMLElement | ElementRef) => void; + exec?: (aiTable: AITable, field: Signal, origin?: HTMLElement | ElementRef) => void; hidden?: (aiTable: AITable, field: Signal) => boolean; disabled?: (aiTable: AITable, field: Signal) => boolean; } From 64b1f94eddf6ecae73a156e0fbd56498bb71e794 Mon Sep 17 00:00:00 2001 From: huanhuanwa <2323666215@qq.com> Date: Mon, 29 Jul 2024 17:13:11 +0800 Subject: [PATCH 2/4] feat(core): optimize code #WIK-16194 --- packages/grid/src/core/action/field.ts | 2 +- packages/grid/src/core/action/general.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/grid/src/core/action/field.ts b/packages/grid/src/core/action/field.ts index b9d3238d..59ba3120 100644 --- a/packages/grid/src/core/action/field.ts +++ b/packages/grid/src/core/action/field.ts @@ -1,4 +1,4 @@ -import { ActionName, AddFieldAction, AIFieldPath, AITable, AITableField } from '../types'; +import { ActionName, AddFieldAction, AIFieldPath, AITable, AITableField, SetFieldAction } from '../types'; import { AITableQueries } from '../utils'; export function addField(aiTable: AITable, field: AITableField, path: AIFieldPath) { diff --git a/packages/grid/src/core/action/general.ts b/packages/grid/src/core/action/general.ts index 1028850b..f6a8b78a 100644 --- a/packages/grid/src/core/action/general.ts +++ b/packages/grid/src/core/action/general.ts @@ -27,6 +27,7 @@ const apply = (aiTable: AITable, records: AITableRecords, fields: AITableFields, ...newRecord }; }); + break; } case ActionName.SetField: { From fee3e3d77152a50bb36dc3d0ebdedb92b1db9af9 Mon Sep 17 00:00:00 2001 From: huanhuanwa <2323666215@qq.com> Date: Mon, 29 Jul 2024 17:27:18 +0800 Subject: [PATCH 3/4] fix: fix build:error --- .../grid/src/components/field-menu/field-menu.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/grid/src/components/field-menu/field-menu.component.ts b/packages/grid/src/components/field-menu/field-menu.component.ts index 5c99b46e..bc01857d 100644 --- a/packages/grid/src/components/field-menu/field-menu.component.ts +++ b/packages/grid/src/components/field-menu/field-menu.component.ts @@ -1,6 +1,6 @@ import { Component, ChangeDetectionStrategy, Input, ElementRef, signal, Signal } from '@angular/core'; import { AITableFieldMenu } from '../../types/field'; -import { AITable } from '../../core'; +import { AITable, AITableField } from '../../core'; import { ThyDropdownMenuItemDirective, ThyDropdownMenuItemNameDirective, @@ -9,7 +9,7 @@ import { } from 'ngx-tethys/dropdown'; import { ThyIcon } from 'ngx-tethys/icon'; import { ThyDivider } from 'ngx-tethys/divider'; -import { AITableField, getRecordOrField } from '@ai-table/grid'; +import { getRecordOrField } from '../../utils'; @Component({ selector: 'field-menu', From f414ba62b0423f5b6427cb5f77233992ac72996a Mon Sep 17 00:00:00 2001 From: huanhuanwa <2323666215@qq.com> Date: Tue, 30 Jul 2024 15:53:09 +0800 Subject: [PATCH 4/4] feat: optimzie code --- .../components/field-menu/field-menu.component.ts | 6 +++--- packages/grid/src/constants/field.ts | 4 ++-- packages/grid/src/core/action/field.ts | 15 +++++++-------- packages/grid/src/core/action/record.ts | 6 +++--- packages/grid/src/core/utils/queries.ts | 14 ++++++++++---- packages/grid/src/grid.component.ts | 4 ++-- packages/grid/src/types/field.ts | 4 ++-- packages/grid/src/types/grid.ts | 4 ++-- 8 files changed, 31 insertions(+), 26 deletions(-) diff --git a/packages/grid/src/components/field-menu/field-menu.component.ts b/packages/grid/src/components/field-menu/field-menu.component.ts index bc01857d..1b7bc2ba 100644 --- a/packages/grid/src/components/field-menu/field-menu.component.ts +++ b/packages/grid/src/components/field-menu/field-menu.component.ts @@ -1,5 +1,5 @@ import { Component, ChangeDetectionStrategy, Input, ElementRef, signal, Signal } from '@angular/core'; -import { AITableFieldMenu } from '../../types/field'; +import { AITableFieldMenuItem } from '../../types/field'; import { AITable, AITableField } from '../../core'; import { ThyDropdownMenuItemDirective, @@ -30,11 +30,11 @@ export class FieldMenu { @Input({ required: true }) aiTable!: AITable; - @Input({ required: true }) fieldMenus!: AITableFieldMenu[]; + @Input({ required: true }) fieldMenus!: AITableFieldMenuItem[]; @Input() origin!: HTMLElement | ElementRef; - execute(menu: AITableFieldMenu) { + execute(menu: AITableFieldMenuItem) { const field = getRecordOrField(this.aiTable.fields, this.fieldId) as Signal; menu.exec && menu.exec(this.aiTable, field, this.origin); } diff --git a/packages/grid/src/constants/field.ts b/packages/grid/src/constants/field.ts index 6e3f69a3..50d4489c 100644 --- a/packages/grid/src/constants/field.ts +++ b/packages/grid/src/constants/field.ts @@ -1,5 +1,5 @@ import { AITable, AITableField } from '../core'; -import { AITableFieldMenu } from '../types/field'; +import { AITableFieldMenuItem } from '../types/field'; import { AI_TABLE_GRID_FIELD_SERVICE_MAP } from '../services/field.service'; import { ElementRef, signal, Signal, WritableSignal } from '@angular/core'; @@ -18,4 +18,4 @@ export const EditFieldPropertyItem = { } }; -export const DefaultFieldMenus: AITableFieldMenu[] = [EditFieldPropertyItem]; +export const DefaultFieldMenus: AITableFieldMenuItem[] = [EditFieldPropertyItem]; diff --git a/packages/grid/src/core/action/field.ts b/packages/grid/src/core/action/field.ts index 59ba3120..377c842c 100644 --- a/packages/grid/src/core/action/field.ts +++ b/packages/grid/src/core/action/field.ts @@ -11,14 +11,14 @@ export function addField(aiTable: AITable, field: AITableField, path: AIFieldPat } export function setField(aiTable: AITable, value: Partial, path: AIFieldPath) { - const node = AITableQueries.getField(aiTable, path); - if (node) { - const field: Partial = {}; + const field = AITableQueries.getField(aiTable, path); + if (field) { + const oldField: Partial = {}; const newField: Partial = {}; for (const k in value) { - if (node[k] !== value[k]) { - if (node.hasOwnProperty(k)) { - field[k] = node[k]; + if (field[k] !== value[k]) { + if (field.hasOwnProperty(k)) { + oldField[k] = field[k]; } newField[k] = value[k]; } @@ -26,7 +26,7 @@ export function setField(aiTable: AITable, value: Partial, path: A const operation: SetFieldAction = { type: ActionName.SetField, - field, + field: oldField, newField, path }; @@ -35,7 +35,6 @@ export function setField(aiTable: AITable, value: Partial, path: A } } - export const FieldActions = { addField, setField diff --git a/packages/grid/src/core/action/record.ts b/packages/grid/src/core/action/record.ts index 3d79a7cd..b8f5d41c 100644 --- a/packages/grid/src/core/action/record.ts +++ b/packages/grid/src/core/action/record.ts @@ -2,11 +2,11 @@ import { ActionName, AddRecordAction, AIRecordPath, UpdateFieldValueAction, AITa import { AITableQueries } from '../utils'; export function updateFieldValue(aiTable: AITable, value: any, path: AIFieldValuePath) { - const node = AITableQueries.getFieldValue(aiTable, path); - if (node !== value) { + const field = AITableQueries.getFieldValue(aiTable, path); + if (field !== value) { const operation: UpdateFieldValueAction = { type: ActionName.UpdateFieldValue, - fieldValue: node, + fieldValue: field, newFieldValue: value, path }; diff --git a/packages/grid/src/core/utils/queries.ts b/packages/grid/src/core/utils/queries.ts index 7f91cb6b..379a1407 100644 --- a/packages/grid/src/core/utils/queries.ts +++ b/packages/grid/src/core/utils/queries.ts @@ -18,13 +18,16 @@ export const AITableQueries = { }, getFieldValue(aiTable: AITable, path: [number, number]): any { if (!aiTable) { - throw new Error(`aiTable does not exist [${path}]`); + throw new Error(`aiTable does not exist`); } if (!aiTable.records()) { - throw new Error(`aiTable has no records [${path}]`); + throw new Error(`aiTable has no records`); } if (!aiTable.fields()) { - throw new Error(`aiTable has no fields [${path}]`); + throw new Error(`aiTable has no fields`); + } + if (!path) { + throw new Error(`path does not exist as path [${path}]`); } const field = aiTable.fields()[path[1]]; @@ -36,7 +39,10 @@ export const AITableQueries = { getField(aiTable: AITable, path: AIFieldPath): AITableField { if (!aiTable) { - throw new Error(`aiTable does not exist [${path}]`); + throw new Error(`aiTable does not exist`); + } + if (!path) { + throw new Error(`path does not exist as path [${path}]`); } return aiTable.fields()[path[0]]; } diff --git a/packages/grid/src/grid.component.ts b/packages/grid/src/grid.component.ts index c438828b..a5cdc4b3 100644 --- a/packages/grid/src/grid.component.ts +++ b/packages/grid/src/grid.component.ts @@ -5,7 +5,7 @@ import { ThyTag } from 'ngx-tethys/tag'; import { ThyPopoverModule } from 'ngx-tethys/popover'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { buildGridData } from './utils'; -import { AIFieldConfig, AITableFieldMenu, AITableRowHeight } from './types'; +import { AIFieldConfig, AITableFieldMenuItem, AITableRowHeight } from './types'; import { Actions, createAITable, @@ -94,7 +94,7 @@ export class AITableGrid implements OnInit { aiTableInitialized = output(); - fieldMenus!: AITableFieldMenu[]; + fieldMenus!: AITableFieldMenuItem[]; gridData = computed(() => { return buildGridData(this.aiRecords(), this.aiFields(), this.aiTable.selection()); diff --git a/packages/grid/src/types/field.ts b/packages/grid/src/types/field.ts index c8a24304..a35ca0c2 100644 --- a/packages/grid/src/types/field.ts +++ b/packages/grid/src/types/field.ts @@ -1,7 +1,7 @@ -import { ElementRef, Signal, WritableSignal } from '@angular/core'; +import { ElementRef, Signal } from '@angular/core'; import { AITable, AITableField } from '../core'; -export interface AITableFieldMenu { +export interface AITableFieldMenuItem { id: string; name?: string; icon?: string; diff --git a/packages/grid/src/types/grid.ts b/packages/grid/src/types/grid.ts index 09f38c13..71a5f682 100644 --- a/packages/grid/src/types/grid.ts +++ b/packages/grid/src/types/grid.ts @@ -1,5 +1,5 @@ import { AITableField, AITableFieldType, AITableRecord } from '../core'; -import { AITableFieldMenu } from './field'; +import { AITableFieldMenuItem } from './field'; export enum AITableRowHeight { Short = 1, @@ -26,5 +26,5 @@ export interface AITableSelection { export interface AIFieldConfig { fieldRenderers?: Partial>; fieldPropertyEditor?: any; - fieldMenus?: AITableFieldMenu[]; + fieldMenus?: AITableFieldMenuItem[]; }