Skip to content

Commit 2664082

Browse files
committed
clone original Table Comp
1 parent 1671585 commit 2664082

39 files changed

+10622
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import { CellProps } from "components/table/EditableCell";
2+
import { DateTimeComp } from "comps/comps/tableComp/column/columnTypeComps/columnDateTimeComp";
3+
import { TimeComp } from "./columnTypeComps/columnTimeComp";
4+
import { ButtonComp } from "comps/comps/tableComp/column/simpleColumnTypeComps";
5+
import { withType } from "comps/generators";
6+
import { trans } from "i18n";
7+
import { Dropdown } from "lowcoder-design/src/components/Dropdown";
8+
import { BooleanComp } from "./columnTypeComps/columnBooleanComp";
9+
import { SwitchComp } from "./columnTypeComps/columnSwitchComp";
10+
import { DateComp } from "./columnTypeComps/columnDateComp";
11+
import { ImageComp } from "./columnTypeComps/columnImgComp";
12+
import { LinkComp } from "./columnTypeComps/columnLinkComp";
13+
import { ColumnLinksComp } from "./columnTypeComps/columnLinksComp";
14+
import { ColumnMarkdownComp } from "./columnTypeComps/columnMarkdownComp";
15+
import { ProgressComp } from "./columnTypeComps/columnProgressComp";
16+
import { RatingComp } from "./columnTypeComps/columnRatingComp";
17+
import { BadgeStatusComp } from "./columnTypeComps/columnStatusComp";
18+
import { ColumnTagsComp } from "./columnTypeComps/columnTagsComp";
19+
import { ColumnSelectComp } from "./columnTypeComps/columnSelectComp";
20+
import { SimpleTextComp } from "./columnTypeComps/simpleTextComp";
21+
import { ColumnNumberComp } from "./columnTypeComps/ColumnNumberComp";
22+
23+
import { ColumnAvatarsComp } from "./columnTypeComps/columnAvatarsComp";
24+
import { ColumnDropdownComp } from "./columnTypeComps/columnDropdownComp";
25+
26+
const actionOptions = [
27+
{
28+
label: trans("table.avatars"),
29+
value: "avatars",
30+
},
31+
{
32+
label: trans("table.text"),
33+
value: "text",
34+
},
35+
{
36+
label: trans("table.number"),
37+
value: "number",
38+
},
39+
{
40+
label: trans("table.link"),
41+
value: "link",
42+
},
43+
{
44+
label: trans("table.links"),
45+
value: "links",
46+
},
47+
{
48+
label: trans("table.tag"),
49+
value: "tag",
50+
},
51+
{
52+
label: trans("table.select"),
53+
value: "select",
54+
},
55+
{
56+
label: trans("table.dropdown"),
57+
value: "dropdown",
58+
},
59+
{
60+
label: trans("table.badgeStatus"),
61+
value: "badgeStatus",
62+
},
63+
{
64+
label: trans("table.button"),
65+
value: "button",
66+
},
67+
{
68+
label: trans("table.image"),
69+
value: "image",
70+
},
71+
{
72+
label: trans("table.time"),
73+
value: "time",
74+
},
75+
76+
{
77+
label: trans("table.date"),
78+
value: "date",
79+
},
80+
{
81+
label: trans("table.dateTime"),
82+
value: "dateTime",
83+
},
84+
{
85+
label: "Markdown",
86+
value: "markdown",
87+
},
88+
{
89+
label: trans("table.boolean"),
90+
value: "boolean",
91+
},
92+
{
93+
label: trans("table.switch"),
94+
value: "switch",
95+
},
96+
{
97+
label: trans("table.rating"),
98+
value: "rating",
99+
},
100+
{
101+
label: trans("table.progress"),
102+
value: "progress",
103+
},
104+
] as const;
105+
106+
export const ColumnTypeCompMap = {
107+
avatars: ColumnAvatarsComp,
108+
text: SimpleTextComp,
109+
number: ColumnNumberComp,
110+
button: ButtonComp,
111+
badgeStatus: BadgeStatusComp,
112+
link: LinkComp,
113+
tag: ColumnTagsComp,
114+
select: ColumnSelectComp,
115+
dropdown: ColumnDropdownComp,
116+
links: ColumnLinksComp,
117+
image: ImageComp,
118+
markdown: ColumnMarkdownComp,
119+
dateTime: DateTimeComp,
120+
boolean: BooleanComp,
121+
switch: SwitchComp,
122+
rating: RatingComp,
123+
progress: ProgressComp,
124+
date: DateComp,
125+
time: TimeComp,
126+
};
127+
128+
type ColumnTypeMapType = typeof ColumnTypeCompMap;
129+
export type ColumnTypeKeys = keyof ColumnTypeMapType;
130+
131+
const TypedColumnTypeComp = withType(ColumnTypeCompMap, "text");
132+
133+
export class ColumnTypeComp extends TypedColumnTypeComp {
134+
override getView() {
135+
const childView = this.children.comp.getView();
136+
return {
137+
view: (cellProps: CellProps) => {
138+
return childView(cellProps);
139+
},
140+
value: this.children.comp.getDisplayValue(),
141+
};
142+
}
143+
144+
private handleTypeChange: (value: ColumnTypeKeys) => void = (value) => {
145+
// Keep the previous text value, some components do not have text, the default value is currentCell
146+
let textRawData = "{{currentCell}}";
147+
if (this.children.comp.children.hasOwnProperty("text")) {
148+
textRawData = (this.children.comp.children as any).text.toJsonValue();
149+
}
150+
this.dispatchChangeValueAction({
151+
compType: value,
152+
comp: { text: textRawData },
153+
} as any);
154+
}
155+
156+
override getPropertyView() {
157+
return (
158+
<>
159+
<Dropdown
160+
showSearch={true}
161+
value={this.children.compType.getView()}
162+
options={actionOptions}
163+
label={trans("table.columnType")}
164+
onChange={this.handleTypeChange}
165+
/>
166+
{this.children.comp.getPropertyView()}
167+
</>
168+
);
169+
}
170+
}
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import {
2+
CellViewReturn,
3+
EditableCell,
4+
EditViewFn,
5+
TABLE_EDITABLE_SWITCH_ON,
6+
} from "components/table/EditableCell";
7+
import { stateComp } from "comps/generators";
8+
import {
9+
MultiCompBuilder,
10+
PropertyViewFnTypeForComp,
11+
ToConstructor,
12+
ViewFnTypeForComp,
13+
} from "comps/generators/multi";
14+
import _ from "lodash";
15+
import {
16+
CompConstructor,
17+
ConstructorToNodeType,
18+
fromRecord,
19+
NodeToValue,
20+
RecordConstructorToComp,
21+
withFunction,
22+
} from "lowcoder-core";
23+
import { ReactNode } from "react";
24+
import { JSONValue } from "util/jsonTypes";
25+
26+
export const __COLUMN_DISPLAY_VALUE_FN = "__COLUMN_DISPLAY_VALUE_FN";
27+
28+
type RecordConstructorToNodeValue<T> = {
29+
[K in keyof T]: NodeToValue<ConstructorToNodeType<T[K]>>;
30+
};
31+
32+
type ViewValueFnType<ChildrenCtorMap extends Record<string, CompConstructor<unknown>>> = (
33+
nodeValue: RecordConstructorToNodeValue<ChildrenCtorMap>
34+
) => JSONValue;
35+
36+
type NewChildrenCtorMap<ChildrenCtorMap, T extends JSONValue> = ChildrenCtorMap & {
37+
changeValue: ReturnType<typeof stateComp<T | null>>;
38+
};
39+
40+
export type ColumnTypeViewFn<ChildrenCtroMap, T extends JSONValue, ViewReturn> = ViewFnTypeForComp<
41+
ViewReturn,
42+
RecordConstructorToComp<NewChildrenCtorMap<ChildrenCtroMap, T>>
43+
>;
44+
45+
export class ColumnTypeCompBuilder<
46+
ChildrenCtorMap extends Record<string, CompConstructor<unknown>>,
47+
T extends JSONValue = JSONValue
48+
> {
49+
private childrenMap: NewChildrenCtorMap<ChildrenCtorMap, T>;
50+
private propertyViewFn?: PropertyViewFnTypeForComp<
51+
RecordConstructorToComp<NewChildrenCtorMap<ChildrenCtorMap, T>>
52+
>;
53+
private stylePropertyViewFn?: PropertyViewFnTypeForComp<
54+
RecordConstructorToComp<NewChildrenCtorMap<ChildrenCtorMap, T>>
55+
>;
56+
private editViewFn?: EditViewFn<T>;
57+
private cleanupFunctions: (() => void)[] = [];
58+
59+
constructor(
60+
childrenMap: ChildrenCtorMap,
61+
private viewFn: ColumnTypeViewFn<ChildrenCtorMap, T, ReactNode>,
62+
private displayValueFn: ViewValueFnType<ChildrenCtorMap>,
63+
private baseValueFn?: ColumnTypeViewFn<ChildrenCtorMap, T, T>
64+
) {
65+
this.childrenMap = { ...childrenMap, changeValue: stateComp<T | null>(null) };
66+
}
67+
68+
setEditViewFn(editViewFn: NonNullable<typeof this.editViewFn>) {
69+
if (TABLE_EDITABLE_SWITCH_ON) {
70+
this.editViewFn = editViewFn;
71+
}
72+
return this;
73+
}
74+
75+
setPropertyViewFn(
76+
propertyViewFn: PropertyViewFnTypeForComp<
77+
RecordConstructorToComp<NewChildrenCtorMap<ChildrenCtorMap, T>>
78+
>
79+
) {
80+
this.propertyViewFn = propertyViewFn;
81+
return this;
82+
}
83+
84+
setStylePropertyViewFn(
85+
stylePropertyViewFn: PropertyViewFnTypeForComp<
86+
RecordConstructorToComp<NewChildrenCtorMap<ChildrenCtorMap, T>>
87+
>
88+
) {
89+
this.stylePropertyViewFn = stylePropertyViewFn;
90+
return this;
91+
}
92+
93+
build() {
94+
if (!this.propertyViewFn) {
95+
throw new Error("need property view fn");
96+
}
97+
98+
// Memoize the props processing
99+
const memoizedViewFn = _.memoize(
100+
(props: any, dispatch: any) => {
101+
const baseValue = this.baseValueFn?.(props, dispatch);
102+
const normalView = this.viewFn(props, dispatch);
103+
return (
104+
<EditableCell<T>
105+
{...props}
106+
normalView={normalView}
107+
dispatch={dispatch}
108+
baseValue={baseValue}
109+
changeValue={props.changeValue as any}
110+
editViewFn={this.editViewFn}
111+
/>
112+
);
113+
},
114+
(props) => {
115+
let safeOptions = [];
116+
let safeAvatars = [];
117+
if(props.options) {
118+
safeOptions = props.options.map((option: Record<string, any>) => {
119+
const {prefixIcon, suffixIcon, ...safeOption} = option;
120+
return safeOption;
121+
})
122+
}
123+
if(props.avatars) {
124+
safeAvatars = props.avatars.map((avatar: Record<string, any>) => {
125+
const {AvatarIcon, ...safeAvatar} = avatar;
126+
return safeAvatar;
127+
})
128+
}
129+
const {
130+
prefixIcon,
131+
suffixIcon,
132+
iconFalse,
133+
iconTrue,
134+
iconNull,
135+
tagColors,
136+
options,
137+
avatars,
138+
...safeProps
139+
} = props;
140+
return safeProps;
141+
}
142+
);
143+
144+
const viewFn: ColumnTypeViewFn<ChildrenCtorMap, T, CellViewReturn> =
145+
(props, dispatch): CellViewReturn =>
146+
(cellProps) => memoizedViewFn({ ...props, ...cellProps } as any, dispatch);
147+
148+
const ColumnTypeCompTmp = new MultiCompBuilder(
149+
this.childrenMap as ToConstructor<
150+
RecordConstructorToComp<NewChildrenCtorMap<ChildrenCtorMap, T>>
151+
>,
152+
viewFn
153+
)
154+
.setPropertyViewFn(this.propertyViewFn)
155+
.build();
156+
157+
const displayValueFn = this.displayValueFn;
158+
const editViewFn = this.editViewFn;
159+
160+
return class extends ColumnTypeCompTmp {
161+
// table cell data
162+
private _displayValue: JSONValue = null;
163+
private cleanupFunctions: (() => void)[] = [];
164+
constructor(props: any) {
165+
super(props);
166+
this.cleanupFunctions.push(() => {
167+
this._displayValue = null;
168+
memoizedViewFn.cache.clear?.();
169+
});
170+
}
171+
172+
override extraNode() {
173+
return {
174+
node: {
175+
[__COLUMN_DISPLAY_VALUE_FN]: withFunction(
176+
fromRecord(this.childrenNode()),
177+
() => displayValueFn
178+
),
179+
},
180+
updateNodeFields: (value: any) => {
181+
const displayValueFunc = value[__COLUMN_DISPLAY_VALUE_FN];
182+
this._displayValue = displayValueFunc(value);
183+
return { displayValue: this._displayValue };
184+
},
185+
};
186+
}
187+
188+
/**
189+
* Get the data actually displayed by the table cell
190+
*/
191+
getDisplayValue() {
192+
return this._displayValue;
193+
}
194+
195+
static canBeEditable() {
196+
return !_.isNil(editViewFn);
197+
}
198+
199+
componentWillUnmount() {
200+
// Cleanup all registered cleanup functions
201+
this.cleanupFunctions.forEach(cleanup => cleanup());
202+
this.cleanupFunctions = [];
203+
}
204+
};
205+
}
206+
207+
// Cleanup method to be called when the builder is no longer needed
208+
cleanup() {
209+
this.cleanupFunctions.forEach(cleanup => cleanup());
210+
this.cleanupFunctions = [];
211+
}
212+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy