Skip to content

Commit 9752906

Browse files
committed
[Feat]: Add event handlers on more column types
1 parent 2dedc8f commit 9752906

File tree

9 files changed

+163
-28
lines changed

9 files changed

+163
-28
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { withDefault } from "comps/generators";
99
import styled from "styled-components";
1010
import { IconControl } from "comps/controls/iconControl";
1111
import { hasIcon } from "comps/utils";
12+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
1213

1314
const InputNumberWrapper = styled.div`
1415
.ant-input-number {
@@ -25,6 +26,15 @@ const InputNumberWrapper = styled.div`
2526
}
2627
`;
2728

29+
const NumberViewWrapper = styled.div`
30+
cursor: pointer;
31+
display: flex;
32+
align-items: center;
33+
gap: 4px;
34+
`;
35+
36+
const NumberEventOptions = [clickEvent] as const;
37+
2838
const childrenMap = {
2939
text: NumberControl,
3040
step: withDefault(NumberControl, 1),
@@ -34,6 +44,7 @@ const childrenMap = {
3444
prefixIcon: IconControl,
3545
suffixIcon: IconControl,
3646
suffix: StringControl,
47+
onEvent: eventHandlerControl(NumberEventOptions),
3748
};
3849

3950
const getBaseValue: ColumnTypeViewFn<typeof childrenMap, number, number> = (props) => props.text;
@@ -46,6 +57,7 @@ type NumberViewProps = {
4657
suffixIcon: ReactNode;
4758
float: boolean;
4859
precision: number;
60+
onEvent?: (eventName: string) => void;
4961
};
5062

5163
type NumberEditProps = {
@@ -66,16 +78,22 @@ const ColumnNumberView = React.memo((props: NumberViewProps) => {
6678
return result;
6779
}, [props.value, props.float, props.precision]);
6880

81+
const handleClick = useCallback(() => {
82+
if (props.onEvent) {
83+
props.onEvent("click");
84+
}
85+
}, [props.onEvent]);
86+
6987
return (
70-
<>
88+
<NumberViewWrapper onClick={handleClick}>
7189
{hasIcon(props.prefixIcon) && (
7290
<span>{props.prefixIcon}</span>
7391
)}
7492
<span>{props.prefix + formattedValue + props.suffix}</span>
7593
{hasIcon(props.suffixIcon) && (
7694
<span>{props.suffixIcon}</span>
7795
)}
78-
</>
96+
</NumberViewWrapper>
7997
);
8098
});
8199

@@ -197,6 +215,7 @@ export const ColumnNumberComp = (function () {
197215
children.step.dispatchChangeValueAction(String(newValue));
198216
}
199217
})}
218+
{children.onEvent.propertyView()}
200219
</>
201220
);
202221
})

client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnAvatarsComp.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const Container = styled.div<{ $style: AvatarGroupStyleType | undefined, alignme
3838
cursor: pointer;
3939
`;
4040

41+
const AvatarEventOptions = [clickEvent, refreshEvent] as const;
42+
4143
const DropdownOption = new MultiCompBuilder(
4244
{
4345
src: StringControl,
@@ -46,6 +48,7 @@ const DropdownOption = new MultiCompBuilder(
4648
color: ColorControl,
4749
backgroundColor: ColorControl,
4850
Tooltip: StringControl,
51+
onEvent: eventHandlerControl(AvatarEventOptions),
4952
},
5053
(props) => props
5154
)
@@ -63,6 +66,7 @@ const DropdownOption = new MultiCompBuilder(
6366
{children.color.propertyView({ label: trans("style.fill") })}
6467
{children.backgroundColor.propertyView({ label: trans("style.background") })}
6568
{children.Tooltip.propertyView({ label: trans("badge.tooltip") })}
69+
{children.onEvent.propertyView()}
6670
</>
6771
);
6872
})
@@ -83,14 +87,16 @@ const MemoizedAvatar = React.memo(({
8387
style,
8488
autoColor,
8589
avatarSize,
86-
onEvent
90+
onEvent,
91+
onItemEvent
8792
}: {
8893
item: any;
8994
index: number;
9095
style: any;
9196
autoColor: boolean;
9297
avatarSize: number;
93-
onEvent: (event: string) => void;
98+
onEvent: (event: string) => void;
99+
onItemEvent?: (event: string) => void;
94100
}) => {
95101
const mountedRef = useRef(true);
96102

@@ -103,8 +109,15 @@ const MemoizedAvatar = React.memo(({
103109

104110
const handleClick = useCallback(() => {
105111
if (!mountedRef.current) return;
112+
113+
// Trigger individual avatar event first
114+
if (onItemEvent) {
115+
onItemEvent("click");
116+
}
117+
118+
// Then trigger main component event
106119
onEvent("click");
107-
}, [onEvent]);
120+
}, [onEvent, onItemEvent]);
108121

109122
return (
110123
<Tooltip title={item.Tooltip} key={index}>
@@ -114,6 +127,7 @@ const MemoizedAvatar = React.memo(({
114127
style={{
115128
color: item.color ? item.color : (style.fill !== '#FFFFFF' ? style.fill : '#FFFFFF'),
116129
backgroundColor: item.backgroundColor ? item.backgroundColor : (autoColor ? MacaroneList[index % MacaroneList.length] : style.background),
130+
cursor: 'pointer',
117131
}}
118132
size={avatarSize}
119133
onClick={handleClick}
@@ -162,6 +176,7 @@ const MemoizedAvatarGroup = React.memo(({
162176
autoColor={autoColor}
163177
avatarSize={avatarSize}
164178
onEvent={onEvent}
179+
onItemEvent={item.onEvent}
165180
/>
166181
))}
167182
</Avatar.Group>

client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnImgComp.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,28 @@ import { withDefault } from "comps/generators";
1010
import { TacoImage } from "lowcoder-design";
1111
import styled from "styled-components";
1212
import { DEFAULT_IMG_URL } from "@lowcoder-ee/util/stringUtils";
13+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
1314

1415
export const ColumnValueTooltip = trans("table.columnValueTooltip");
1516

1617
const childrenMap = {
1718
src: withDefault(StringControl, "{{currentCell}}"),
1819
size: withDefault(NumberControl, "50"),
20+
onEvent: eventHandlerControl([clickEvent]),
1921
};
2022

2123
const StyledTacoImage = styled(TacoImage)`
22-
pointer-events: auto;
24+
pointer-events: auto !important;
25+
cursor: pointer !important;
26+
27+
&:hover {
28+
opacity: 0.8;
29+
transition: opacity 0.2s ease;
30+
}
2331
`;
2432

2533
// Memoized image component
26-
const ImageView = React.memo(({ src, size }: { src: string; size: number }) => {
34+
const ImageView = React.memo(({ src, size, onEvent }: { src: string; size: number; onEvent?: (eventName: string) => void }) => {
2735
const mountedRef = useRef(true);
2836

2937
// Cleanup on unmount
@@ -33,10 +41,19 @@ const ImageView = React.memo(({ src, size }: { src: string; size: number }) => {
3341
};
3442
}, []);
3543

44+
const handleClick = useCallback(() => {
45+
console.log("Image clicked!", { src, onEvent: !!onEvent }); // Debug log
46+
if (mountedRef.current && onEvent) {
47+
onEvent("click");
48+
}
49+
}, [onEvent, src]);
50+
3651
return (
3752
<StyledTacoImage
3853
src={src || DEFAULT_IMG_URL}
3954
width={size}
55+
onClick={handleClick}
56+
style={{ cursor: 'pointer' }} // Inline style as backup
4057
/>
4158
);
4259
});
@@ -96,7 +113,7 @@ export const ImageComp = (function () {
96113
childrenMap,
97114
(props, dispatch) => {
98115
const value = props.changeValue ?? getBaseValue(props, dispatch);
99-
return <ImageView src={value} size={props.size} />;
116+
return <ImageView src={value} size={props.size} onEvent={props.onEvent} />;
100117
},
101118
(nodeValue) => nodeValue.src.value,
102119
getBaseValue
@@ -118,6 +135,7 @@ export const ImageComp = (function () {
118135
{children.size.propertyView({
119136
label: trans("table.imageSize"),
120137
})}
138+
{children.onEvent.propertyView()}
121139
</>
122140
);
123141
})

client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnLinksComp.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const OptionItem = new MultiCompBuilder(
7070
.build();
7171

7272
// Memoized menu item component
73-
const MenuItem = React.memo(({ option, index }: { option: any; index: number }) => {
73+
const MenuItem = React.memo(({ option, index, onMainEvent }: { option: any; index: number; onMainEvent?: (eventName: string) => void }) => {
7474
const handleClick = useCallback(() => {
7575
if (!option.disabled) {
7676
if (option.onClick) {
@@ -79,8 +79,12 @@ const MenuItem = React.memo(({ option, index }: { option: any; index: number })
7979
if (option.onEvent) {
8080
option.onEvent("click");
8181
}
82+
// Trigger the main component's event handler
83+
if (onMainEvent) {
84+
onMainEvent("click");
85+
}
8286
}
83-
}, [option.disabled, option.onClick, option.onEvent]);
87+
}, [option.disabled, option.onClick, option.onEvent, onMainEvent]);
8488

8589
return (
8690
<MenuLinkWrapper>
@@ -96,7 +100,7 @@ const MenuItem = React.memo(({ option, index }: { option: any; index: number })
96100
MenuItem.displayName = 'MenuItem';
97101

98102
// Memoized menu component
99-
const LinksMenu = React.memo(({ options }: { options: any[] }) => {
103+
const LinksMenu = React.memo(({ options, onEvent }: { options: any[]; onEvent?: (eventName: string) => void }) => {
100104
const mountedRef = useRef(true);
101105

102106
// Cleanup on unmount
@@ -111,9 +115,9 @@ const LinksMenu = React.memo(({ options }: { options: any[] }) => {
111115
.filter((o) => !o.hidden)
112116
.map((option, index) => ({
113117
key: index,
114-
label: <MenuItem option={option} index={index} />
118+
label: <MenuItem option={option} index={index} onMainEvent={onEvent} />
115119
})),
116-
[options]
120+
[options, onEvent]
117121
);
118122

119123
return (
@@ -130,11 +134,12 @@ export const ColumnLinksComp = (function () {
130134
options: manualOptionsControl(OptionItem, {
131135
initOptions: [{ label: trans("table.option1") }],
132136
}),
137+
onEvent: eventHandlerControl(LinksEventOptions),
133138
};
134139
return new ColumnTypeCompBuilder(
135140
childrenMap,
136141
(props) => {
137-
return <LinksMenu options={props.options} />;
142+
return <LinksMenu options={props.options} onEvent={props.onEvent} />;
138143
},
139144
() => ""
140145
)
@@ -144,6 +149,7 @@ export const ColumnLinksComp = (function () {
144149
newOptionLabel: trans("table.option"),
145150
title: trans("table.optionList"),
146151
})}
152+
{children.onEvent.propertyView()}
147153
</>
148154
))
149155
.build();

client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/columnMarkdownComp.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import { StringControl } from "comps/controls/codeControl";
99
import { trans } from "i18n";
1010
import { markdownCompCss, TacoMarkDown } from "lowcoder-design";
1111
import styled from "styled-components";
12+
import { clickEvent, eventHandlerControl } from "comps/controls/eventHandlerControl";
1213

1314
const Wrapper = styled.div`
1415
${markdownCompCss};
1516
max-height: 32px;
17+
cursor: pointer;
1618
1719
> .markdown-body {
1820
margin: 0;
@@ -22,16 +24,25 @@ const Wrapper = styled.div`
2224
}
2325
`;
2426

27+
const MarkdownEventOptions = [clickEvent] as const;
28+
2529
const childrenMap = {
2630
text: StringControl,
31+
onEvent: eventHandlerControl(MarkdownEventOptions),
2732
};
2833

2934
const getBaseValue: ColumnTypeViewFn<typeof childrenMap, string, string> = (props) => props.text;
3035

3136
// Memoized markdown view component
32-
const MarkdownView = React.memo(({ value }: { value: string }) => {
37+
const MarkdownView = React.memo(({ value, onEvent }: { value: string; onEvent?: (eventName: string) => void }) => {
38+
const handleClick = useCallback(() => {
39+
if (onEvent) {
40+
onEvent("click");
41+
}
42+
}, [onEvent]);
43+
3344
return (
34-
<Wrapper>
45+
<Wrapper onClick={handleClick}>
3546
<TacoMarkDown>{value}</TacoMarkDown>
3647
</Wrapper>
3748
);
@@ -92,7 +103,7 @@ export const ColumnMarkdownComp = (function () {
92103
childrenMap,
93104
(props, dispatch) => {
94105
const value = props.changeValue ?? getBaseValue(props, dispatch);
95-
return <MarkdownView value={value} />;
106+
return <MarkdownView value={value} onEvent={props.onEvent} />;
96107
},
97108
(nodeValue) => nodeValue.text.value,
98109
getBaseValue
@@ -110,6 +121,7 @@ export const ColumnMarkdownComp = (function () {
110121
label: trans("table.columnValue"),
111122
tooltip: ColumnValueTooltip,
112123
})}
124+
{children.onEvent.propertyView()}
113125
</>
114126
))
115127
.build();

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ const SelectOptionWithEventsControl = optionsControl(SelectOptionWithEvents, {
116116
const childrenMap = {
117117
text: StringControl,
118118
options: SelectOptionWithEventsControl,
119+
onEvent: eventHandlerControl(SelectOptionEventOptions),
119120
};
120121

121122
const getBaseValue: ColumnTypeViewFn<typeof childrenMap, string, string> = (props) => props.text;
@@ -125,6 +126,7 @@ type SelectEditProps = {
125126
onChange: (value: string) => void;
126127
onChangeEnd: () => void;
127128
options: any[];
129+
onMainEvent?: (eventName: string) => void;
128130
};
129131

130132
const SelectEdit = React.memo((props: SelectEditProps) => {
@@ -150,7 +152,12 @@ const SelectEdit = React.memo((props: SelectEditProps) => {
150152
if (selectedOption && selectedOption.onEvent) {
151153
selectedOption.onEvent("click");
152154
}
153-
}, [props.onChange, props.options]);
155+
156+
// Also trigger the main component's event handler
157+
if (props.onMainEvent) {
158+
props.onMainEvent("click");
159+
}
160+
}, [props.onChange, props.options, props.onMainEvent]);
154161

155162
const handleEvent = useCallback(async (eventName: string) => {
156163
if (!mountedRef.current) return [] as unknown[];
@@ -203,6 +210,7 @@ export const ColumnSelectComp = (function () {
203210
options={props.otherProps?.options || []}
204211
onChange={props.onChange}
205212
onChangeEnd={props.onChangeEnd}
213+
onMainEvent={props.otherProps?.onEvent}
206214
/>
207215
</Wrapper>
208216
)
@@ -217,6 +225,7 @@ export const ColumnSelectComp = (function () {
217225
{children.options.propertyView({
218226
title: trans("optionsControl.optionList"),
219227
})}
228+
{children.onEvent.propertyView()}
220229
</>
221230
);
222231
})

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