Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit327e4f8

Browse files
authored
Merge pull request#1114 from lowcoder-org/table-summary-row
Table summary row + Inline add new row
2 parents64d5bbd +7f157db commit327e4f8

21 files changed

+1056
-187
lines changed

‎client/packages/lowcoder/src/components/table/EditableCell.tsx

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export interface CellProps {
3737
candidateStatus?:{text:string;status:StatusType}[];
3838
textOverflow?:boolean;
3939
cellTooltip?:string;
40+
editMode?:string;
4041
onTableEvent?:(eventName:any)=>void;
4142
}
4243

@@ -94,17 +95,19 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
9495
candidateTags,
9596
// tagColors
9697
candidateStatus,
98+
editMode,
9799
onTableEvent,
98100
}=props;
99101
conststatus=_.isNil(changeValue) ?"normal" :"toSave";
100102
consteditable=editViewFn ?props.editable :false;
101103
const{ isEditing, setIsEditing}=useContext(TableCellContext);
102104
constvalue=changeValue??baseValue!;
103105
const[tmpValue,setTmpValue]=useState<T|null>(value);
106+
constsingleClickEdit=editMode==='single';
104107

105108
useEffect(()=>{
106109
setTmpValue(value);
107-
},[value]);
110+
},[JSON.stringify(value)]);
108111

109112
constonChange=useCallback(
110113
(value:T)=>{
@@ -125,21 +128,27 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
125128
if(!_.isEqual(tmpValue,value)){
126129
onTableEvent?.('columnEdited');
127130
}
128-
},[dispatch,baseValue,tmpValue]);
131+
},[dispatch,JSON.stringify(baseValue),JSON.stringify(tmpValue)]);
132+
129133
consteditView=useMemo(
130134
()=>editViewFn?.({ value, onChange, onChangeEnd})??<></>,
131-
[editViewFn,value,onChange,onChangeEnd]
135+
[editViewFn,JSON.stringify(value),onChange,onChangeEnd]
132136
);
137+
133138
constenterEditFn=useCallback(()=>{
134139
if(editable)setIsEditing(true);
135140
},[editable]);
136141

137142
if(isEditing){
138143
return(
139144
<>
140-
<BorderDiv/>
145+
<BorderDivclassName="editing-border"/>
141146
<TagsContext.Providervalue={candidateTags??[]}>
142-
<StatusContext.Providervalue={candidateStatus??[]}>{editView}</StatusContext.Provider>
147+
<StatusContext.Providervalue={candidateStatus??[]}>
148+
<divclassName="editing-wrapper">
149+
{editView}
150+
</div>
151+
</StatusContext.Provider>
143152
</TagsContext.Provider>
144153
</>
145154
);
@@ -151,7 +160,12 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
151160
>
152161
{status==="toSave"&&!isEditing&&<EditableChip/>}
153162
<CellWrappertooltipTitle={props.cellTooltip}>
154-
{normalView}
163+
<div
164+
tabIndex={editable ?0 :-1}
165+
onFocus={enterEditFn}
166+
>
167+
{normalView}
168+
</div>
155169
</CellWrapper>
156170
{/* overlay on normal view to handle double click for editing */}
157171
{editable&&(
@@ -164,7 +178,8 @@ export function EditableCell<T extends JSONValue>(props: EditableCellProps<T>) {
164178
width:'100%',
165179
height:'100%',
166180
}}
167-
onDoubleClick={enterEditFn}
181+
onDoubleClick={!singleClickEdit ?enterEditFn :undefined}
182+
onClick={singleClickEdit ?enterEditFn :undefined}
168183
>
169184
</div>
170185
</CellWrapper>

‎client/packages/lowcoder/src/comps/comps/selectInputComp/selectCompConstants.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,12 @@ export const SelectUIView = (
253253
inputFieldStyle:SelectStyleType;
254254
onChange:(value:any)=>void;
255255
dispatch:DispatchType;
256+
autoFocus?:boolean;
256257
}
257258
)=>{
258259
return<Select
259260
ref={props.viewRef}
261+
autoFocus={props.autoFocus}
260262
mode={props.mode}
261263
$inputFieldStyle={props.inputFieldStyle}
262264
$style={props.styleasSelectStyleType&MultiSelectStyleType}

‎client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/ColumnNumberComp.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const InputNumberWrapper = styled.div`
1414
width: 100%;
1515
border-radius: 0;
1616
background: transparent !important;
17-
padding: 0 !important;
17+
//padding: 0 !important;
1818
box-shadow: none;
1919
2020
input {

‎client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnDateComp.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ const DatePickerStyled = styled(DatePicker)<{ $open: boolean }>`
4949
top: 0.5px;
5050
display: flex;
5151
align-items: center;
52-
background: #fff;
52+
//background: #fff;
5353
padding: 0 3px;
54-
border-left: 1px solid #d7d9e0;
54+
//border-left: 1px solid #d7d9e0;
5555
}
5656
`;
5757

@@ -183,7 +183,7 @@ export const DateEdit = (props: DateEditProps) => {
183183
nextIcon={<IconNext/>}
184184
superNextIcon={<IconSuperNext/>}
185185
superPrevIcon={<SuperPrevIcon/>}
186-
allowClear={false}
186+
allowClear={true}
187187
variant="borderless"
188188
autoFocus
189189
value={tempValue}
@@ -197,7 +197,9 @@ export const DateEdit = (props: DateEditProps) => {
197197
overflow:"hidden",
198198
}}
199199
onOpenChange={(open)=>setPanelOpen(open)}
200-
onChange={(value,dateString)=>props.onChange(dateStringasstring)}
200+
onChange={(value,dateString)=>{
201+
props.onChange(dateStringasstring)
202+
}}
201203
onBlur={()=>props.onChangeEnd()}
202204
/>
203205
</Wrapper>

‎client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnSelectComp.tsx

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,73 @@ import { StringControl } from "comps/controls/codeControl";
77
import{trans}from"i18n";
88
import{ColumnTypeCompBuilder,ColumnTypeViewFn}from"../columnTypeCompBuilder";
99
import{ColumnValueTooltip}from"../simpleColumnTypeComps";
10+
import{styled}from"styled-components";
11+
12+
constWrapper=styled.div`
13+
display: inline-flex;
14+
align-items: center;
15+
width: 100%;
16+
height: 100%;
17+
position: absolute;
18+
top: 0;
19+
background: transparent !important;
20+
padding: 8px;
21+
22+
> div {
23+
width: 100%;
24+
height: 100%;
25+
}
26+
27+
.ant-select {
28+
height: 100%;
29+
.ant-select-selector {
30+
padding: 0 7px;
31+
height: 100%;
32+
overflow: hidden;
33+
.ant-select-selection-item {
34+
display: inline-flex;
35+
align-items: center;
36+
padding-right: 24px;
37+
}
38+
}
39+
.ant-select-arrow {
40+
height: calc(100% - 3px);
41+
width: fit-content;
42+
top: 1.5px;
43+
margin-top: 0;
44+
background-color: white;
45+
right: 1.5px;
46+
border-right: 1px solid #d7d9e0;
47+
cursor: pointer;
48+
pointer-events: auto;
49+
svg {
50+
min-width: 18px;
51+
min-height: 18px;
52+
}
53+
&:hover svg path {
54+
fill: #315efb;
55+
}
56+
}
57+
.ant-select-selector .ant-select-selection-search {
58+
left: 7px;
59+
input {
60+
height: 100%;
61+
}
62+
}
63+
&.ant-select-open {
64+
.ant-select-arrow {
65+
border-right: none;
66+
border-left: 1px solid #d7d9e0;
67+
svg g path {
68+
fill: #315efb;
69+
}
70+
}
71+
.ant-select-selection-item {
72+
opacity: 0.4;
73+
}
74+
}
75+
}
76+
`;
1077

1178
constchildrenMap={
1279
text:StringControl,
@@ -28,6 +95,8 @@ const SelectEdit = (props: SelectEditProps) => {
2895
const[currentValue,setCurrentValue]=useState(props.initialValue);
2996
return(
3097
<SelectUIView
98+
autoFocus
99+
allowClear
31100
{...defaultProps}
32101
value={currentValue}
33102
options={props.options}
@@ -67,12 +136,14 @@ export const ColumnSelectComp = (function () {
67136
)
68137
.setEditViewFn((props)=>{
69138
return(
70-
<SelectEdit
71-
initialValue={props.value}
72-
options={options}
73-
onChange={props.onChange}
74-
onChangeEnd={props.onChangeEnd}
75-
/>
139+
<Wrapper>
140+
<SelectEdit
141+
initialValue={props.value}
142+
options={options}
143+
onChange={props.onChange}
144+
onChangeEnd={props.onChangeEnd}
145+
/>
146+
</Wrapper>
76147
)
77148
})
78149
.setPropertyViewFn((children)=>{

‎client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnStatusComp.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const StatusEdit = (props: StatusEditPropsType) => {
4848
constdefaultStatus=useContext(StatusContext);
4949
const[status,setStatus]=useState(defaultStatus);
5050
const[allOptions,setAllOptions]=useState(BadgeStatusOptions);
51-
const[open,setOpen]=useState(true);
51+
const[open,setOpen]=useState(false);
5252

5353
return(
5454
<Wrapper>
@@ -84,18 +84,20 @@ const StatusEdit = (props: StatusEditPropsType) => {
8484
value,
8585
status:status.find((item)=>item.text===value)?.status||"none",
8686
});
87+
setOpen(false)
8788
}}
8889
dropdownRender={(originNode:ReactNode)=>(
8990
<DropdownStyled>
9091
<ScrollBarstyle={{maxHeight:"256px"}}>{originNode}</ScrollBar>
9192
</DropdownStyled>
9293
)}
9394
dropdownStyle={{marginTop:"7px",padding:"8px 0 6px 0"}}
94-
onBlur={props.onChangeEnd}
95-
onKeyDown={(e)=>{
96-
if(e.key==="Enter"){
97-
props.onChangeEnd();
98-
}
95+
onBlur={()=>{
96+
props.onChangeEnd();
97+
setOpen(false);
98+
}}
99+
onFocus={()=>{
100+
setOpen(true);
99101
}}
100102
onClick={()=>setOpen(!open)}
101103
>

‎client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnTagsComp.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ export const Wrapper = styled.div`
9292
position: absolute;
9393
top: 0;
9494
background: transparent !important;
95+
padding: 8px;
96+
9597
> div {
9698
width: 100%;
9799
height: 100%;
@@ -147,7 +149,7 @@ export const Wrapper = styled.div`
147149
}
148150
}
149151
.ant-tag {
150-
margin-left:20px;
152+
margin-left:5px;
151153
}
152154
.ant-tag svg {
153155
margin-right: 4px;
@@ -159,6 +161,10 @@ export const DropdownStyled = styled.div`
159161
padding: 3px 8px;
160162
margin: 0 0 2px 8px;
161163
border-radius: 4px;
164+
165+
&.ant-select-item-option-active {
166+
background-color: #f2f7fc;
167+
}
162168
}
163169
.ant-select-item-option-content {
164170
display: flex;
@@ -193,7 +199,7 @@ const TagEdit = (props: TagEditPropsType) => {
193199
});
194200
returnresult;
195201
});
196-
const[open,setOpen]=useState(true);
202+
const[open,setOpen]=useState(false);
197203
return(
198204
<Wrapper>
199205
<CustomSelect
@@ -205,6 +211,7 @@ const TagEdit = (props: TagEditPropsType) => {
205211
defaultValue={props.value}
206212
style={{width:"100%"}}
207213
open={open}
214+
allowClear={true}
208215
suffixIcon={<PackUpIcon/>}
209216
onSearch={(value:string)=>{
210217
if(defaultTags.findIndex((item)=>item.includes(value))<0){
@@ -216,18 +223,20 @@ const TagEdit = (props: TagEditPropsType) => {
216223
}}
217224
onChange={(value:string|string[])=>{
218225
props.onChange(value);
226+
setOpen(false)
219227
}}
220228
dropdownRender={(originNode:ReactNode)=>(
221229
<DropdownStyled>
222230
<ScrollBarstyle={{maxHeight:"256px"}}>{originNode}</ScrollBar>
223231
</DropdownStyled>
224232
)}
225233
dropdownStyle={{marginTop:"7px",padding:"8px 0 6px 0"}}
226-
onBlur={props.onChangeEnd}
227-
onKeyDown={(e)=>{
228-
if(e.key==="Enter"){
229-
props.onChangeEnd();
230-
}
234+
onFocus={()=>{
235+
setOpen(true);
236+
}}
237+
onBlur={()=>{
238+
props.onChangeEnd();
239+
setOpen(false);
231240
}}
232241
onClick={()=>setOpen(!open)}
233242
>
@@ -259,7 +268,7 @@ export const ColumnTagsComp = (function () {
259268
tagOptionsList=props.tagColors;
260269
letvalue=props.changeValue??getBaseValue(props,dispatch);
261270
value=typeofvalue==="string"&&value.split(",")[1] ?value.split(",") :value;
262-
consttags=_.isArray(value) ?value :[value];
271+
consttags=_.isArray(value) ?value :(value.length ?[value] :[]);
263272
constview=tags.map((tag,index)=>{
264273
// The actual eval value is of type number or boolean
265274
consttagText=String(tag);

‎client/packages/lowcoder/src/comps/comps/tableComp/column/simpleColumnTypeComps.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const ButtonComp = (function () {
4545
loading={props.loading}
4646
disabled={props.disabled}
4747
$buttonStyle={props.buttonType==="primary" ?style :undefined}
48+
style={{margin:0}}
4849
>
4950
{/* prevent the button from disappearing */}
5051
{!props.text ?" " :props.text}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp