- Notifications
You must be signed in to change notification settings - Fork277
[Feat] Table Lite Component#1939
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
Show all changes
49 commits Select commitHold shift + click to select a range
2664082
clone original Table Comp
iamfaran9ff640d
register table lite comp
iamfaran491782f
remove expansion data layer
iamfaranb43d31e
remove expansion functionality from table
iamfaran13cdeff
fix imports for table lite comp
iamfaran966c4df
remove edit functionality
iamfaran4d75755
remove filter modal / table toolbar unnecessary code
iamfarand03a02d
remove search filter and fix css issue
iamfaran5d6301e
remove edit / insert functions
iamfaran714e6cc
remove row context
iamfarand4afdb4
split down tableComp.tsx
iamfaran8b492c2
refactor tableCompView
iamfarana909c64
refactor / add virtualization
iamfaran18a93cf
remove edit functionality from columns
iamfaran6b34a8d
remove remaining edit functionality from the columns
iamfaran38c8653
remove change value props
iamfaranc82279e
refactor columnToAntd function
iamfaran29f29b3
remove more edit related code from columns
iamfaranc406bb5
add basic filters in headers
iamfaranf09e36f
add dynamic virtualization
iamfaran07abda7
remove unnecssory code for virtualization
iamfaran5a6ac32
fix x scrolling
iamfaran3af069a
scroll fixes
iamfaran1e1b61e
fix virtualization toolbar bottom
iamfarane98b05c
hide horizontal scroll virtualization
iamfaranfed09b1
fix y scroll
iamfaran58f13b2
delete rc-virtual-list
iamfaranb8c7586
fix infinite re renders / unnecessary logic
iamfaranc84c902
add styling structure / refactor styles
iamfaran67f9952
add custom Hook to calculate table height / body
iamfaran26f6b10
Add Base Table component
iamfaran4fd3e12
Add auto / fixed tables
iamfaran37d494a
basic refactor complete
iamfarand73a5ff
add styles
iamfaran3edaee4
fix header styles
iamfaran4590bfe
add remaining styles
iamfaran2fc52e6
move footer inside the main wrapper
iamfaran8a4c68f
fix window height
iamfaran6f5f5c5
Add footer/ header customizations + virtualization layout fix
iamfaranc30ffdd
add borders
iamfaranb293eac
implement simple bar
iamfaranffbea62
add customize scrollbars functionality
iamfaran59e02f5
add scroll
b6f71c2
match colors
3ae83d5
scrollbar settings
f86fcd3
hide custom scrolls on virtualization
19692fd
styled components syntax
dc6c5b9
fix scolling customization
iamfaran85f690f
remove console log
iamfaranFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
2 changes: 1 addition & 1 deletionclient/packages/lowcoder/src/comps/comps/tableComp/tablePropertyView.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
179 changes: 179 additions & 0 deletionsclient/packages/lowcoder/src/comps/comps/tableLiteComp/column/columnTypeComp.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
import { DateTimeComp } from "comps/comps/tableComp/column/columnTypeComps/columnDateTimeComp"; | ||
import { TimeComp } from "./columnTypeComps/columnTimeComp"; | ||
import { ButtonComp } from "./simpleColumnTypeComps"; | ||
import { withType } from "comps/generators"; | ||
import { trans } from "i18n"; | ||
import { Dropdown } from "lowcoder-design/src/components/Dropdown"; | ||
import { BooleanComp } from "./columnTypeComps/columnBooleanComp"; | ||
import { SwitchComp } from "./columnTypeComps/columnSwitchComp"; | ||
import { DateComp } from "./columnTypeComps/columnDateComp"; | ||
import { ImageComp } from "./columnTypeComps/columnImgComp"; | ||
import { LinkComp } from "./columnTypeComps/columnLinkComp"; | ||
import { ColumnLinksComp } from "./columnTypeComps/columnLinksComp"; | ||
import { ColumnMarkdownComp } from "./columnTypeComps/columnMarkdownComp"; | ||
import { ProgressComp } from "./columnTypeComps/columnProgressComp"; | ||
import { RatingComp } from "./columnTypeComps/columnRatingComp"; | ||
import { BadgeStatusComp } from "./columnTypeComps/columnStatusComp"; | ||
import { ColumnTagsComp } from "./columnTypeComps/columnTagsComp"; | ||
import { ColumnSelectComp } from "./columnTypeComps/columnSelectComp"; | ||
import { SimpleTextComp } from "./columnTypeComps/simpleTextComp"; | ||
import { ColumnNumberComp } from "./columnTypeComps/ColumnNumberComp"; | ||
import { ColumnAvatarsComp } from "./columnTypeComps/columnAvatarsComp"; | ||
import { ColumnDropdownComp } from "./columnTypeComps/columnDropdownComp"; | ||
export type CellProps = { | ||
tableSize?: string; | ||
candidateTags?: string[]; | ||
candidateStatus?: { text: string; status: any }[]; | ||
textOverflow?: boolean; | ||
cellTooltip?: string; | ||
onTableEvent?: (eventName: any) => void; | ||
cellIndex?: string; | ||
}; | ||
const actionOptions = [ | ||
{ | ||
label: trans("table.avatars"), | ||
value: "avatars", | ||
}, | ||
{ | ||
label: trans("table.text"), | ||
value: "text", | ||
}, | ||
{ | ||
label: trans("table.number"), | ||
value: "number", | ||
}, | ||
{ | ||
label: trans("table.link"), | ||
value: "link", | ||
}, | ||
{ | ||
label: trans("table.links"), | ||
value: "links", | ||
}, | ||
{ | ||
label: trans("table.tag"), | ||
value: "tag", | ||
}, | ||
{ | ||
label: trans("table.select"), | ||
value: "select", | ||
}, | ||
{ | ||
label: trans("table.dropdown"), | ||
value: "dropdown", | ||
}, | ||
{ | ||
label: trans("table.badgeStatus"), | ||
value: "badgeStatus", | ||
}, | ||
{ | ||
label: trans("table.button"), | ||
value: "button", | ||
}, | ||
{ | ||
label: trans("table.image"), | ||
value: "image", | ||
}, | ||
{ | ||
label: trans("table.time"), | ||
value: "time", | ||
}, | ||
{ | ||
label: trans("table.date"), | ||
value: "date", | ||
}, | ||
{ | ||
label: trans("table.dateTime"), | ||
value: "dateTime", | ||
}, | ||
{ | ||
label: "Markdown", | ||
value: "markdown", | ||
}, | ||
{ | ||
label: trans("table.boolean"), | ||
value: "boolean", | ||
}, | ||
{ | ||
label: trans("table.switch"), | ||
value: "switch", | ||
}, | ||
{ | ||
label: trans("table.rating"), | ||
value: "rating", | ||
}, | ||
{ | ||
label: trans("table.progress"), | ||
value: "progress", | ||
}, | ||
] as const; | ||
export const ColumnTypeCompMap = { | ||
avatars: ColumnAvatarsComp, | ||
text: SimpleTextComp, | ||
number: ColumnNumberComp, | ||
button: ButtonComp, | ||
badgeStatus: BadgeStatusComp, | ||
link: LinkComp, | ||
tag: ColumnTagsComp, | ||
select: ColumnSelectComp, | ||
dropdown: ColumnDropdownComp, | ||
links: ColumnLinksComp, | ||
image: ImageComp, | ||
markdown: ColumnMarkdownComp, | ||
dateTime: DateTimeComp, | ||
boolean: BooleanComp, | ||
switch: SwitchComp, | ||
rating: RatingComp, | ||
progress: ProgressComp, | ||
date: DateComp, | ||
time: TimeComp, | ||
}; | ||
type ColumnTypeMapType = typeof ColumnTypeCompMap; | ||
export type ColumnTypeKeys = keyof ColumnTypeMapType; | ||
const TypedColumnTypeComp = withType(ColumnTypeCompMap, "text"); | ||
export class ColumnTypeComp extends TypedColumnTypeComp { | ||
override getView() { | ||
const childView = this.children.comp.getView(); | ||
return { | ||
view: (cellProps: CellProps) => { | ||
return childView(cellProps); | ||
}, | ||
value: this.children.comp.getDisplayValue(), | ||
}; | ||
} | ||
private handleTypeChange: (value: ColumnTypeKeys) => void = (value) => { | ||
// Keep the previous text value, some components do not have text, the default value is currentCell | ||
let textRawData = "{{currentCell}}"; | ||
if (this.children.comp.children.hasOwnProperty("text")) { | ||
textRawData = (this.children.comp.children as any).text.toJsonValue(); | ||
} | ||
this.dispatchChangeValueAction({ | ||
compType: value, | ||
comp: { text: textRawData }, | ||
} as any); | ||
} | ||
override getPropertyView() { | ||
return ( | ||
<> | ||
<Dropdown | ||
showSearch={true} | ||
value={this.children.compType.getView()} | ||
options={actionOptions} | ||
label={trans("table.columnType")} | ||
onChange={this.handleTypeChange} | ||
/> | ||
{this.children.comp.getPropertyView()} | ||
</> | ||
); | ||
} | ||
} |
186 changes: 186 additions & 0 deletionsclient/packages/lowcoder/src/comps/comps/tableLiteComp/column/columnTypeCompBuilder.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
import { CellViewReturn } from "components/table/EditableCell"; | ||
import { stateComp } from "comps/generators"; | ||
import { | ||
MultiCompBuilder, | ||
PropertyViewFnTypeForComp, | ||
ToConstructor, | ||
ViewFnTypeForComp, | ||
} from "comps/generators/multi"; | ||
import _ from "lodash"; | ||
import { | ||
CompConstructor, | ||
ConstructorToNodeType, | ||
fromRecord, | ||
NodeToValue, | ||
RecordConstructorToComp, | ||
withFunction, | ||
} from "lowcoder-core"; | ||
import { ReactNode } from "react"; | ||
import { JSONValue } from "util/jsonTypes"; | ||
export const __COLUMN_DISPLAY_VALUE_FN = "__COLUMN_DISPLAY_VALUE_FN"; | ||
type RecordConstructorToNodeValue<T> = { | ||
[K in keyof T]: NodeToValue<ConstructorToNodeType<T[K]>>; | ||
}; | ||
type ViewValueFnType<ChildrenCtorMap extends Record<string, CompConstructor<unknown>>> = ( | ||
nodeValue: RecordConstructorToNodeValue<ChildrenCtorMap> | ||
) => JSONValue; | ||
export type ColumnTypeViewFn<ChildrenCtroMap, T extends JSONValue, ViewReturn> = ViewFnTypeForComp< | ||
ViewReturn, | ||
RecordConstructorToComp<ChildrenCtroMap> | ||
>; | ||
export class ColumnTypeCompBuilder< | ||
ChildrenCtorMap extends Record<string, CompConstructor<unknown>>, | ||
T extends JSONValue = JSONValue | ||
> { | ||
private childrenMap: ChildrenCtorMap; | ||
private propertyViewFn?: PropertyViewFnTypeForComp< | ||
RecordConstructorToComp<ChildrenCtorMap> | ||
>; | ||
private stylePropertyViewFn?: PropertyViewFnTypeForComp< | ||
RecordConstructorToComp<ChildrenCtorMap> | ||
>; | ||
private cleanupFunctions: (() => void)[] = []; | ||
constructor( | ||
childrenMap: ChildrenCtorMap, | ||
private viewFn: ColumnTypeViewFn<ChildrenCtorMap, T, ReactNode>, | ||
private displayValueFn: ViewValueFnType<ChildrenCtorMap>, | ||
private baseValueFn?: ColumnTypeViewFn<ChildrenCtorMap, T, T> | ||
) { | ||
this.childrenMap = { ...childrenMap } as ChildrenCtorMap; | ||
} | ||
setEditViewFn(_: any) { | ||
// Edit views are disabled in Table Lite; keep chainability without storing | ||
return this; | ||
} | ||
setPropertyViewFn( | ||
propertyViewFn: PropertyViewFnTypeForComp< | ||
RecordConstructorToComp<ChildrenCtorMap> | ||
> | ||
) { | ||
this.propertyViewFn = propertyViewFn; | ||
return this; | ||
} | ||
setStylePropertyViewFn( | ||
stylePropertyViewFn: PropertyViewFnTypeForComp< | ||
RecordConstructorToComp<ChildrenCtorMap> | ||
> | ||
) { | ||
this.stylePropertyViewFn = stylePropertyViewFn; | ||
return this; | ||
} | ||
build() { | ||
if (!this.propertyViewFn) { | ||
throw new Error("need property view fn"); | ||
} | ||
// Memoize the props processing | ||
const memoizedViewFn = _.memoize( | ||
(props: any, dispatch: any) => { | ||
const baseValue = this.baseValueFn?.(props, dispatch); | ||
const normalView = this.viewFn(props, dispatch); | ||
return normalView; | ||
}, | ||
(props) => { | ||
let safeOptions = []; | ||
let safeAvatars = []; | ||
if(props.options) { | ||
safeOptions = props.options.map((option: Record<string, any>) => { | ||
const {prefixIcon, suffixIcon, ...safeOption} = option; | ||
return safeOption; | ||
}) | ||
} | ||
if(props.avatars) { | ||
safeAvatars = props.avatars.map((avatar: Record<string, any>) => { | ||
const {AvatarIcon, ...safeAvatar} = avatar; | ||
return safeAvatar; | ||
}) | ||
} | ||
const { | ||
prefixIcon, | ||
suffixIcon, | ||
iconFalse, | ||
iconTrue, | ||
iconNull, | ||
tagColors, | ||
options, | ||
avatars, | ||
...safeProps | ||
} = props; | ||
return safeProps; | ||
} | ||
); | ||
const viewFn: ColumnTypeViewFn<ChildrenCtorMap, T, CellViewReturn> = | ||
(props, dispatch): CellViewReturn => | ||
(cellProps) => memoizedViewFn({ ...props, ...cellProps } as any, dispatch); | ||
const ColumnTypeCompTmp = new MultiCompBuilder( | ||
(this.childrenMap as unknown) as ToConstructor< | ||
RecordConstructorToComp<ChildrenCtorMap> | ||
>, | ||
viewFn | ||
) | ||
.setPropertyViewFn(this.propertyViewFn) | ||
.build(); | ||
const displayValueFn = this.displayValueFn; | ||
return class extends ColumnTypeCompTmp { | ||
// table cell data | ||
private _displayValue: JSONValue = null; | ||
private cleanupFunctions: (() => void)[] = []; | ||
constructor(props: any) { | ||
super(props); | ||
this.cleanupFunctions.push(() => { | ||
this._displayValue = null; | ||
memoizedViewFn.cache.clear?.(); | ||
}); | ||
} | ||
override extraNode() { | ||
return { | ||
node: { | ||
[__COLUMN_DISPLAY_VALUE_FN]: withFunction( | ||
fromRecord(this.childrenNode()), | ||
() => displayValueFn | ||
), | ||
}, | ||
updateNodeFields: (value: any) => { | ||
const displayValueFunc = value[__COLUMN_DISPLAY_VALUE_FN]; | ||
this._displayValue = displayValueFunc(value); | ||
return { displayValue: this._displayValue }; | ||
}, | ||
}; | ||
} | ||
/** | ||
* Get the data actually displayed by the table cell | ||
*/ | ||
getDisplayValue() { | ||
return this._displayValue; | ||
} | ||
componentWillUnmount() { | ||
// Cleanup all registered cleanup functions | ||
this.cleanupFunctions.forEach(cleanup => cleanup()); | ||
this.cleanupFunctions = []; | ||
} | ||
}; | ||
} | ||
// Cleanup method to be called when the builder is no longer needed | ||
cleanup() { | ||
this.cleanupFunctions.forEach(cleanup => cleanup()); | ||
this.cleanupFunctions = []; | ||
} | ||
} |
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.