Skip to content
29 changes: 22 additions & 7 deletions client/packages/lowcoder/src/components/table/EditableCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface CellProps {
candidateStatus?: { text: string; status: StatusType }[];
textOverflow?: boolean;
cellTooltip?: string;
editMode?: string;
onTableEvent?: (eventName: any) => void;
}

Expand Down Expand Up @@ -94,17 +95,19 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
candidateTags,
// tagColors
candidateStatus,
editMode,
onTableEvent,
} = props;
const status = _.isNil(changeValue) ? "normal" : "toSave";
const editable = editViewFn ? props.editable : false;
const { isEditing, setIsEditing } = useContext(TableCellContext);
const value = changeValue ?? baseValue!;
const [tmpValue, setTmpValue] = useState<T | null>(value);
const singleClickEdit = editMode === 'single';

useEffect(() => {
setTmpValue(value);
}, [value]);
}, [JSON.stringify(value)]);

const onChange = useCallback(
(value: T) => {
Expand All @@ -125,21 +128,27 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
if(!_.isEqual(tmpValue, value)) {
onTableEvent?.('columnEdited');
}
}, [dispatch, baseValue, tmpValue]);
}, [dispatch, JSON.stringify(baseValue), JSON.stringify(tmpValue)]);

const editView = useMemo(
() => editViewFn?.({ value, onChange, onChangeEnd }) ?? <></>,
[editViewFn, value, onChange, onChangeEnd]
[editViewFn, JSON.stringify(value), onChange, onChangeEnd]
);

const enterEditFn = useCallback(() => {
if (editable) setIsEditing(true);
}, [editable]);

if (isEditing) {
return (
<>
<BorderDiv />
<BorderDiv className="editing-border" />
<TagsContext.Provider value={candidateTags ?? []}>
<StatusContext.Provider value={candidateStatus ?? []}>{editView}</StatusContext.Provider>
<StatusContext.Provider value={candidateStatus ?? []}>
<div className="editing-wrapper">
{editView}
</div>
</StatusContext.Provider>
</TagsContext.Provider>
</>
);
Expand All @@ -151,7 +160,12 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
>
{status === "toSave" && !isEditing && <EditableChip />}
<CellWrapper tooltipTitle={props.cellTooltip}>
{normalView}
<div
tabIndex={editable ? 0 : -1 }
onFocus={enterEditFn}
>
{normalView}
</div>
</CellWrapper>
{/* overlay on normal view to handle double click for editing */}
{editable && (
Expand All @@ -164,7 +178,8 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
width: '100%',
height: '100%',
}}
onDoubleClick={enterEditFn}
onDoubleClick={!singleClickEdit ? enterEditFn : undefined}
onClick={singleClickEdit ? enterEditFn : undefined}
>
</div>
</CellWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,12 @@ export const SelectUIView = (
inputFieldStyle: SelectStyleType;
onChange: (value: any) => void;
dispatch: DispatchType;
autoFocus?: boolean;
}
) => {
return <Select
ref={props.viewRef}
autoFocus={props.autoFocus}
mode={props.mode}
$inputFieldStyle={props.inputFieldStyle}
$style={props.style as SelectStyleType & MultiSelectStyleType}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const InputNumberWrapper = styled.div`
width: 100%;
border-radius: 0;
background: transparent !important;
padding: 0 !important;
// padding: 0 !important;
box-shadow: none;

input {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ const DatePickerStyled = styled(DatePicker)<{ $open: boolean }>`
top: 0.5px;
display: flex;
align-items: center;
background: #fff;
// background: #fff;
padding: 0 3px;
border-left: 1px solid #d7d9e0;
// border-left: 1px solid #d7d9e0;
}
`;

Expand Down Expand Up @@ -183,7 +183,7 @@ export const DateEdit = (props: DateEditProps) => {
nextIcon={<IconNext />}
superNextIcon={<IconSuperNext />}
superPrevIcon={<SuperPrevIcon />}
allowClear={false}
allowClear={true}
variant="borderless"
autoFocus
value={tempValue}
Expand All @@ -197,7 +197,9 @@ export const DateEdit = (props: DateEditProps) => {
overflow: "hidden",
}}
onOpenChange={(open) => setPanelOpen(open)}
onChange={(value, dateString) => props.onChange(dateString as string)}
onChange={(value, dateString) => {
props.onChange(dateString as string)
}}
onBlur={() => props.onChangeEnd()}
/>
</Wrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,73 @@ import { StringControl } from "comps/controls/codeControl";
import { trans } from "i18n";
import { ColumnTypeCompBuilder, ColumnTypeViewFn } from "../columnTypeCompBuilder";
import { ColumnValueTooltip } from "../simpleColumnTypeComps";
import { styled } from "styled-components";

const Wrapper = styled.div`
display: inline-flex;
align-items: center;
width: 100%;
height: 100%;
position: absolute;
top: 0;
background: transparent !important;
padding: 8px;

> div {
width: 100%;
height: 100%;
}

.ant-select {
height: 100%;
.ant-select-selector {
padding: 0 7px;
height: 100%;
overflow: hidden;
.ant-select-selection-item {
display: inline-flex;
align-items: center;
padding-right: 24px;
}
}
.ant-select-arrow {
height: calc(100% - 3px);
width: fit-content;
top: 1.5px;
margin-top: 0;
background-color: white;
right: 1.5px;
border-right: 1px solid #d7d9e0;
cursor: pointer;
pointer-events: auto;
svg {
min-width: 18px;
min-height: 18px;
}
&:hover svg path {
fill: #315efb;
}
}
.ant-select-selector .ant-select-selection-search {
left: 7px;
input {
height: 100%;
}
}
&.ant-select-open {
.ant-select-arrow {
border-right: none;
border-left: 1px solid #d7d9e0;
svg g path {
fill: #315efb;
}
}
.ant-select-selection-item {
opacity: 0.4;
}
}
}
`;

const childrenMap = {
text: StringControl,
Expand All @@ -28,6 +95,8 @@ const SelectEdit = (props: SelectEditProps) => {
const [currentValue, setCurrentValue] = useState(props.initialValue);
return (
<SelectUIView
autoFocus
allowClear
{...defaultProps}
value={currentValue}
options={props.options}
Expand Down Expand Up @@ -67,12 +136,14 @@ export const ColumnSelectComp = (function () {
)
.setEditViewFn((props) => {
return (
<SelectEdit
initialValue={props.value}
options={options}
onChange={props.onChange}
onChangeEnd={props.onChangeEnd}
/>
<Wrapper>
<SelectEdit
initialValue={props.value}
options={options}
onChange={props.onChange}
onChangeEnd={props.onChangeEnd}
/>
</Wrapper>
)
})
.setPropertyViewFn((children) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const StatusEdit = (props: StatusEditPropsType) => {
const defaultStatus = useContext(StatusContext);
const [status, setStatus] = useState(defaultStatus);
const [allOptions, setAllOptions] = useState(BadgeStatusOptions);
const [open, setOpen] = useState(true);
const [open, setOpen] = useState(false);

return (
<Wrapper>
Expand Down Expand Up @@ -84,18 +84,20 @@ const StatusEdit = (props: StatusEditPropsType) => {
value,
status: status.find((item) => item.text === value)?.status || "none",
});
setOpen(false)
}}
dropdownRender={(originNode: ReactNode) => (
<DropdownStyled>
<ScrollBar style={{ maxHeight: "256px" }}>{originNode}</ScrollBar>
</DropdownStyled>
)}
dropdownStyle={{ marginTop: "7px", padding: "8px 0 6px 0" }}
onBlur={props.onChangeEnd}
onKeyDown={(e) => {
if (e.key === "Enter") {
props.onChangeEnd();
}
onBlur={() => {
props.onChangeEnd();
setOpen(false);
}}
onFocus={() => {
setOpen(true);
}}
onClick={() => setOpen(!open)}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ export const Wrapper = styled.div`
position: absolute;
top: 0;
background: transparent !important;
padding: 8px;

> div {
width: 100%;
height: 100%;
Expand Down Expand Up @@ -147,7 +149,7 @@ export const Wrapper = styled.div`
}
}
.ant-tag {
margin-left: 20px;
margin-left: 5px;
}
.ant-tag svg {
margin-right: 4px;
Expand All @@ -159,6 +161,10 @@ export const DropdownStyled = styled.div`
padding: 3px 8px;
margin: 0 0 2px 8px;
border-radius: 4px;

&.ant-select-item-option-active {
background-color: #f2f7fc;
}
}
.ant-select-item-option-content {
display: flex;
Expand Down Expand Up @@ -193,7 +199,7 @@ const TagEdit = (props: TagEditPropsType) => {
});
return result;
});
const [open, setOpen] = useState(true);
const [open, setOpen] = useState(false);
return (
<Wrapper>
<CustomSelect
Expand All @@ -205,6 +211,7 @@ const TagEdit = (props: TagEditPropsType) => {
defaultValue={props.value}
style={{ width: "100%" }}
open={open}
allowClear={true}
suffixIcon={<PackUpIcon />}
onSearch={(value: string) => {
if (defaultTags.findIndex((item) => item.includes(value)) < 0) {
Expand All @@ -216,18 +223,20 @@ const TagEdit = (props: TagEditPropsType) => {
}}
onChange={(value: string | string[]) => {
props.onChange(value);
setOpen(false)
}}
dropdownRender={(originNode: ReactNode) => (
<DropdownStyled>
<ScrollBar style={{ maxHeight: "256px" }}>{originNode}</ScrollBar>
</DropdownStyled>
)}
dropdownStyle={{ marginTop: "7px", padding: "8px 0 6px 0" }}
onBlur={props.onChangeEnd}
onKeyDown={(e) => {
if (e.key === "Enter") {
props.onChangeEnd();
}
onFocus={() => {
setOpen(true);
}}
onBlur={() => {
props.onChangeEnd();
setOpen(false);
}}
onClick={() => setOpen(!open)}
>
Expand Down Expand Up @@ -259,7 +268,7 @@ export const ColumnTagsComp = (function () {
tagOptionsList = props.tagColors;
let value = props.changeValue ?? getBaseValue(props, dispatch);
value = typeof value === "string" && value.split(",")[1] ? value.split(",") : value;
const tags = _.isArray(value) ? value : [value];
const tags = _.isArray(value) ? value : (value.length ? [value] : []);
const view = tags.map((tag, index) => {
// The actual eval value is of type number or boolean
const tagText = String(tag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const ButtonComp = (function () {
loading={props.loading}
disabled={props.disabled}
$buttonStyle={props.buttonType === "primary" ? style : undefined}
style={{margin: 0}}
>
{/* prevent the button from disappearing */}
{!props.text ? " " : props.text}
Expand Down
Loading
Loading