Skip to content

Commit c490d82

Browse files
Merge branch 'dev' into ptm-apps-enhancements
2 parents d4ea385 + c2b90de commit c490d82

39 files changed

+2690
-181
lines changed

‎README.md

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ And we mean it... Day by day!
8585
🔎 Submit an issue here on [GitHub](https://github.com/lowcoder-org/lowcoder/issues)
8686

8787
## 💻 Deployment Options
88+
[![Deploy to AWS using Stitch](https://img.shields.io/badge/deploy_with-Stitch-%23E369F7?logo=amazonaws&color=%23E369F7)](https://deploy.stitch.tech/lowcoder/lowcoder)
89+
8890
You can access Lowcoder from [cloud-hosted version](https://app.lowcoder.cloud/) at any time, or use the following resources for self-host Lowcoder on different platforms:
8991
- [Docker](https://docs.lowcoder.cloud/lowcoder-documentation/setup-and-run/self-hosting)
9092

‎client/VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.3.0
1+
2.3.1

‎client/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lowcoder-root",
3-
"version": "2.3.0",
3+
"version": "2.3.1",
44
"type": "module",
55
"private": true,
66
"workspaces": [
@@ -70,6 +70,7 @@
7070
},
7171
"dependencies": {
7272
"@lottiefiles/react-lottie-player": "^3.5.3",
73+
"@remixicon/react": "^4.1.1",
7374
"@testing-library/react": "^14.1.2",
7475
"@testing-library/user-event": "^14.5.1",
7576
"@types/styled-components": "^5.1.34",

‎client/packages/lowcoder-comps/src/comps/calendarComp/calendarConstants.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,9 @@ export const Wrapper = styled.div<{
205205
flex-direction: inherit;
206206
}
207207
.fc-day-today .fc-daygrid-day-number {
208-
background-color: ${(props) => props.$theme.primary};
208+
background-color: ${(props) => props.$theme?.primary ? props.$theme.primary : props.$style.background};
209209
color: ${(props) =>
210-
contrastText(props.$theme.primary || "", props.$theme.textDark, props.$theme.textLight)};
210+
contrastText(props.$theme?.primary || "", props.$theme?.textDark || "#000000", props.$theme?.textLight || "#ffffff")};
211211
}
212212
.fc-daygrid-day-events {
213213
padding: 1px 0 5px 0;
@@ -585,10 +585,10 @@ export const Wrapper = styled.div<{
585585
}
586586
.fc-day-today.fc-col-header-cell {
587587
background-color: ${(props) =>
588-
isDarkColor(props.$style.background) ? "#ffffff19" : toHex(props.$theme.primary!) + "19"};
588+
isDarkColor(props.$style.background) ? "#ffffff19" : toHex(props.$theme?.primary!) + "19"};
589589
a {
590590
color: ${(props) =>
591-
!isDarkColor(props.$style.background) && darkenColor(props.$theme.primary!, 0.1)};
591+
!isDarkColor(props.$style.background) && darkenColor(props.$theme?.primary!, 0.1)};
592592
}
593593
}
594594
.fc-col-header-cell-cushion {

‎client/packages/lowcoder-design/src/components/edit.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const TextInput = styled(Input)<InputProps & { $hasPrefix?: boolean }>`
6868
border: none;
6969
padding: 0 8px 0 4px;
7070
padding-left: ${(props) => (props.$hasPrefix ? "28px" : "4px")};
71-
color: #ffffff;
71+
color: #444444;
7272
line-height: 28px;
7373
font-size: 14px;
7474

‎client/packages/lowcoder-design/src/components/iconSelect/index.tsx

+112-38
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
22
import type { IconDefinition } from "@fortawesome/free-regular-svg-icons";
3-
import { default as Popover } from "antd/es/popover";
4-
import { ActionType } from '@rc-component/trigger/lib/interface';
3+
// import type { IconDefinition as IconDefinitionBrands } from "@fortawesome/free-brands-svg-icons";
4+
import { Popover } from "antd";
5+
import { ActionType } from "@rc-component/trigger/lib/interface";
56
import { TacoInput } from "components/tacoInput";
67
import { Tooltip } from "components/toolTip";
78
import { trans } from "i18n/design";
89
import _ from "lodash";
9-
import { ReactNode, useEffect, useCallback, useMemo, useRef, useState } from "react";
10+
import {
11+
ReactNode,
12+
useEffect,
13+
useCallback,
14+
useMemo,
15+
useRef,
16+
useState,
17+
} from "react";
1018
import Draggable from "react-draggable";
1119
import { default as List, ListRowProps } from "react-virtualized/dist/es/List";
1220
import styled from "styled-components";
1321
import { CloseIcon, SearchIcon } from "icons";
22+
import { ANTDICON } from "icons/antIcon";
23+
import { Divider } from "antd-mobile";
1424

1525
const PopupContainer = styled.div`
16-
width: 408px;
26+
width: 580px;
1727
background: #ffffff;
1828
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
1929
border-radius: 8px;
@@ -76,25 +86,28 @@ const IconList = styled(List)`
7686
background-color: rgba(139, 143, 163, 0.36);
7787
}
7888
`;
89+
7990
const IconRow = styled.div`
8091
padding: 0 6px;
8192
display: flex;
82-
align-items: center;
93+
align-items: flex-start; /* Align items to the start to allow different heights */
8394
justify-content: space-between;
8495
8596
&:last-child {
8697
gap: 8px;
8798
justify-content: flex-start;
8899
}
89100
`;
101+
90102
const IconItemContainer = styled.div`
91-
width: 40px;
92-
height: 40px;
103+
width: 60px;
93104
display: flex;
94-
align-items: center;
95-
justify-content: center;
105+
flex-direction: column;
106+
align-items: center;
107+
justify-content: flex-start;
96108
cursor: pointer;
97-
font-size: 20px;
109+
font-size: 28px;
110+
margin-bottom: 24px;
98111
99112
&:hover {
100113
border: 1px solid #315efb;
@@ -108,13 +121,41 @@ const IconItemContainer = styled.div`
108121
}
109122
`;
110123

124+
const IconWrapper = styled.div`
125+
height: auto;
126+
display: flex;
127+
align-items: center;
128+
justify-content: center;
129+
`;
130+
131+
const IconKeyDisplay = styled.div`
132+
font-size: 8px;
133+
color: #8b8fa3;
134+
margin-top: 4px; /* Space between the icon and the text */
135+
text-align: center;
136+
word-wrap: break-word; /* Ensure text wraps */
137+
width: 100%; /* Ensure the container can grow */
138+
`;
139+
111140
class Icon {
112141
readonly title: string;
113-
constructor(readonly def: IconDefinition, readonly names: string[]) {
114-
this.title = def.iconName.split("-").map(_.upperFirst).join(" ");
142+
constructor(readonly def: IconDefinition | any, readonly names: string[]) {
143+
if (def?.iconName) {
144+
this.title = def.iconName.split("-").map(_.upperFirst).join(" ");
145+
} else {
146+
this.title = names[0].slice(5);
147+
this.def = def;
148+
}
115149
}
116150
getView() {
117-
return <FontAwesomeIcon icon={this.def} style={{ width: "1em", height: "1em" }} />;
151+
if (this.names[0]?.startsWith("antd/")) return this.def;
152+
else
153+
return (
154+
<FontAwesomeIcon
155+
icon={this.def}
156+
style={{ width: "1em", height: "1em"}}
157+
/>
158+
);
118159
}
119160
}
120161

@@ -127,6 +168,7 @@ async function getAllIcons() {
127168
const [{ far }, { fas }] = await Promise.all([
128169
import("@fortawesome/free-regular-svg-icons"),
129170
import("@fortawesome/free-solid-svg-icons"),
171+
// import("@fontawesome/free-brands-svg-icons"),
130172
]);
131173
const ret: Record<string, Icon> = {};
132174
for (const [type, pack] of Object.entries({ solid: fas, regular: far })) {
@@ -144,14 +186,25 @@ async function getAllIcons() {
144186
}
145187
}
146188
}
189+
//append ant icon
190+
for (let key of Object.keys(ANTDICON)) {
191+
ret["antd/" + key] = new Icon(
192+
ANTDICON[key.toLowerCase() as keyof typeof ANTDICON],
193+
["antd/" + key]
194+
);
195+
}
147196
allIcons = ret;
148197
return ret;
149198
}
150199

151200
export const iconPrefix = "/icon:";
152201

153202
export function removeQuote(value?: string) {
154-
return value ? (value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value) : "";
203+
return value
204+
? value.startsWith('"') && value.endsWith('"')
205+
? value.slice(1, -1)
206+
: value
207+
: "";
155208
}
156209

157210
function getIconKey(value?: string) {
@@ -171,7 +224,8 @@ export function useIcon(value?: string) {
171224
function search(
172225
allIcons: Record<string, Icon>,
173226
searchText: string,
174-
searchKeywords?: Record<string, string>
227+
searchKeywords?: Record<string, string>,
228+
IconType?: "OnlyAntd" | "All" | "default" | undefined
175229
) {
176230
const tokens = searchText
177231
.toLowerCase()
@@ -182,6 +236,8 @@ function search(
182236
if (icon.names.length === 0) {
183237
return false;
184238
}
239+
if (IconType === "OnlyAntd" && !key.startsWith("antd/")) return false;
240+
if (IconType === "default" && key.startsWith("antd/")) return false;
185241
let text = icon.names
186242
.flatMap((name) => [name, searchKeywords?.[name]])
187243
.filter((t) => t)
@@ -198,43 +254,54 @@ const IconPopup = (props: {
198254
label?: ReactNode;
199255
onClose: () => void;
200256
searchKeywords?: Record<string, string>;
257+
IconType?: "OnlyAntd" | "All" | "default" | undefined;
201258
}) => {
202259
const [searchText, setSearchText] = useState("");
203260
const [allIcons, setAllIcons] = useState<Record<string, Icon>>({});
204261
const searchResults = useMemo(
205-
() => search(allIcons, searchText, props.searchKeywords),
262+
() => search(allIcons, searchText, props.searchKeywords, props.IconType),
206263
[searchText, allIcons]
207264
);
208265
const onChangeRef = useRef(props.onChange);
209266
onChangeRef.current = props.onChange;
210-
const onChangeIcon = useCallback((key: string) => onChangeRef.current(iconPrefix + key), []);
267+
const onChangeIcon = useCallback(
268+
(key: string) => onChangeRef.current(iconPrefix + key),
269+
[]
270+
);
211271
const columnNum = 8;
212272

213273
useEffect(() => {
214274
getAllIcons().then(setAllIcons);
215275
}, []);
216276

277+
const smallTextStyle = {
278+
fontSize: '8px'
279+
};
280+
217281
const rowRenderer = useCallback(
218282
(p: ListRowProps) => (
219283
<IconRow key={p.key} style={p.style}>
220-
{searchResults.slice(p.index * columnNum, (p.index + 1) * columnNum).map(([key, icon]) => (
221-
<Tooltip
222-
key={key}
223-
title={icon.title}
224-
placement="bottom"
225-
align={{ offset: [0, -7, 0, 0] }}
226-
destroyTooltipOnHide
227-
>
228-
<IconItemContainer
229-
tabIndex={0}
230-
onClick={() => {
231-
onChangeIcon(key);
232-
}}
284+
{searchResults
285+
.slice(p.index * columnNum, (p.index + 1) * columnNum)
286+
.map(([key, icon]) => (
287+
<Tooltip
288+
key={key}
289+
title={icon.title + ", Key: " + key}
290+
placement="bottom"
291+
align={{ offset: [0, -7, 0, 0] }}
292+
destroyTooltipOnHide
233293
>
234-
{icon.getView()}
235-
</IconItemContainer>
236-
</Tooltip>
237-
))}
294+
<IconItemContainer
295+
tabIndex={0}
296+
onClick={() => {
297+
onChangeIcon(key);
298+
}}
299+
>
300+
<IconWrapper>{icon.getView()}</IconWrapper>
301+
<IconKeyDisplay>{key}</IconKeyDisplay>
302+
</IconItemContainer>
303+
</Tooltip>
304+
))}
238305
</IconRow>
239306
),
240307
[searchResults, allIcons, onChangeIcon]
@@ -257,9 +324,9 @@ const IconPopup = (props: {
257324
</SearchDiv>
258325
<IconListWrapper>
259326
<IconList
260-
width={394}
261-
height={312}
262-
rowHeight={48}
327+
width={550}
328+
height={400}
329+
rowHeight={80}
263330
rowCount={Math.ceil(searchResults.length / columnNum)}
264331
rowRenderer={rowRenderer}
265332
/>
@@ -279,6 +346,7 @@ export const IconSelectBase = (props: {
279346
leftOffset?: number;
280347
parent?: HTMLElement | null;
281348
searchKeywords?: Record<string, string>;
349+
IconType?: "OnlyAntd" | "All" | "default" | undefined;
282350
}) => {
283351
const { setVisible, parent } = props;
284352
return (
@@ -290,7 +358,11 @@ export const IconSelectBase = (props: {
290358
onOpenChange={setVisible}
291359
getPopupContainer={parent ? () => parent : undefined}
292360
// hide the original background when dragging the popover is allowed
293-
overlayInnerStyle={{ border: "none", boxShadow: "none", background: "transparent" }}
361+
overlayInnerStyle={{
362+
border: "none",
363+
boxShadow: "none",
364+
background: "transparent",
365+
}}
294366
// when dragging is allowed, always re-location to avoid the popover exceeds the screen
295367
destroyTooltipOnHide
296368
content={
@@ -299,6 +371,7 @@ export const IconSelectBase = (props: {
299371
label={props.label}
300372
onClose={() => setVisible?.(false)}
301373
searchKeywords={props.searchKeywords}
374+
IconType={props.IconType}
302375
/>
303376
}
304377
>
@@ -312,6 +385,7 @@ export const IconSelect = (props: {
312385
label?: ReactNode;
313386
children?: ReactNode;
314387
searchKeywords?: Record<string, string>;
388+
IconType?: "OnlyAntd" | "All" | "default" | undefined;
315389
}) => {
316390
const [visible, setVisible] = useState(false);
317391
return (

0 commit comments

Comments
 (0)