Skip to content

Commit

Permalink
Merge pull request #334 from easyops-cn/jie/APM-1253
Browse files Browse the repository at this point in the history
feat(): 穿梭框表格支持useBrick展示自定义节点
  • Loading branch information
WHChen-Alex authored Jul 1, 2024
2 parents 55be9b5 + 28da60f commit efdb3be
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 4 deletions.
124 changes: 120 additions & 4 deletions bricks/presentational-bricks/src/table-transfer/TableTransfer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
import { NS_PRESENTATIONAL_BRICKS, K } from "../i18n/constants";
import type { ColumnsType, TableRowSelection } from "antd/es/table/interface";
Expand All @@ -13,7 +13,10 @@ import { MenuOutlined } from "@ant-design/icons";
import { Transfer, Table, Modal } from "antd";
import difference from "lodash/difference";
import styles from "./index.module.css";
import { cloneDeep, isNumber, get, uniq } from "lodash";
import { cloneDeep, isNumber, get, uniq, toPath } from "lodash";
import { CustomColumn } from "../brick-table";
import { UseBrickConf } from "@next-core/brick-types";
import { getCustomComp, getCustomHeader } from "./TableTransferHelper";

interface TableTransferProps {
dataSource: any[];
Expand All @@ -31,6 +34,13 @@ interface TableTransferProps {
searchPlaceholder?: string;
onSearch?: (direction: "left" | "right", value: string) => void;
}
type ItemBrickDataMap = Map<unknown, BrickData>;
type BrickData = {
cellData: unknown;
rowData: Record<string, unknown>;
columnIndex: number;
};

export function arrayMoveImmutable(array, fromIndex, toIndex) {
const newArray = [...array];
const startIndex = fromIndex < 0 ? newArray.length + fromIndex : fromIndex;
Expand Down Expand Up @@ -131,6 +141,13 @@ export function TableTransfer(props: TableTransferProps): React.ReactElement {
const [rightColumns, setRightColumns] = useState([]);
const [targetKeys, setTargetKeys] = useState([]);
const [selectedKeys, setSelectedKeys] = useState([]);
const columnTitleBrickDataMapRef = useRef<
Map<CustomColumn, { title: unknown }>
>(new Map());
const useBrickItemBrickDataMapRef = useRef<
Map<UseBrickConf, ItemBrickDataMap>
>(new Map());

useEffect(() => {
const modifiedDataSource = filterDisabledDataSource(
originDataSource,
Expand All @@ -147,7 +164,12 @@ export function TableTransfer(props: TableTransferProps): React.ReactElement {
));
setRightColumns([
...originColumns,
{ title: sortTitle, dataIndex: "sort", render: () => <DragHandle /> },
{
title: sortTitle,
dataIndex: "sort",
width: 50,
render: () => <DragHandle />,
},
]);
} else {
setRightColumns(originColumns);
Expand Down Expand Up @@ -219,6 +241,100 @@ export function TableTransfer(props: TableTransferProps): React.ReactElement {
disabled: listDisabled,
}) => {
const columns = direction === "left" ? originColumns : rightColumns;
let customColumns;

if (columns) {
columnTitleBrickDataMapRef.current.clear();
useBrickItemBrickDataMapRef.current.clear();
customColumns = columns.map((column, index) => {
const {
useBrick,
component,
valueSuffix,
cellStatus,
titleUseBrick,
headerBrick,
colSpanKey,
rowSpanKey,
...columnConf
} = column;

if (headerBrick?.useBrick || titleUseBrick) {
if (titleUseBrick) {
// eslint-disable-next-line no-console
console.warn(
"`titleUseBrick` of `<presentational-bricks.rank-table>` is deprecated, use `headerBrick` instead."
);
}

const useBrick = headerBrick?.useBrick || titleUseBrick;
let data = columnTitleBrickDataMapRef.current.get(column);

if (!data) {
data = {
title: columnConf.title,
};
columnTitleBrickDataMapRef.current.set(column, data);
}

columnConf.title = getCustomHeader(useBrick, data);
}

if (useBrick || component) {
let itemBrickDataMap: ItemBrickDataMap;

if (useBrick) {
itemBrickDataMap =
useBrickItemBrickDataMapRef.current.get(useBrick);

if (!itemBrickDataMap) {
itemBrickDataMap = new Map();
useBrickItemBrickDataMapRef.current.set(
useBrick,
itemBrickDataMap
);
}
}

columnConf.render = getCustomComp(
useBrick,
component,
itemBrickDataMap
);
} else if (valueSuffix) {
// eslint-disable-next-line react/display-name
columnConf.render = (value: any, record: any, index: any) => (
<>{value + valueSuffix}</>
);
}

if (typeof columnConf.dataIndex === "string") {
columnConf.dataIndex = toPath(columnConf.dataIndex);
}
if (columnConf.verticalAlign === "top") {
columnConf.className
? (columnConf.className += " alignTop")
: (columnConf.className = "alignTop");
}
if (columnConf.verticalAlign === "bottom") {
columnConf.className
? (columnConf.className += " alignBottom")
: (columnConf.className = "alignBottom");
}

if (!columnConf.render) {
// eslint-disable-next-line react/display-name
columnConf.render = (text: string) => (
<div style={{ display: "flex", alignItems: "center" }}>
<span style={{ flex: 1 }}>{text}</span>
</div>
);
}

return columnConf;
});
}

const rowSelection: TableRowSelection<TransferItem> = {
getCheckboxProps: (item) => ({
disabled: listDisabled || item.disabled,
Expand Down Expand Up @@ -294,7 +410,7 @@ export function TableTransfer(props: TableTransferProps): React.ReactElement {
<Table
rowSelection={rowSelection}
dataSource={filteredItems}
columns={columns}
columns={customColumns}
size="small"
onRow={({ key, disabled: itemDisabled }) => ({
onClick: () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { UseBrickConf } from "@next-core/brick-types";
import React from "react";
import { BrickAsComponent } from "@next-core/brick-kit";
import { CustomColumnComponent } from "../brick-table";

export const getCustomHeader = (
useBrick: UseBrickConf,
data?: { title: unknown }
): (() => React.ReactElement) => {
return function CustomHeader() {
return <BrickAsComponent useBrick={useBrick} data={data} />;
};
};

export const getCustomComp = (
useBrick: UseBrickConf,
component?: CustomColumnComponent,
itemBrickDataMap?: ItemBrickDataMap,
awardsComponent?: (index: number) => void | null,
size?: "default" | "small"
) => {
return function CustomComp(
value: any,
item: Record<string, any>,
index: number
) {
if (useBrick) {
let brickData: BrickData = itemBrickDataMap.get(item);

if (!brickData) {
brickData = {
cellData: value,
rowData: item,
columnIndex: index,
};
itemBrickDataMap.set(item, brickData);
}

if (typeof awardsComponent === "function") {
return (
<div style={{ display: "flex" }}>
{awardsComponent(index)}
<div style={{ margin: "auto 0" }}>
<BrickAsComponent useBrick={useBrick} data={brickData} />
</div>
</div>
);
}
return <BrickAsComponent useBrick={useBrick} data={brickData} />;
}

if (component.fields) {
// eslint-disable-next-line no-console
console.warn(
"`<presentational-bricks.brick-table>.columns[].component` is deprecated, use `useBrick` instead."
);
const props: Record<string, any> = Object.assign(
{},
component.properties
);
const {
value: valueKey,
item: itemKey,
index: indexKey,
} = component.fields;
if (valueKey) {
props[valueKey] = value;
}

if (itemKey) {
props[itemKey] = item;
}

if (indexKey) {
props[indexKey] = index;
}

if (typeof awardsComponent === "function") {
return (
<>
{awardsComponent(index)}
<BrickAsComponent
key={value}
useBrick={{
...component,
properties: props,
}}
/>
</>
);
}

return (
<BrickAsComponent
key={value}
useBrick={{
...component,
properties: props,
}}
/>
);
}
};
};

type ItemBrickDataMap = Map<unknown, BrickData>;
type BrickData = {
cellData: unknown;
rowData: Record<string, unknown>;
columnIndex: number;
};

0 comments on commit efdb3be

Please sign in to comment.