Skip to content

Commit

Permalink
feat(grid): support highlight the cell which match the keywords
Browse files Browse the repository at this point in the history
  • Loading branch information
minlovehua committed Dec 23, 2024
1 parent d23082c commit 22385ad
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/grid/src/constants/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const Colors = {
gray80: '#fafafa',
headSelectedBgColor: '#EAEFFA',
itemActiveBgColor: '#6698ff1a',
itemMatchBgColor: '#ff9f731a',
waring: '#ffcd5d',
success: '#73d897'
};
3 changes: 2 additions & 1 deletion packages/grid/src/core/types/ai-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ export interface AITable {
fields: WritableSignal<AITableFields>;
context?: RendererContext;
selection: WritableSignal<AITableSelection>;
matchedCells: WritableSignal<string[]>; // [`${recordId}-${fieldId}`]
recordsMap: Signal<{ [kay: string]: AITableRecord }>;
fieldsMap: Signal<{ [kay: string]: AITableField }>;
recordsWillHidden: WritableSignal<string[]>;
recordsWillMove: WritableSignal<string[]>
recordsWillMove: WritableSignal<string[]>;
}

export type AIPlugin = (aiTable: AITable) => AITable;
Expand Down
1 change: 1 addition & 0 deletions packages/grid/src/core/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function createAITable(records: WritableSignal<AITableRecords>, fields: W
selectedFields: new Map(),
selectedCells: new Map()
}),
matchedCells: signal([]),
recordsMap: computed(() => {
return records().reduce(
(object, item) => {
Expand Down
5 changes: 5 additions & 0 deletions packages/grid/src/grid-base.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { AI_TABLE_GRID_FIELD_SERVICE_MAP, AITableGridFieldService } from './serv
import { AITableGridSelectionService } from './services/selection.service';
import { AIFieldConfig, AITableFieldMenuItem, AITableContextMenuItem, AITableReferences } from './types';
import { AITableFieldPropertyEditor } from './components';
import { AITableGridMatchCellService } from './services/match-cell.service';

@Component({
selector: 'ai-table-grid-base',
Expand All @@ -59,6 +60,8 @@ export class AITableGridBase implements OnInit {

aiBuildRenderDataFn = input<(aiTable: AITable) => AITableValue>();

aiKeywords = input<string>();

AITableFieldType = AITableFieldType;

AITableSelectOptionStyle = AITableSelectOptionStyle;
Expand Down Expand Up @@ -99,6 +102,7 @@ export class AITableGridBase implements OnInit {
protected aiTableGridFieldService = inject(AITableGridFieldService);
protected aiTableGridEventService = inject(AITableGridEventService);
protected aiTableGridSelectionService = inject(AITableGridSelectionService);
protected aiTableGridMatchCellService = inject(AITableGridMatchCellService);

ngOnInit(): void {
this.initAITable();
Expand All @@ -116,6 +120,7 @@ export class AITableGridBase implements OnInit {
initService() {
this.aiTableGridEventService.initialize(this.aiTable, this.aiFieldConfig()?.fieldPropertyEditor);
this.aiTableGridSelectionService.initialize(this.aiTable);
this.aiTableGridMatchCellService.initialize(this.aiTable);
this.aiTableGridEventService.registerEvents(this.elementRef.nativeElement);
this.aiTableGridFieldService.initAIFieldConfig(this.aiFieldConfig());
AI_TABLE_GRID_FIELD_SERVICE_MAP.set(this.aiTable, this.aiTableGridFieldService);
Expand Down
11 changes: 10 additions & 1 deletion packages/grid/src/grid.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { AITableGridSelectionService } from './services/selection.service';
import { AITableMouseDownType, AITableRendererConfig, ScrollActionOptions } from './types';
import { buildGridLinearRows, getColumnIndicesMap, getDetailByTargetName, handleMouseStyle, isWindows } from './utils';
import { getMousePosition } from './utils/position';
import { AITableGridMatchCellService } from './services/match-cell.service';

@Component({
selector: 'ai-table-grid',
Expand All @@ -53,7 +54,7 @@ import { getMousePosition } from './utils/position';
class: 'ai-table-grid'
},
imports: [AITableRenderer],
providers: [AITableGridEventService, AITableGridFieldService, AITableGridSelectionService]
providers: [AITableGridEventService, AITableGridFieldService, AITableGridSelectionService, AITableGridMatchCellService]
})
export class AITableGrid extends AITableGridBase implements OnInit, OnDestroy {
private viewContainerRef = inject(ViewContainerRef);
Expand Down Expand Up @@ -147,6 +148,14 @@ export class AITableGrid extends AITableGridBase implements OnInit, OnDestroy {
this.toggleHoverCellEditor();
}
});
effect(
() => {
if (this.aiKeywords()) {
this.aiTableGridMatchCellService.findMatchedCells(this.aiKeywords()!, this.aiReferences());
}
},
{ allowSignalWrites: true }
);
}

override ngOnInit(): void {
Expand Down
12 changes: 10 additions & 2 deletions packages/grid/src/renderer/creations/create-cells.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
DEFAULT_FONT_STYLE
} from '../../constants';
import { AITable, AITableQueries, RendererContext } from '../../core';
import { AITableAreaType, AITableCellsDrawerConfig, AITableRender, AITableRowType } from '../../types';
import { AITableCellsDrawerConfig, AITableRender, AITableRowType } from '../../types';
import { getCellHorizontalPosition, transformCellValue } from '../../utils';
import { addRowLayout } from '../drawers/add-row-layout-drawer';
import { cellDrawer } from '../drawers/cell-drawer';
Expand Down Expand Up @@ -85,7 +85,15 @@ export const createCells = (config: AITableCellsDrawerConfig) => {
const isSiblingActiveCell = recordId === activeCell?.recordId && fieldId !== activeCell?.fieldId;
const isActiveCell = recordId === activeCell?.recordId;

if (isCheckedRow || isSelected || isSiblingActiveCell) {
let matchedCellsMap: { [key: string]: boolean } = {};
aiTable.matchedCells().forEach((key) => {
matchedCellsMap[key] = true;
});
const isMatchedCell = matchedCellsMap[`${recordId}-${fieldId}`];

if (isMatchedCell && !isActiveCell) {
background = colors.itemMatchBgColor;
} else if (isCheckedRow || isSelected || isSiblingActiveCell) {
background = colors.itemActiveBgColor;
} else if (isHoverRow && !isActiveCell) {
background = colors.gray80;
Expand Down
1 change: 1 addition & 0 deletions packages/grid/src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './event.service';
export * from './field.service';
export * from './selection.service';
export * from './match-cell.service';
82 changes: 82 additions & 0 deletions packages/grid/src/services/match-cell.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Injectable } from '@angular/core';
import { AITable, AITableField, AITableFieldType, AITableQueries } from '../core';
import { AITableReferences, AITableSelectField } from '../types';
import { transformCellValue } from '../utils';

@Injectable()
export class AITableGridMatchCellService {
aiTable!: AITable;

initialize(aiTable: AITable) {
this.aiTable = aiTable;
}

findMatchedCells(keywords: string, references: AITableReferences) {
let matchedCells: string[] = [];
this.aiTable.records().forEach((record) => {
this.aiTable.fields().forEach((field) => {
if (this.isCellMatchKeywords(this.aiTable, field, record._id, keywords, references)) {
matchedCells.push(`${record._id}-${field._id}`);
}
});
});
this.aiTable.matchedCells.set([...matchedCells]);
}

private isCellMatchKeywords(aiTable: AITable, field: AITableField, recordId: string, keywords: string, references: AITableReferences) {
const cellValue = AITableQueries.getFieldValue(aiTable, [recordId, field._id]);
const transformValue = transformCellValue(aiTable, field, cellValue);
const fieldType = field.type;

let cellText: string[] = [];

switch (fieldType) {
case AITableFieldType.link:
if (transformValue?.text) {
cellText.push(transformValue.text);
}
break;
case AITableFieldType.select:
if (transformValue && Array.isArray(transformValue) && transformValue.length) {
transformValue.forEach((optionId) => {
const item = (field as AITableSelectField).settings.options?.find((option) => option._id === optionId);
if (item?.text) {
cellText.push(item.text);
}
});
}
break;
case AITableFieldType.progress:
cellText.push(`${transformValue}%`);
break;
case AITableFieldType.number:
case AITableFieldType.rate:
cellText.push(String(transformValue));
break;
case AITableFieldType.member:
case AITableFieldType.createdBy:
case AITableFieldType.updatedBy:
if (cellValue?.length && references) {
for (let index = 0; index < cellValue.length; index++) {
const userInfo = references?.members[cellValue[index]];
if (!userInfo) {
continue;
}
if (userInfo.display_name) {
cellText.push(userInfo.display_name);
}
}
}
break;
default:
if (transformValue) {
cellText.push(transformValue);
}
}
try {
return keywords && cellText.length && cellText.some((item) => item.toLowerCase().includes(keywords.toLowerCase()));
} catch (error) {
return false;
}
}
}
6 changes: 5 additions & 1 deletion packages/state/src/types/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export enum AITableFilterOperation {
notContain = 'not_contain'
}

export type ViewSettings = AITableFilterConditions & AITableSortOptions;
export type ViewSettings = AITableSearchOptions & AITableFilterConditions & AITableSortOptions;

export interface AITableView {
_id: string;
Expand Down Expand Up @@ -78,4 +78,8 @@ export interface AITableSortOptions {
}[];
}

export interface AITableSearchOptions {
keywords?: string;
}

export type AITableViews = AITableView[];
1 change: 1 addition & 0 deletions src/app/component/common/content/content.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
[(aiRecords)]="tableService.records"
[(aiFields)]="tableService.fields"
[aiFieldConfig]="aiFieldConfig()"
[aiKeywords]="tableService.keywords()"
[aiPlugins]="plugins"
[aiReferences]="references()"
(aiAddRecord)="addRecord($event)"
Expand Down

0 comments on commit 22385ad

Please sign in to comment.