diff --git a/client/packages/lowcoder/src/components/table/EditableCell.tsx b/client/packages/lowcoder/src/components/table/EditableCell.tsx index 799c21a26..a08a3607d 100644 --- a/client/packages/lowcoder/src/components/table/EditableCell.tsx +++ b/client/packages/lowcoder/src/components/table/EditableCell.tsx @@ -35,6 +35,7 @@ export interface CellProps { candidateTags?: string[]; candidateStatus?: { text: string; status: StatusType }[]; textOverflow?: boolean; + onTableEvent?: (eventName: any) => void; } export type CellViewReturn = (props: CellProps) => ReactNode; @@ -71,6 +72,7 @@ export function EditableCell(props: EditableCellProps) { baseValue, candidateTags, candidateStatus, + onTableEvent, } = props; const status = _.isNil(changeValue) ? "normal" : "toSave"; const editable = editViewFn ? props.editable : false; @@ -96,6 +98,9 @@ export function EditableCell(props: EditableCellProps) { false ) ); + if(!_.isEqual(tmpValue, value)) { + onTableEvent?.('columnEdited'); + } }, [dispatch, baseValue, tmpValue]); const editView = useMemo( () => editViewFn?.({ value, onChange, onChangeEnd }) ?? <>, diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/ColumnNumberComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/ColumnNumberComp.tsx index 20a390294..20622b3b2 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/ColumnNumberComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/ColumnNumberComp.tsx @@ -1,18 +1,40 @@ - import { default as Input } from "antd/es/input"; -import { NumberControl, StringControl } from "comps/controls/codeControl"; + import { default as InputNumber } from "antd/es/input-number"; +import { NumberControl, RangeControl, StringControl } from "comps/controls/codeControl"; import { BoolControl } from "comps/controls/boolControl"; import { trans } from "i18n"; import { ColumnTypeCompBuilder, ColumnTypeViewFn } from "../columnTypeCompBuilder"; import { ColumnValueTooltip } from "../simpleColumnTypeComps"; +import { withDefault } from "comps/generators"; +import styled from "styled-components"; + +const InputNumberWrapper = styled.div` + .ant-input-number { + width: 100%; + border-radius: 0; + background: transparent !important; + padding: 0 !important; + box-shadow: none; + + input { + padding: 0; + border-radius: 0; + } + } +`; const childrenMap = { text: NumberControl, + step: withDefault(NumberControl, 1), + precision: RangeControl.closed(0, 20, 0), float: BoolControl, prefix: StringControl, suffix: StringControl, }; let float = false; +let step = 1; +let precision = 0; + const getBaseValue: ColumnTypeViewFn = ( props ) => { @@ -24,26 +46,35 @@ export const ColumnNumberComp = (function () { childrenMap, (props, dispatch) => { float = props.float; - const value = !float ? Math.floor(props.changeValue ?? getBaseValue(props, dispatch)) : props.changeValue ?? getBaseValue(props, dispatch); - return props.prefix + value + props.suffix; + step = props.step; + precision = props.precision; + const value = props.changeValue ?? getBaseValue(props, dispatch); + let formattedValue: string | number = !float ? Math.floor(value) : value; + if(float) { + formattedValue = formattedValue.toPrecision(precision + 1); + } + return props.prefix + formattedValue + props.suffix; }, (nodeValue) => nodeValue.text.value, getBaseValue, ) .setEditViewFn((props) => { return ( - { - props.onChange(!float ? Math.floor(e.target.valueAsNumber) : e.target.valueAsNumber); - }} - onBlur={props.onChangeEnd} - onPressEnter={props.onChangeEnd} - /> + + { + value = value ?? 0; + props.onChange(!float ? Math.floor(value) : value); + }} + precision={float ? precision : 0} + onBlur={props.onChangeEnd} + onPressEnter={props.onChangeEnd} + /> + )}) .setPropertyViewFn((children) => { return ( @@ -52,17 +83,36 @@ export const ColumnNumberComp = (function () { label: trans("table.columnValue"), tooltip: ColumnValueTooltip, })} + {children.step.propertyView({ + label: trans("table.numberStep"), + tooltip: trans("table.numberStepTooltip"), + onFocus: (focused) => { + if(!focused) { + const value = children.step.getView(); + const isFloat = children.float.getView(); + const newValue = !isFloat ? Math.floor(value) : value; + children.step.dispatchChangeValueAction(String(newValue)); + } + } + })} + {float && ( + children.precision.propertyView({ + label: trans("table.precision"), + }) + )} {children.prefix.propertyView({ label: trans("table.prefix"), - // tooltip: ColumnValueTooltip, })} {children.suffix.propertyView({ label: trans("table.suffix"), - // tooltip: ColumnValueTooltip, })} {children.float.propertyView({ label: trans("table.float"), - // tooltip: ColumnValueTooltip, + onChange: (isFloat) => { + const value = children.step.getView(); + const newValue = !isFloat ? Math.floor(value) : value; + children.step.dispatchChangeValueAction(String(newValue)); + } })} ); diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnLinksComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnLinksComp.tsx index 7329db720..06f7fcb38 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnLinksComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnLinksComp.tsx @@ -1,5 +1,3 @@ -import { EllipsisOutlined } from "@ant-design/icons"; -import { default as Dropdown} from "antd/es/dropdown"; import { default as Menu } from "antd/es/menu"; import { ColumnTypeCompBuilder } from "comps/comps/tableComp/column/columnTypeCompBuilder"; import { ActionSelectorControlInContext } from "comps/controls/actionSelector/actionSelectorControl"; @@ -12,18 +10,6 @@ import styled from "styled-components"; import { ColumnLink } from "comps/comps/tableComp/column/columnTypeComps/columnLinkComp"; import { LightActiveTextColor, PrimaryColor } from "constants/style"; -const LinksWrapper = styled.div` - white-space: nowrap; - - > a { - margin-right: 8px; - } - - > a:last-child { - margin-right: 0; - } -`; - const MenuLinkWrapper = styled.div` > a { color: ${PrimaryColor} !important; @@ -34,6 +20,22 @@ const MenuLinkWrapper = styled.div` } `; +const MenuWrapper = styled.div` + ul { + background: transparent !important; + border-bottom: 0; + + li { + padding: 0 10px 0 0 !important; + line-height: normal !important; + + &::after { + content: none !important; + } + } + } +`; + const OptionItem = new MultiCompBuilder( { label: StringControl, @@ -69,48 +71,28 @@ export const ColumnLinksComp = (function () { return new ColumnTypeCompBuilder( childrenMap, (props) => { - const menu = props.options.length > 3 && ( - - {props.options - .filter((o) => !o.hidden) - .slice(3) - .map((option, index) => ( - - - - - - ))} - - ); + const menuItems = props.options + .filter((o) => !o.hidden) + .map((option, index) => ( + { + key: index, + label: ( + + + + ) + } + )); return ( - - {props.options - .filter((o) => !o.hidden) - .slice(0, 3) - .map((option, i) => ( - - ))} - {menu && ( - menu} - > - e.preventDefault()} /> - - )} - - ); + + + + ) }, () => "" ) diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx index 8bf84e276..b97c16b50 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/column/tableColumnComp.tsx @@ -323,7 +323,6 @@ export function newPrimaryColumn( title?: string, isTag?: boolean ): ConstructorToDataType { - console.log('newPrimaryColumn', title); return { title: title ?? key, dataIndex: key, diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableComp.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableComp.tsx index 65555c29f..a9e32547a 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableComp.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableComp.tsx @@ -176,7 +176,6 @@ export class TableImplComp extends TableInitComp implements IContainer { override reduce(action: CompAction): this { let comp = super.reduce(action); - let dataChanged = false; if (action.type === CompActionTypes.UPDATE_NODES_V2) { const nextRowExample = tableDataRowExample(comp.children.data.getView()); @@ -316,10 +315,18 @@ export class TableImplComp extends TableInitComp implements IContainer { filter: this.children.toolbar.children.filter.node(), showFilter: this.children.toolbar.children.showFilter.node(), }; + let context = this; const filteredDataNode = withFunction(fromRecord(nodes), (input) => { const { data, searchValue, filter, showFilter } = input; const filteredData = filterData(data, searchValue.value, filter, showFilter.value); // console.info("filterNode. data: ", data, " filter: ", filter, " filteredData: ", filteredData); + // if data is changed on search then trigger event + if(Boolean(searchValue.value) && data.length !== filteredData.length) { + const onEvent = context.children.onEvent.getView(); + setTimeout(() => { + onEvent("dataSearch"); + }); + } return filteredData.map((row) => tranToTableRecord(row, row[OB_ROW_ORI_INDEX])); }); return lastValueIfEqual(this, "filteredDataNode", [filteredDataNode, nodes] as const, (a, b) => diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx index 92e241663..4f45854bf 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx @@ -680,6 +680,7 @@ export function TableCompView(props: { dynamicColumn, dynamicColumnConfig, columnsAggrData, + onEvent, ), [ columnViews, @@ -745,7 +746,10 @@ export function TableCompView(props: { setLoading ) } - onDownload={() => onDownload(`${compName}-data`)} + onDownload={() => { + handleChangeEvent("download"); + onDownload(`${compName}-data`) + }} hasChange={hasChange} onSaveChanges={() => handleChangeEvent("saveChanges")} onCancelChanges={() => handleChangeEvent("cancelChanges")} @@ -778,7 +782,11 @@ export function TableCompView(props: { : "OB_CHILDREN_KEY_PLACEHOLDER", fixed: "left", onExpand: (expanded) => { - if(expanded) handleChangeEvent('rowExpand') + if(expanded) { + handleChangeEvent('rowExpand') + } else { + handleChangeEvent('rowShrink') + } } }} rowColorFn={compChildren.rowColor.getView() as any} diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableDynamicColumn.test.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableDynamicColumn.test.tsx index c5e1b65a0..022e0558b 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableDynamicColumn.test.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableDynamicColumn.test.tsx @@ -36,6 +36,7 @@ const expectColumn = ( // with dynamic config const dynamicColumnConfig = comp.children.dynamicColumnConfig.getView(); if (dynamicColumnConfig?.length > 0) { + const onEvent = (eventName: any) => {}; const antdColumns = columnsToAntdFormat( columnViews, comp.children.sort.getView(), @@ -43,7 +44,8 @@ const expectColumn = ( comp.children.size.getView(), comp.children.dynamicColumn.getView(), dynamicColumnConfig, - comp.columnAggrData + comp.columnAggrData, + onEvent, ); expect(columnViews.length).toBeGreaterThanOrEqual(antdColumns.length); antdColumns.forEach((column) => { diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx index d4cc986b8..3e9c8d559 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableTypes.tsx @@ -78,6 +78,26 @@ export const TableEventOptions = [ value: "rowExpand", description: trans("table.rowExpand"), }, + { + label: trans("table.rowShrink"), + value: "rowShrink", + description: trans("table.rowShrink"), + }, + { + label: trans("table.columnEdited"), + value: "columnEdited", + description: trans("table.columnEdited"), + }, + { + label: trans("table.search"), + value: "dataSearch", + description: trans("table.search"), + }, + { + label: trans("table.download"), + value: "download", + description: trans("table.download"), + }, { label: trans("table.filterChange"), value: "filterChange", diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx index c3c6a3fa1..993a8b9dd 100644 --- a/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx +++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableUtils.tsx @@ -269,6 +269,7 @@ export function columnsToAntdFormat( dynamicColumn: boolean, dynamicColumnConfig: Array, columnsAggrData: ColumnsAggrData, + onTableEvent: (eventName: any) => void, ): Array> { const sortMap: Map = new Map( sort.map((s) => [s.column, s.desc ? "descend" : "ascend"]) @@ -346,9 +347,11 @@ export function columnsToAntdFormat( .getView() .view({ editable: column.editable, - size, candidateTags: tags, + size, + candidateTags: tags, candidateStatus: status, textOverflow: column.textOverflow, + onTableEvent, }); }, ...(column.sortable diff --git a/client/packages/lowcoder/src/comps/controls/boolControl.tsx b/client/packages/lowcoder/src/comps/controls/boolControl.tsx index 7ea77e88e..b044138fa 100644 --- a/client/packages/lowcoder/src/comps/controls/boolControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/boolControl.tsx @@ -106,7 +106,7 @@ class BoolControl extends AbstractComp({ useCodeEditor: !this.useCodeEditor }, true); } - propertyView(params: ControlParams) { + propertyView(params: ControlParams & {onChange?: (changed: boolean) => void}) { const changeModeIcon = ( this.dispatchChangeValueAction(x)} + onChange={(x) => { + this.dispatchChangeValueAction(x); + params?.onChange?.(x); + }} > )} diff --git a/client/packages/lowcoder/src/i18n/locales/de.ts b/client/packages/lowcoder/src/i18n/locales/de.ts index bc5cd9101..298e80ef4 100644 --- a/client/packages/lowcoder/src/i18n/locales/de.ts +++ b/client/packages/lowcoder/src/i18n/locales/de.ts @@ -1135,6 +1135,9 @@ export const de = { "auto": "Auto", "fixed": "Festgelegt", "columnType": "Säule Typ", + "numberStep": "Schritt", + "numberStepTooltip": "Die Zahl, auf die der aktuelle Wert erhöht oder verringert wird. Es kann eine ganze Zahl oder eine Dezimalzahl sein", + "precision": "Präzision", "float": "Schwimmer", "prefix": "Präfix", "suffix": "Nachsilbe", @@ -1188,7 +1191,11 @@ export const de = { "cancelChanges": "Änderungen abbrechen", "rowSelectChange": "Zeile auswählen Ändern", "rowClick": "Reihe Klicken", - "rowExpand": "Reihe Erweitern", + "rowExpand": "Reihe verkleinern", + "rowShrink": "Zeilenverkleinerung", + "search": "Suchen", + "download": "Herunterladen", + "columnEdited": "Spalte bearbeitet", "filterChange": "Filterwechsel", "sortChange": "Sortieren Ändern", "pageChange": "Seitenwechsel", diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index ef8d3d165..4d330c32b 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -1239,6 +1239,9 @@ export const en = { "auto": "Auto", "fixed": "Fixed", "columnType": "Column Type", + "numberStep": "Step", + "numberStepTooltip": "The number to which the current value is increased or decreased. It can be an integer or decimal", + "precision": "Precision", "float": "Float", "prefix": "Prefix", "suffix": "Suffix", @@ -1294,6 +1297,10 @@ export const en = { "rowSelectChange": "Row Select Change", "rowClick": "Row Click", "rowExpand": "Row Expand", + "rowShrink": "Row Shrink", + "search": "Search", + "download": "Download", + "columnEdited": "Column Edited", "filterChange": "Filter Change", "sortChange": "Sort Change", "pageChange": "Page Change", diff --git a/client/packages/lowcoder/src/i18n/locales/zh.ts b/client/packages/lowcoder/src/i18n/locales/zh.ts index fe235979e..63cb07acf 100644 --- a/client/packages/lowcoder/src/i18n/locales/zh.ts +++ b/client/packages/lowcoder/src/i18n/locales/zh.ts @@ -1210,6 +1210,9 @@ table: { auto: "自动", fixed: "固定", columnType: "列类型", + numberStep: "步", + numberStepTooltip: "当前值增加或减少的数量。它可以是整数或小数", + precision: "精度", float: "分数", prefix: "字首", suffix: "后缀", @@ -1265,6 +1268,10 @@ table: { rowSelectChange: "行选中变化", rowClick: "行点击", rowExpand: "行展开", + rowShrink: "行收缩", + search: "搜索", + download: "下载", + columnEdited: "栏目已编辑", filterChange: "筛选变化", sortChange: "排序变化", pageChange: "分页变化",