diff --git a/client/VERSION b/client/VERSION
index cc6612c36..a6254504e 100644
--- a/client/VERSION
+++ b/client/VERSION
@@ -1 +1 @@
-2.3.0
\ No newline at end of file
+2.3.1
\ No newline at end of file
diff --git a/client/package.json b/client/package.json
index fccf0fff1..f2054b530 100644
--- a/client/package.json
+++ b/client/package.json
@@ -70,6 +70,7 @@
},
"dependencies": {
"@lottiefiles/react-lottie-player": "^3.5.3",
+ "@remixicon/react": "^4.1.1",
"@testing-library/react": "^14.1.2",
"@testing-library/user-event": "^14.5.1",
"@types/styled-components": "^5.1.34",
diff --git a/client/packages/lowcoder-comps/README.md b/client/packages/lowcoder-comps/README.md
index 7c74d491a..15f56dc46 100644
--- a/client/packages/lowcoder-comps/README.md
+++ b/client/packages/lowcoder-comps/README.md
@@ -1,22 +1,100 @@
-# lowcoder comp lib
+# Lowcoder Extra Components
+
+This is the workspace for Lowcoder Extra Components like Calendar, Image Editor, Mermaid Charts and eCharts.
+
+## Local Development preparation
+
+Navigate your terminal or bash to your /root folder (lowcoder repository) to install Lowcoder Extra Components dependencies and the Lowcoder SDK
+
+To develop with the Lowcoder Extra Components after you clone the Lowcoder Repository, first make sure the Lowcoder SDK is local built.
+
+```bash
+cd client/packages/lowcoder-sdk
+yarn build
+```
## Start
-Start dev server to develop your comp lib.
+Now you can start the local dev server for Lowcoder Extra Components to develop and add your Component Plugin
```bash
+cd client/packages/lowcoder-comps
yarn start
+```
-# or
+The local dev server will build for roughly a minute and open then a Browser Window on http://localhost:9000/ with the Lowcoder Component Builder.
+
+## Local development
+
+After the local dev server is started, the Lowcoder Component Builder is prepared. A new browser window should open at http://localhost:9000 This is the Components Preview, which allows you to see your new component in action, as it would work in the Lowcoder Editor.
+
+Data, methods and properties are visible and interactive, so you can test your Component during development. The view will get automatically refreshed.
+
+The Lowcoder Component Builder makes the development & publishing of multiple individual components as bundle possible. Find the /src/comps folder in /lowcoder-comps. Here are existing components to find. It is suggested for new components to create a new folder. In the left navigation of the Components Preview you can switch between your components.
+
+to see your component and include it in the processing on the development server, you have to do the folloiwing steps:
+
+### modify /lowcoder-comps/package.json
+
+```JSON
+"yournewcomponent": {
+ "name": "Your new Component name",
+ "icon": "./icons/your-icon.svg",
+ "description": "A Component Plugin to ...",
+ "category": "itemHandling",
+ "layoutInfo": {
+ "w": 6,
+ "h": 30
+ }
+}
+```
-npm start
+
+Please choose one category out of:
+
+ - dashboards
+ - layout
+ - forms
+ - collaboration
+ - projectmanagement
+ - scheduling
+ - documents
+ - itemHandling
+ - multimedia
+ - integration
+
+layoutInfo helps you to define the size (in grid-cells) of your Component in the grid for the very first moment, when a user drags your Component out of the components display on the right side in the Lowcoder Editor.
+
+### modify /lowcoder-comps/src/index.ts
+
+```JavaScript
+Add your Component for the exported members of Lowcoder Extra Components
+
+import { ChartCompWithDefault } from "./comps/chartComp/chartComp";
+import { ImageEditorComp } from "./comps/imageEditorComp/index";
+import { CalendarComp } from "./comps/calendarComp/calendarComp";
+import { MermaidComp } from "comps/mermaidComp";
+
+import { YourComponent } from "comps/yourComponentFolder/yourComponent";
+
+export default {
+ chart: ChartCompWithDefault,
+ imageEditor: ImageEditorComp,
+ calendar: CalendarComp,
+ mermaid: MermaidComp,
+
+ yourcomponent: YourComponent,
+};
```
+Now your Plugin should be visibe and displayed in the Lowcoder Component Builder at http://localhost:9000/
## Build
-Build current comp lib into a .tgz file that you can upload it to the Lowcoder Comp Market.
+When you finish development and all tests, you can build the Components to use it in runtime.
-Before build you should change the version in package.json file.
+This will build the current Component Plugins into a .tgz file that you can upload.
+
+**Before build you should change the version in package.json file.**
```bash
yarn build
@@ -25,3 +103,18 @@ yarn build
npm run build
```
+
+## How to publish a Component Plugin
+
+With the following command you can publish the script to the NPM repository:
+
+```bash
+yarn build --publish
+```
+
+This command will publis the whole Lowcoder Extra Components bundle to [NPMjs](https://www.npmjs.com/)
+Make sure, you updated the Version of Lowcoder Comps before in /lowcoder-comps/package.json
+
+## Contribute your Plugin
+
+If you wish to contribute your plugin and persist it as general Lowcoder Extra Component, please raise a PR to our /dev branch in the Lowcoder Community-Edition Repository https://github.com/lowcoder-org/lowcoder
\ No newline at end of file
diff --git a/client/packages/lowcoder-comps/package.json b/client/packages/lowcoder-comps/package.json
index 1bf1dae92..43386ccf9 100644
--- a/client/packages/lowcoder-comps/package.json
+++ b/client/packages/lowcoder-comps/package.json
@@ -69,7 +69,7 @@
},
"devDependencies": {
"jest": "29.3.0",
- "vite": "^4.5.2",
+ "vite": "^5.0.12",
"vite-tsconfig-paths": "^3.6.0"
}
}
diff --git a/client/packages/lowcoder-comps/src/comps/calendarComp/calendarConstants.tsx b/client/packages/lowcoder-comps/src/comps/calendarComp/calendarConstants.tsx
index 93c07c462..bbc02cafd 100644
--- a/client/packages/lowcoder-comps/src/comps/calendarComp/calendarConstants.tsx
+++ b/client/packages/lowcoder-comps/src/comps/calendarComp/calendarConstants.tsx
@@ -205,9 +205,9 @@ export const Wrapper = styled.div<{
flex-direction: inherit;
}
.fc-day-today .fc-daygrid-day-number {
- background-color: ${(props) => props.$theme.primary};
+ background-color: ${(props) => props.$theme?.primary ? props.$theme.primary : props.$style.background};
color: ${(props) =>
- contrastText(props.$theme.primary || "", props.$theme.textDark, props.$theme.textLight)};
+ contrastText(props.$theme?.primary || "", props.$theme?.textDark || "#000000", props.$theme?.textLight || "#ffffff")};
}
.fc-daygrid-day-events {
padding: 1px 0 5px 0;
@@ -585,10 +585,10 @@ export const Wrapper = styled.div<{
}
.fc-day-today.fc-col-header-cell {
background-color: ${(props) =>
- isDarkColor(props.$style.background) ? "#ffffff19" : toHex(props.$theme.primary!) + "19"};
+ isDarkColor(props.$style.background) ? "#ffffff19" : toHex(props.$theme?.primary!) + "19"};
a {
color: ${(props) =>
- !isDarkColor(props.$style.background) && darkenColor(props.$theme.primary!, 0.1)};
+ !isDarkColor(props.$style.background) && darkenColor(props.$theme?.primary!, 0.1)};
}
}
.fc-col-header-cell-cushion {
diff --git a/client/packages/lowcoder-design/src/components/edit.tsx b/client/packages/lowcoder-design/src/components/edit.tsx
index c093fa6a2..0a17bfe8a 100644
--- a/client/packages/lowcoder-design/src/components/edit.tsx
+++ b/client/packages/lowcoder-design/src/components/edit.tsx
@@ -68,7 +68,7 @@ const TextInput = styled(Input)`
border: none;
padding: 0 8px 0 4px;
padding-left: ${(props) => (props.$hasPrefix ? "28px" : "4px")};
- color: #ffffff;
+ color: #444444;
line-height: 28px;
font-size: 14px;
diff --git a/client/packages/lowcoder/src/comps/comps/timelineComp/antIcon.tsx b/client/packages/lowcoder-design/src/icons/antIcon.tsx
similarity index 98%
rename from client/packages/lowcoder/src/comps/comps/timelineComp/antIcon.tsx
rename to client/packages/lowcoder-design/src/icons/antIcon.tsx
index 7879ff920..34cd128f2 100644
--- a/client/packages/lowcoder/src/comps/comps/timelineComp/antIcon.tsx
+++ b/client/packages/lowcoder-design/src/icons/antIcon.tsx
@@ -1581,3 +1581,24 @@ export const ANTDICON = {
zoominoutlined: ,
zoomoutoutlined: ,
};
+
+
+// Function to dynamically import icons
+export const loadAntDIcon = async (iconName: string) => {
+ if (!iconName) return null;
+
+ try {
+ const module = await import(`@ant-design/icons`);
+ const IconComponent = (module as any)[iconName];
+ if (IconComponent) {
+ // Return the icon component if found
+ return ;
+ } else {
+ console.error(`Icon ${iconName} not found in @ant-design/icons`);
+ return null;
+ }
+ } catch (error) {
+ console.error(`Error loading icon ${iconName}:`, error);
+ return null;
+ }
+};
\ No newline at end of file
diff --git a/client/packages/lowcoder-design/src/icons/icon-application-home.svg b/client/packages/lowcoder-design/src/icons/icon-application-home.svg
index 8435068e1..e56d475c9 100644
--- a/client/packages/lowcoder-design/src/icons/icon-application-home.svg
+++ b/client/packages/lowcoder-design/src/icons/icon-application-home.svg
@@ -1,7 +1,7 @@
-
+
@@ -11,6 +11,6 @@
-
+
diff --git a/client/packages/lowcoder-design/src/icons/icon-application-marketplace-active.svg b/client/packages/lowcoder-design/src/icons/icon-application-marketplace-active.svg
new file mode 100644
index 000000000..6db0975e5
--- /dev/null
+++ b/client/packages/lowcoder-design/src/icons/icon-application-marketplace-active.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/packages/lowcoder-design/src/icons/icon-application-marketplace.svg b/client/packages/lowcoder-design/src/icons/icon-application-marketplace.svg
new file mode 100644
index 000000000..417513063
--- /dev/null
+++ b/client/packages/lowcoder-design/src/icons/icon-application-marketplace.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/packages/lowcoder-design/src/icons/index.ts b/client/packages/lowcoder-design/src/icons/index.ts
index 938cd1fc4..e9d141765 100644
--- a/client/packages/lowcoder-design/src/icons/index.ts
+++ b/client/packages/lowcoder-design/src/icons/index.ts
@@ -176,11 +176,13 @@ export { ReactComponent as HomeModuleIcon } from "./icon-application-module.svg"
export { ReactComponent as HomeQueryLibraryIcon } from "./icon-application-query-library.svg";
export { ReactComponent as HomeDataSourceIcon } from "./icon-application-datasource.svg";
export { ReactComponent as RecyclerIcon } from "./icon-application-recycler.svg";
+export { ReactComponent as MarketplaceIcon } from "./icon-application-marketplace.svg";
export { ReactComponent as HomeActiveIcon } from "./icon-application-home-active.svg";
export { ReactComponent as HomeModuleActiveIcon } from "./icon-application-module-active.svg";
export { ReactComponent as HomeQueryLibraryActiveIcon } from "./icon-application-query-library-active.svg";
export { ReactComponent as HomeDataSourceActiveIcon } from "./icon-application-datasource-active.svg";
export { ReactComponent as RecyclerActiveIcon } from "./icon-application-recycler-active.svg";
+export { ReactComponent as MarketplaceActiveIcon } from "./icon-application-marketplace-active.svg";
export { ReactComponent as FavoritesIcon } from "./icon-application-favorites.svg";
export { ReactComponent as HomeSettingIcon } from "./icon-application-setting.svg";
export { ReactComponent as FolderIcon } from "./icon-application-folder.svg";
diff --git a/client/packages/lowcoder-design/src/index.ts b/client/packages/lowcoder-design/src/index.ts
index a2a7ca495..92a05fb78 100644
--- a/client/packages/lowcoder-design/src/index.ts
+++ b/client/packages/lowcoder-design/src/index.ts
@@ -49,3 +49,5 @@ export * from "./components/toolTip";
export * from "./components/video";
export * from "./icons";
+
+export * from "./icons/antIcon";
diff --git a/client/packages/lowcoder/src/api/applicationApi.ts b/client/packages/lowcoder/src/api/applicationApi.ts
index 41ee23204..06659a441 100644
--- a/client/packages/lowcoder/src/api/applicationApi.ts
+++ b/client/packages/lowcoder/src/api/applicationApi.ts
@@ -78,6 +78,7 @@ class ApplicationApi extends Api {
static newURLPrefix = "/applications";
static fetchHomeDataURL = "/v1/applications/home";
static createApplicationURL = "/v1/applications";
+ static fetchAllMarketplaceAppsURL = "/v1/applications/marketplace-apps";
static deleteApplicationURL = (applicationId: string) => `/v1/applications/${applicationId}`;
static getAppPublishInfoURL = (applicationId: string) => `/v1/applications/${applicationId}/view`;
static getAppEditingInfoURL = (applicationId: string) => `/v1/applications/${applicationId}`;
@@ -92,6 +93,9 @@ class ApplicationApi extends Api {
`/v1/applications/${applicationId}/permissions/${permissionId}`;
static createFromTemplateURL = `/v1/applications/createFromTemplate`;
static publicToAllURL = (applicationId: string) => `/applications/${applicationId}/public-to-all`;
+ static publicToMarketplaceURL = (applicationId: string) => `/v1/applications/${applicationId}/public-to-marketplace`;
+ static getMarketplaceAppURL = (applicationId: string) => `/v1/applications/${applicationId}/view_marketplace`;
+
static fetchHomeData(request: HomeDataPayload): AxiosPromise {
return Api.get(ApplicationApi.fetchHomeDataURL, request);
@@ -167,7 +171,9 @@ class ApplicationApi extends Api {
const url =
type === "published"
? ApplicationApi.getAppPublishInfoURL(applicationId)
- : ApplicationApi.getAppEditingInfoURL(applicationId);
+ : type === "view_marketplace"
+ ? ApplicationApi.getMarketplaceAppURL(applicationId)
+ : ApplicationApi.getAppEditingInfoURL(applicationId);
return Api.get(url);
}
@@ -211,6 +217,20 @@ class ApplicationApi extends Api {
publicToAll: publicToAll,
});
}
+
+ static publicToMarketplace(appId: string, publicToMarketplace: boolean) {
+ return Api.put(ApplicationApi.publicToMarketplaceURL(appId), {
+ publicToMarketplace,
+ });
+ }
+
+ static fetchAllMarketplaceApps() {
+ return Api.get(ApplicationApi.fetchAllMarketplaceAppsURL);
+ }
+
+ static getMarketplaceApp(appId: string) {
+ return Api.get(ApplicationApi.getMarketplaceAppURL(appId));
+ }
}
export default ApplicationApi;
diff --git a/client/packages/lowcoder/src/api/orgApi.ts b/client/packages/lowcoder/src/api/orgApi.ts
index 31ed40e58..7c1396a39 100644
--- a/client/packages/lowcoder/src/api/orgApi.ts
+++ b/client/packages/lowcoder/src/api/orgApi.ts
@@ -29,6 +29,10 @@ export interface CreateOrgResponse extends ApiResponse {
data: { orgId: string };
}
+export interface OrgAPIUsageResponse extends ApiResponse {
+ data: number;
+}
+
export class OrgApi extends Api {
static createGroupURL = "/v1/groups";
static updateGroupURL = (groupId: string) => `/v1/groups/${groupId}/update`;
@@ -47,6 +51,7 @@ export class OrgApi extends Api {
static createOrgURL = "/v1/organizations";
static deleteOrgURL = (orgId: string) => `/v1/organizations/${orgId}`;
static updateOrgURL = (orgId: string) => `/v1/organizations/${orgId}/update`;
+ static fetchUsage = (orgId: string) => `/v1/organizations/${orgId}/api-usage`;
static createGroup(request: { name: string }): AxiosPromise> {
return Api.post(OrgApi.createGroupURL, request);
@@ -127,6 +132,10 @@ export class OrgApi extends Api {
static updateOrg(request: UpdateOrgPayload): AxiosPromise {
return Api.put(OrgApi.updateOrgURL(request.id), request);
}
+
+ static fetchAPIUsage(orgId: string, lastMonthOnly?: boolean): AxiosPromise {
+ return Api.get(OrgApi.fetchUsage(orgId), lastMonthOnly);
+ }
}
export default OrgApi;
diff --git a/client/packages/lowcoder/src/app.tsx b/client/packages/lowcoder/src/app.tsx
index 0e25e3a52..8b3a944f7 100644
--- a/client/packages/lowcoder/src/app.tsx
+++ b/client/packages/lowcoder/src/app.tsx
@@ -14,6 +14,7 @@ import {
IMPORT_APP_FROM_TEMPLATE_URL,
INVITE_LANDING_URL,
isAuthUnRequired,
+ MARKETPLACE_URL,
ORG_AUTH_LOGIN_URL,
ORG_AUTH_REGISTER_URL,
QUERY_LIBRARY_URL,
@@ -138,6 +139,7 @@ class AppIndex extends React.Component {
FOLDER_URL,
TRASH_URL,
SETTING,
+ MARKETPLACE_URL,
]}
// component={ApplicationListPage}
component={ApplicationHome}
diff --git a/client/packages/lowcoder/src/assets/images/marketplaceHeaderImage.jpg b/client/packages/lowcoder/src/assets/images/marketplaceHeaderImage.jpg
new file mode 100644
index 000000000..a4eeb5714
Binary files /dev/null and b/client/packages/lowcoder/src/assets/images/marketplaceHeaderImage.jpg differ
diff --git a/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx b/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx
index b86282d80..499ceae37 100644
--- a/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx
+++ b/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx
@@ -29,6 +29,7 @@ import { StyledLoading } from "./commonComponents";
import { PermissionRole } from "./Permission";
import { SHARE_TITLE } from "../../constants/apiConstants";
import { messageInstance } from "lowcoder-design";
+import { Divider } from "antd";
export const AppPermissionDialog = (props: {
applicationId: string;
@@ -197,12 +198,17 @@ function AppShareView(props: {
}) {
const { applicationId, permissionInfo, isModule } = props;
const [isPublic, setPublic] = useState(permissionInfo.publicToAll);
+ const [isPublicToMarketplace, setPublicToMarketplace] = useState(permissionInfo.publicToMarketplace);
const dispatch = useDispatch();
useEffect(() => {
setPublic(permissionInfo.publicToAll);
}, [permissionInfo.publicToAll]);
+ useEffect(() => {
+ setPublicToMarketplace(permissionInfo.publicToMarketplace);
+ }, [permissionInfo.publicToMarketplace]);
return (
+
+ {isPublic &&
+
+ {
+ setPublicToMarketplace(checked);
+ ApplicationApi.publicToMarketplace(applicationId, checked)
+ .then((resp) => {
+ validateResponse(resp);
+ dispatch(updateAppPermissionInfo({ publicToMarketplace: checked }));
+ })
+ .catch((e) => {
+ messageInstance.error(e.message);
+ });
+ } }
+ label={isModule ? trans("home.moduleMarketplaceMessage") : trans("home.appMarketplaceMessage")} />
+ }
+ { isPublicToMarketplace && <>
+ {trans("home.marketplaceGoodPublishing")}
+
>}
+
{isPublic &&
}
);
diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/segmentedControl.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/segmentedControl.tsx
index 6c82fd62b..156c83799 100644
--- a/client/packages/lowcoder/src/comps/comps/selectInputComp/segmentedControl.tsx
+++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/segmentedControl.tsx
@@ -79,7 +79,6 @@ const SegmentedControlBasicComp = (function () {
return new UICompBuilder(SegmentChildrenMap, (props) => {
const [
validateState,
- handleValidate,
handleChange,
] = useSelectInputValidate(props);
return props.label({
diff --git a/client/packages/lowcoder/src/comps/comps/selectInputComp/selectInputConstants.tsx b/client/packages/lowcoder/src/comps/comps/selectInputComp/selectInputConstants.tsx
index 7c4fdc126..c69c35605 100644
--- a/client/packages/lowcoder/src/comps/comps/selectInputComp/selectInputConstants.tsx
+++ b/client/packages/lowcoder/src/comps/comps/selectInputComp/selectInputConstants.tsx
@@ -91,7 +91,7 @@ export const useSelectInputValidate = (props: ValidationParams) => {
return [
validateState,
- handleValidate,
+ // handleValidate,
handleChange,
] as const;
};
diff --git a/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx b/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx
index 729e8f6b9..d19586c6b 100644
--- a/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx
+++ b/client/packages/lowcoder/src/comps/comps/tableComp/tableCompView.tsx
@@ -517,7 +517,7 @@ function TableCellView(props: {
columnTitle: title,
});
const cellColor = cellColorFn({
- currentCell: record[title.toLowerCase()],
+ currentCell: record[title],
});
const style = {
diff --git a/client/packages/lowcoder/src/comps/comps/timelineComp/timelineComp.tsx b/client/packages/lowcoder/src/comps/comps/timelineComp/timelineComp.tsx
index 78a2787af..7433cc64d 100644
--- a/client/packages/lowcoder/src/comps/comps/timelineComp/timelineComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/timelineComp/timelineComp.tsx
@@ -1,26 +1,19 @@
-import React, { useEffect, useState } from "react";
+import React, { useEffect, useState, useContext } from "react";
import { default as Button } from "antd/es/button";
-// 渲染组件到编辑器
import {
changeChildAction,
DispatchType,
CompAction,
RecordConstructorToView,
} from "lowcoder-core";
-// 文字国际化转换api
import { trans } from "i18n";
-// 右侧属性栏总框架
import { UICompBuilder, withDefault } from "../../generators";
-// 右侧属性子框架
import { Section, sectionNames } from "lowcoder-design";
-// 指示组件是否隐藏的开关
import { hiddenPropertyView } from "comps/utils/propertyUtils";
-// 右侧属性开关
-
import { BoolControl } from "comps/controls/boolControl";
-import { stringExposingStateControl } from "comps/controls/codeStateControl"; //文本并暴露值
+import { stringExposingStateControl } from "comps/controls/codeStateControl";
import { dropdownControl } from "comps/controls/dropdownControl";
-import { styleControl } from "comps/controls/styleControl"; //样式输入框
+import { styleControl } from "comps/controls/styleControl";
import { alignControl } from "comps/controls/alignControl";
import { AutoHeightControl } from "comps/controls/autoHeightControl";
import { jsonValueExposingStateControl } from "comps/controls/codeStateControl";
@@ -34,35 +27,25 @@ import {
NumberControl,
StringControl,
} from "comps/controls/codeControl";
-// 事件控制
import {
clickEvent,
eventHandlerControl,
} from "comps/controls/eventHandlerControl";
-
-// 引入样式
import {
TimeLineStyle,
heightCalculator,
widthCalculator,
marginCalculator,
} from "comps/controls/styleControlConstants";
-// 初始化暴露值
import { stateComp, valueComp } from "comps/generators/simpleGenerators";
-// 组件对外暴露属性的api
import {
NameConfig,
NameConfigHidden,
withExposingConfigs,
} from "comps/generators/withExposing";
-
import { timelineDate, timelineNode, TimelineDataTooltip } from "./timelineConstants";
import { convertTimeLineData } from "./timelineUtils";
import { default as Timeline } from "antd/es/timeline";
-
-import { ANTDICON } from "./antIcon"; // todo: select icons to not import all icons
-
-import { useContext } from "react";
import { EditorContext } from "comps/editorState";
const EventOptions = [
@@ -86,18 +69,44 @@ const childrenMap = {
clickedIndex: valueComp(0),
};
+// Utility function to dynamically load Ant Design icons
+const loadIcon = async (iconName: string) => {
+ if (!iconName) return null;
+ try {
+ const module = await import(`@ant-design/icons`);
+ const IconComponent = (module as any)[iconName];
+ return IconComponent ? : null;
+ } catch (error) {
+ console.error(`Error loading icon ${iconName}:`, error);
+ return null;
+ }
+};
+
const TimelineComp = (
props: RecordConstructorToView & {
dispatch: (action: CompAction) => void;
}
) => {
const { value, dispatch, style, mode, reverse, onEvent } = props;
+ const [icons, setIcons] = useState([]);
+
+ useEffect(() => {
+ const loadIcons = async () => {
+ const iconComponents = await Promise.all(
+ value.map((node) =>
+ node.dot ? loadIcon(node.dot) : Promise.resolve(null)
+ )
+ );
+ setIcons(iconComponents);
+ };
+
+ loadIcons();
+ }, [value]);
+
const timelineItems = value.map((value: timelineNode, index: number) => ({
key: index,
color: value?.color,
- dot: value?.dot && ANTDICON.hasOwnProperty(value?.dot.toLowerCase())
- ? ANTDICON[value?.dot.toLowerCase() as keyof typeof ANTDICON]
- : "",
+ dot: icons[index] || "",
label: (
{value?.label}
@@ -125,10 +134,8 @@ const TimelineComp = (
>
)
- }
- ))
+ }));
- // TODO:parse px string
return (
= {
[AppTypeEnum.MobileTabLayout]: "mobileTabLayout",
};
-export type ApplicationDSLType = "editing" | "published";
+export type ApplicationDSLType = "editing" | "published" | "view_marketplace";
export type ApplicationRoleType = "viewer" | "editor" | "owner";
export type ApplicationPermissionType = "USER" | "GROUP" | "ORG_ADMIN";
@@ -36,6 +36,7 @@ export interface ApplicationMeta {
containerSize?: { height: number; width: number };
createBy: string;
createAt: number;
+ creatorEmail?: string;
orgId: string;
role: ApplicationRoleType;
extra: ApplicationExtra;
@@ -80,9 +81,10 @@ export interface AppPermissionInfo {
permissions: PermissionItem[];
invitationCodes: AppInviteInfo[];
publicToAll: boolean;
+ publicToMarketplace: boolean;
}
-export type AppViewMode = "edit" | "preview" | "view";
+export type AppViewMode = "edit" | "preview" | "view" | "view_marketplace";
export type AppPathParams = {
viewMode: AppViewMode;
diff --git a/client/packages/lowcoder/src/constants/reduxActionConstants.ts b/client/packages/lowcoder/src/constants/reduxActionConstants.ts
index 7b2b28442..ae7ebf129 100644
--- a/client/packages/lowcoder/src/constants/reduxActionConstants.ts
+++ b/client/packages/lowcoder/src/constants/reduxActionConstants.ts
@@ -100,6 +100,8 @@ export const ReduxActionTypes = {
UPDATE_USER_PROFILE_SUCCESS: "UPDATE_USER_PROFILE_SUCCESS",
UPLOAD_USER_HEAD_SUCCESS: "UPLOAD_USER_HEAD_SUCCESS", // update avatar
MARK_USER_STATUS: "MARK_USER_STATUS",
+ FETCH_ORG_API_USAGE: "FETCH_ORG_API_USAGE",
+ FETCH_ORG_API_USAGE_SUCCESS: "FETCH_ORG_API_USAGE_SUCCESS",
/* home data */
FETCH_HOME_DATA: "FETCH_HOME_DATA",
@@ -135,6 +137,8 @@ export const ReduxActionTypes = {
FETCH_ALL_APPLICATIONS_SUCCESS: "FETCH_ALL_APPLICATIONS_SUCCESS",
FETCH_ALL_MODULES_INIT: "FETCH_ALL_MODULES_INIT",
FETCH_ALL_MODULES_SUCCESS: "FETCH_ALL_MODULES_SUCCESS",
+ FETCH_ALL_MARKETPLACE_APPS: "FETCH_ALL_MARKETPLACE_APPS",
+ FETCH_ALL_MARKETPLACE_APPS_SUCCESS: "FETCH_ALL_MARKETPLACE_APPS_SUCCESS",
/* user profile */
SET_USER_PROFILE_SETTING_MODAL_VISIBLE: "SET_USER_PROFILE_SETTING_MODAL_VISIBLE",
diff --git a/client/packages/lowcoder/src/constants/routesURL.ts b/client/packages/lowcoder/src/constants/routesURL.ts
index 8b7abb5ee..1c21036ab 100644
--- a/client/packages/lowcoder/src/constants/routesURL.ts
+++ b/client/packages/lowcoder/src/constants/routesURL.ts
@@ -21,6 +21,7 @@ export const ORGANIZATION_SETTING_DETAIL = `${ORGANIZATION_SETTING}/:orgId`;
export const ALL_APPLICATIONS_URL = "/apps";
export const MODULE_APPLICATIONS_URL = "/apps/module";
+export const MARKETPLACE_URL = `/marketplace`;
export const DATASOURCE_URL = `/datasource`;
export const DATASOURCE_CREATE_URL = `${DATASOURCE_URL}/new/:datasourceType`;
export const DATASOURCE_EDIT_URL = `${DATASOURCE_URL}/:datasourceId`;
diff --git a/client/packages/lowcoder/src/i18n/locales/de.ts b/client/packages/lowcoder/src/i18n/locales/de.ts
index b30fead70..671abf94c 100644
--- a/client/packages/lowcoder/src/i18n/locales/de.ts
+++ b/client/packages/lowcoder/src/i18n/locales/de.ts
@@ -2053,6 +2053,7 @@ export const de = {
"modules": "Module",
"module": "Modul",
"trash": "Papierkorb",
+ "marketplace": "Marktplatz",
"queryLibrary": "Abfragebibliothek",
"datasource": "Datenquellen",
"selectDatasourceType": "Datenquellentyp auswählen",
@@ -2110,8 +2111,12 @@ export const de = {
"allPermissions": "Besitzer",
"shareLink": "Link teilen: ",
"copyLink": "Link kopieren",
- "appPublicMessage": "Mach die App öffentlich. Jeder kann sie sehen.",
- "modulePublicMessage": "Mach das Modul öffentlich. Jeder kann es sehen.",
+ "appPublicMessage": "App veröffentlichen. Auf dem Marktplatz für jeden zu sehen.",
+ "modulePublicMessage": "Module veröffentlichen. Auf dem Marktplatz für jeden zu sehen.",
+ "appMarketplaceMessage": "Veröffentlichen Sie Ihre App auf dem Lowcoder-Marktplatz. Jeder kann sie dort sehen und kopieren.",
+ "moduleMarketplaceMessage": "Veröffentlichen Sie Ihr Modul auf dem Lowcoder-Marktplatz. Jeder kann es dort sehen und kopieren.",
+ "marketplaceGoodPublishing": "Bitte stellen Sie sicher, dass Ihre App gut benannt und einfach zu bedienen ist. Entfernen Sie alle sensiblen Informationen vor der Veröffentlichung. Entfernen Sie außerdem lokale Datenquellen und ersetzen Sie sie durch statische, integrierte temporäre Daten.",
+ "noMarketplaceApps": "Noch sind keine Anwendungen auf dem Marktplatz.",
"memberPermissionList": "Mitgliedschaftsberechtigungen: ",
"orgName": "{orgName} admins",
"addMember": "Mitglieder hinzufügen",
diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts
index 287603466..a40d69d2e 100644
--- a/client/packages/lowcoder/src/i18n/locales/en.ts
+++ b/client/packages/lowcoder/src/i18n/locales/en.ts
@@ -2238,12 +2238,13 @@ export const en = {
"history": "History"
},
"home": {
- "allApplications": "All Apps",
- "allModules": "All Modules",
+ "allApplications": "Your Apps",
+ "allModules": "Your Modules",
"allFolders": "All Folders",
"modules": "Modules",
"module": "Module",
"trash": "Trash",
+ "marketplace": "Marketplace",
"queryLibrary": "Query Library",
"datasource": "Data Sources",
"selectDatasourceType": "Select Data Source Type",
@@ -2303,6 +2304,10 @@ export const en = {
"copyLink": "Copy link",
"appPublicMessage": "Make the app public. Anyone can view.",
"modulePublicMessage": "Make the module public. Anyone can view.",
+ "appMarketplaceMessage": "Publish your App on Lowcoder Marketplace. Anyone can view and copy it from there.",
+ "moduleMarketplaceMessage": "Publish your Module on Lowcoder Marketplace. Anyone can view and copy it from there.",
+ "marketplaceGoodPublishing": "Please make sure your app is well-named and easy to use. Remove any sensitive information before publishing. Also, remove local datasources and replace by static built-in temporary data.",
+ "noMarketplaceApps": "No apps yet in the marketplace",
"memberPermissionList": "Member permissions: ",
"orgName": "{orgName} admins",
"addMember": "Add members",
diff --git a/client/packages/lowcoder/src/i18n/locales/zh.ts b/client/packages/lowcoder/src/i18n/locales/zh.ts
index e0634a234..b90d3a8f1 100644
--- a/client/packages/lowcoder/src/i18n/locales/zh.ts
+++ b/client/packages/lowcoder/src/i18n/locales/zh.ts
@@ -2123,6 +2123,7 @@ home: {
modules: "模块",
module: "模块",
trash: "回收站",
+ marketplace: "市场",
queryLibrary: "查询管理",
datasource: "数据源",
selectDatasourceType: "选择数据源类型",
@@ -2182,6 +2183,10 @@ home: {
copyLink: "复制链接",
appPublicMessage: "将应用设为公开,任何人都可以查看.",
modulePublicMessage: "将模块设为公开,任何人都可以查看.",
+ "appMarketplaceMessage": "发布您的应用程序到Lowcoder市场.任何人都可以在那里查看和复制它.",
+ "moduleMarketplaceMessage": "发布您的模块到Lowcoder市场.任何人都可以在那里查看和复制它.",
+ "marketplaceGoodPublishing": "请确保您的应用程序命名准确、易于使用。发布前请删除任何敏感信息。此外,移除本地数据源,代之以静态内置临时数据",
+ "noMarketplaceApps": "市场上还没有应用程序",
memberPermissionList: "成员权限:",
orgName: "{orgName}管理员",
addMember: "添加成员",
diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/HomeLayout.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/HomeLayout.tsx
index fde596953..9ea75b051 100644
--- a/client/packages/lowcoder/src/pages/ApplicationV2/HomeLayout.tsx
+++ b/client/packages/lowcoder/src/pages/ApplicationV2/HomeLayout.tsx
@@ -32,6 +32,7 @@ import { CreateDropdown } from "./CreateDropdown";
import { trans } from "../../i18n";
import { isFetchingFolderElements } from "../../redux/selectors/folderSelector";
import { checkIsMobile } from "util/commonUtils";
+import MarketplaceHeaderImage from "assets/images/marketplaceHeaderImage.jpg";
const Wrapper = styled.div`
display: flex;
@@ -65,6 +66,23 @@ const OperationWrapper = styled.div`
}
`;
+const MarketplaceHeader = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ height: 200px;
+ padding: 0 36px;
+ margin: 8px 0 20px 0;
+ @media screen and (max-width: 500px) {
+ padding: 0 24px;
+ }
+ > img {
+ width: 100%;
+ object-fit: cover;
+ }
+`;
+
const ContentWrapper = styled.div`
position: relative;
`;
@@ -238,11 +256,12 @@ export interface HomeRes {
isEditable?: boolean;
isManageable: boolean;
isDeletable: boolean;
+ isMarketplace?: boolean;
}
export type HomeBreadcrumbType = { text: string; path: string };
-export type HomeLayoutMode = "view" | "trash" | "module" | "folder" | "folders";
+export type HomeLayoutMode = "view" | "trash" | "module" | "folder" | "folders" | "marketplace";
export interface HomeLayoutProps {
breadcrumb?: HomeBreadcrumbType[];
@@ -306,11 +325,12 @@ export function HomeLayout(props: HomeLayoutProps) {
id: e.applicationId,
name: e.name,
type: HomeResTypeEnum[HomeResTypeEnum[e.applicationType] as HomeResKey],
- creator: e.createBy,
+ creator: e?.creatorEmail ?? e.createBy,
lastModifyTime: e.lastModifyTime,
- isEditable: canEditApp(user, e),
- isManageable: canManageApp(user, e),
- isDeletable: canEditApp(user, e),
+ isEditable: mode !== 'marketplace' && canEditApp(user, e),
+ isManageable: mode !== 'marketplace' && canManageApp(user, e),
+ isDeletable: mode !== 'marketplace' && canEditApp(user, e),
+ isMarketplace: mode === 'marketplace',
}
);
@@ -362,6 +382,10 @@ export function HomeLayout(props: HomeLayoutProps) {
{showNewUserGuide(user) &&
}
{/*
*/}
+ {mode === "marketplace" && (
+
+ )}
+
{mode !== "folders" && mode !== "module" && (
node}
suffixIcon={ }
@@ -387,13 +412,15 @@ export function HomeLayout(props: HomeLayoutProps) {
onChange={(e) => setSearchValue(e.target.value)}
style={{ width: "192px", height: "32px", margin: "0" }}
/>
- {mode !== "trash" && user.orgDev && (
+ {mode !== "trash" && mode !== "marketplace" && user.orgDev && (
)}
+
+
{isFetching && resList.length === 0 ? (
) : (
@@ -421,11 +448,13 @@ export function HomeLayout(props: HomeLayoutProps) {
{mode === "trash"
? trans("home.trashEmpty")
+ : mode === "marketplace"
+ ? trans("home.noMarketplaceApps")
: user.orgDev
? trans("home.projectEmptyCanAdd")
: trans("home.projectEmpty")}
- {mode !== "trash" && user.orgDev && }
+ {mode !== "trash" && mode !== "marketplace" && user.orgDev && }
)}
>
diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/HomeResCard.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/HomeResCard.tsx
index 26c97eb30..ceef8b54a 100644
--- a/client/packages/lowcoder/src/pages/ApplicationV2/HomeResCard.tsx
+++ b/client/packages/lowcoder/src/pages/ApplicationV2/HomeResCard.tsx
@@ -11,6 +11,7 @@ import {
handleAppEditClick,
handleAppViewClick,
handleFolderViewClick,
+ handleMarketplaceAppViewClick,
HomeResInfo,
} from "../../util/homeResUtils";
import { HomeResOptions } from "./HomeResOptions";
@@ -177,6 +178,10 @@ export function HomeResCard(props: { res: HomeRes; onMove: (res: HomeRes) => voi
history.push(APPLICATION_VIEW_URL(res.id, "view"));
return;
}
+ if(res.isMarketplace) {
+ handleMarketplaceAppViewClick(res.id);
+ return;
+ }
res.isEditable ? handleAppEditClick(e, res.id) : handleAppViewClick(res.id);
}
}}
@@ -211,6 +216,8 @@ export function HomeResCard(props: { res: HomeRes; onMove: (res: HomeRes) => voi
onClick={() =>
res.type === HomeResTypeEnum.Folder
? handleFolderViewClick(res.id)
+ : res.isMarketplace
+ ? handleMarketplaceAppViewClick(res.id)
: handleAppViewClick(res.id)
}
>
diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/HomeTableView.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/HomeTableView.tsx
index 4a76939ee..aa767250c 100644
--- a/client/packages/lowcoder/src/pages/ApplicationV2/HomeTableView.tsx
+++ b/client/packages/lowcoder/src/pages/ApplicationV2/HomeTableView.tsx
@@ -7,6 +7,7 @@ import {
handleAppEditClick,
handleAppViewClick,
handleFolderViewClick,
+ handleMarketplaceAppViewClick,
HomeResInfo,
} from "../../util/homeResUtils";
import { HomeResTypeEnum } from "../../types/homeRes";
@@ -75,6 +76,8 @@ export const HomeTableView = (props: { resources: HomeRes[] }) => {
}
if (item.type === HomeResTypeEnum.Folder) {
handleFolderViewClick(item.id);
+ } else if(item.isMarketplace) {
+ handleMarketplaceAppViewClick(item.id);
} else {
item.isEditable ? handleAppEditClick(e, item.id) : handleAppViewClick(item.id);
}
@@ -209,6 +212,8 @@ export const HomeTableView = (props: { resources: HomeRes[] }) => {
e.stopPropagation();
return item.type === HomeResTypeEnum.Folder
? handleFolderViewClick(item.id)
+ : item.isMarketplace
+ ? handleMarketplaceAppViewClick(item.id)
: handleAppViewClick(item.id);
}}
style={{ marginRight: "52px" }}
diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/MarketplaceView.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/MarketplaceView.tsx
new file mode 100644
index 000000000..d518250d1
--- /dev/null
+++ b/client/packages/lowcoder/src/pages/ApplicationV2/MarketplaceView.tsx
@@ -0,0 +1,35 @@
+import { useEffect, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import { HomeLayout } from "./HomeLayout";
+import { MARKETPLACE_URL } from "constants/routesURL";
+import { marketplaceSelector } from "redux/selectors/applicationSelector";
+import { fetchAllMarketplaceApps } from "redux/reduxActions/applicationActions";
+import { trans } from "../../i18n";
+
+export function MarketplaceView() {
+ const [haveFetchedApps, setHaveFetchApps] = useState(false);
+
+ const dispatch = useDispatch();
+ const marketplaceApps = useSelector(marketplaceSelector);
+
+ useEffect(() => {
+ if (!marketplaceApps.length && !haveFetchedApps) {
+ dispatch(fetchAllMarketplaceApps());
+ setHaveFetchApps(true);
+ }
+ }, []);
+
+ useEffect(() => {
+ if (marketplaceApps.length) {
+ setHaveFetchApps(true);
+ }
+ }, [marketplaceApps])
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx
index 7e24d5eee..2baac3259 100644
--- a/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx
+++ b/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx
@@ -4,6 +4,7 @@ import {
FOLDER_URL,
FOLDER_URL_PREFIX,
FOLDERS_URL,
+ MARKETPLACE_URL,
MODULE_APPLICATIONS_URL,
QUERY_LIBRARY_URL,
SETTING,
@@ -30,6 +31,8 @@ import {
PointIcon,
RecyclerActiveIcon,
RecyclerIcon,
+ MarketplaceIcon,
+ MarketplaceActiveIcon,
} from "lowcoder-design";
import React, { useEffect, useState } from "react";
import { fetchAllApplications, fetchHomeData } from "redux/reduxActions/applicationActions";
@@ -44,6 +47,7 @@ import styled, { css } from "styled-components";
import history from "../../util/history";
import { FolderView } from "./FolderView";
import { TrashView } from "./TrashView";
+import { MarketplaceView } from "./MarketplaceView";
import { SideBarItemType } from "../../components/layout/SideBarSection";
import { RootFolderListView } from "./RootFolderListView";
import InviteDialog from "../common/inviteDialog";
@@ -341,7 +345,7 @@ export default function ApplicationHome() {
selected ? : ,
},
{
- text: {trans("home.modules")} ,
+ text: {trans("home.allModules")} ,
routePath: MODULE_APPLICATIONS_URL,
routeComp: ModuleView,
icon: ({ selected, ...otherProps }) =>
@@ -352,6 +356,19 @@ export default function ApplicationHome() {
),
visible: ({ user }) => user.orgDev,
},
+ {
+ text: {trans("home.marketplace")} ,
+ routePath: MARKETPLACE_URL,
+ routePathExact: false,
+ routeComp: MarketplaceView,
+ icon: ({ selected, ...otherProps }) =>
+ selected ? (
+
+ ) : (
+
+ ),
+ visible: ({ user }) => user.orgDev,
+ },
{
text: {trans("home.trash")} ,
routePath: TRASH_URL,
diff --git a/client/packages/lowcoder/src/pages/common/headerStartDropdown.tsx b/client/packages/lowcoder/src/pages/common/headerStartDropdown.tsx
index eefa27800..6fe44ec93 100644
--- a/client/packages/lowcoder/src/pages/common/headerStartDropdown.tsx
+++ b/client/packages/lowcoder/src/pages/common/headerStartDropdown.tsx
@@ -11,7 +11,7 @@ import {
} from "lowcoder-design";
import { trans, transToNode } from "i18n";
import { exportApplicationAsJSONFile } from "pages/ApplicationV2/components/AppImport";
-import { useContext, useState } from "react";
+import { useContext, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { currentApplication } from "redux/selectors/applicationSelector";
import { showAppSnapshotSelector } from "redux/selectors/appSnapshotSelector";
@@ -23,6 +23,8 @@ import { recycleApplication } from "redux/reduxActions/applicationActions";
import { CopyModal } from "./copyModal";
import { ExternalEditorContext } from "util/context/ExternalEditorContext";
import { messageInstance } from "lowcoder-design";
+import { getUser } from "redux/selectors/usersSelectors";
+import { canEditApp } from "util/permissionUtils";
const PackUpIconStyled = styled(PackUpIcon)`
transform: rotate(180deg);
@@ -68,6 +70,7 @@ export const TypeName = {
};
export function HeaderStartDropdown(props: { setEdit: () => void }) {
+ const user = useSelector(getUser);
const showAppSnapshot = useSelector(showAppSnapshotSelector);
const applicationId = useApplicationId();
const application = useSelector(currentApplication);
@@ -76,6 +79,37 @@ export function HeaderStartDropdown(props: { setEdit: () => void }) {
const { appType } = useContext(ExternalEditorContext);
const isModule = appType === AppTypeEnum.Module;
+ const isEditable = canEditApp(user, application);
+
+ const menuItems = useMemo(() => ([
+ {
+ key: "edit",
+ label: {trans("header.editName")} ,
+ visible: isEditable,
+ },
+ {
+ key: "export",
+ label: {trans("header.export")} ,
+ visible: true,
+ },
+ {
+ key: "duplicate",
+ label: (
+
+ {trans("header.duplicate", {
+ type: TypeName[application?.applicationType!]?.toLowerCase(),
+ })}
+
+ ),
+ visible: true,
+ },
+ {
+ key: "delete",
+ label: {trans("home.moveToTrash")} ,
+ visible: isEditable,
+ },
+ ]), [isEditable]);
+
return (
<>
void }) {
});
}
}}
- items={[
- {
- key: "edit",
- label: {trans("header.editName")} ,
- },
- {
- key: "export",
- label: {trans("header.export")} ,
- },
- {
- key: "duplicate",
- label: (
-
- {trans("header.duplicate", {
- type: TypeName[application?.applicationType!]?.toLowerCase(),
- })}
-
- ),
- },
- {
- key: "delete",
- label: {trans("home.moveToTrash")} ,
- },
- ]}
+ items={menuItems.filter(item => item.visible)}
/>
)}
>
{isModule && (
diff --git a/client/packages/lowcoder/src/pages/common/previewHeader.tsx b/client/packages/lowcoder/src/pages/common/previewHeader.tsx
index 507330cbf..85ae198d6 100644
--- a/client/packages/lowcoder/src/pages/common/previewHeader.tsx
+++ b/client/packages/lowcoder/src/pages/common/previewHeader.tsx
@@ -17,6 +17,9 @@ import { Logo } from "@lowcoder-ee/assets/images";
import { AppPermissionDialog } from "../../components/PermissionDialog/AppPermissionDialog";
import { useState } from "react";
import { getBrandingConfig } from "../../redux/selectors/configSelectors";
+import { HeaderStartDropdown } from "./headerStartDropdown";
+import { useParams } from "react-router";
+import { AppPathParams } from "constants/applicationConstants";
const HeaderFont = styled.div<{ $bgColor: string }>`
font-weight: 500;
@@ -125,21 +128,32 @@ export function HeaderProfile(props: { user: User }) {
}
export const PreviewHeader = () => {
+ const params = useParams();
const user = useSelector(getUser);
const application = useSelector(currentApplication);
const applicationId = useApplicationId();
const templateId = useSelector(getTemplateId);
const brandingConfig = useSelector(getBrandingConfig);
const [permissionDialogVisible, setPermissionDialogVisible] = useState(false);
+ const isViewMarketplaceMode = params.viewMode === 'view_marketplace';
const headerStart = (
<>
history.push(ALL_APPLICATIONS_URL)}>
-
- {application && application.name}
-
+ {isViewMarketplaceMode && (
+ {
+
+ }}
+ />
+ )}
+ {!isViewMarketplaceMode && (
+
+ {application && application.name}
+
+ )}
>
);
diff --git a/client/packages/lowcoder/src/pages/editor/AppEditor.tsx b/client/packages/lowcoder/src/pages/editor/AppEditor.tsx
index 05d5c4a08..c1d241a0a 100644
--- a/client/packages/lowcoder/src/pages/editor/AppEditor.tsx
+++ b/client/packages/lowcoder/src/pages/editor/AppEditor.tsx
@@ -33,7 +33,7 @@ export default function AppEditor() {
const isUserViewMode = useUserViewMode();
const params = useParams();
const applicationId = params.applicationId;
- const viewMode = params.viewMode === "view" ? "published" : "editing";
+ const viewMode = params.viewMode === "view" ? "published" : params.viewMode === "view_marketplace" ? "view_marketplace" : "editing";
const currentUser = useSelector(getUser);
const dispatch = useDispatch();
const fetchOrgGroupsFinished = useSelector(getFetchOrgGroupsFinished);
diff --git a/client/packages/lowcoder/src/pages/setting/index.tsx b/client/packages/lowcoder/src/pages/setting/index.tsx
index e77bb1450..9cfa2b235 100644
--- a/client/packages/lowcoder/src/pages/setting/index.tsx
+++ b/client/packages/lowcoder/src/pages/setting/index.tsx
@@ -8,6 +8,16 @@ import SettingHome from "./settingHome";
export function Setting() {
const user = useSelector(getUser);
+
+ /* fetch Org's API usage
+
+ const apiUsage = useSelector(getOrgApiUsage);
+ useEffect(() => {
+ dispatch(fetchAPIUsageAction(user.currentOrgId));
+ }, [user.currentOrgId])
+
+ */
+
if (!currentOrgAdminOrDev(user)) {
history.push(BASE_URL);
}
diff --git a/client/packages/lowcoder/src/redux/reducers/uiReducers/applicationReducer.ts b/client/packages/lowcoder/src/redux/reducers/uiReducers/applicationReducer.ts
index 7938543a4..dda424c1f 100644
--- a/client/packages/lowcoder/src/redux/reducers/uiReducers/applicationReducer.ts
+++ b/client/packages/lowcoder/src/redux/reducers/uiReducers/applicationReducer.ts
@@ -24,6 +24,7 @@ const initialState: ApplicationReduxState = {
applicationList: [],
modules: [],
recycleList: [],
+ marketplace: [],
loadingStatus: {
isFetchingHomeData: false,
fetchHomeDataFinished: false,
@@ -98,6 +99,13 @@ const usersReducer = createReducer(initialState, {
...state,
recycleList: action.payload,
}),
+ [ReduxActionTypes.FETCH_ALL_MARKETPLACE_APPS_SUCCESS]: (
+ state: ApplicationReduxState,
+ action: ReduxAction
+ ): ApplicationReduxState => ({
+ ...state,
+ marketplace: action.payload,
+ }),
[ReduxActionTypes.CREATE_APPLICATION_INIT]: (
state: ApplicationReduxState
): ApplicationReduxState => ({
@@ -336,6 +344,7 @@ export interface ApplicationReduxState {
applicationList: ApplicationMeta[];
modules: ApplicationMeta[];
recycleList: ApplicationMeta[];
+ marketplace: ApplicationMeta[];
appPermissionInfo?: AppPermissionInfo;
currentApplication?: ApplicationMeta;
templateId?: string;
diff --git a/client/packages/lowcoder/src/redux/reducers/uiReducers/orgReducer.ts b/client/packages/lowcoder/src/redux/reducers/uiReducers/orgReducer.ts
index 2d35b7e0c..f020cf99f 100644
--- a/client/packages/lowcoder/src/redux/reducers/uiReducers/orgReducer.ts
+++ b/client/packages/lowcoder/src/redux/reducers/uiReducers/orgReducer.ts
@@ -8,6 +8,7 @@ import { User } from "constants/userConstants";
import {
DeleteOrgUserPayload,
GroupUsersPayload,
+ OrgAPIUsagePayload,
OrgUsersPayload,
RemoveGroupUserPayload,
} from "redux/reduxActions/orgActions";
@@ -24,6 +25,7 @@ const initialState: OrgReduxState = {
groupUsersFetching: true,
fetchOrgGroupsFinished: false,
orgCreateStatus: "init",
+ apiUsage: 0,
};
const orgReducer = createImmerReducer(initialState, {
@@ -104,6 +106,13 @@ const orgReducer = createImmerReducer(initialState, {
...state,
orgCreateStatus: "error",
}),
+ [ReduxActionTypes.FETCH_ORG_API_USAGE_SUCCESS]: (
+ state: OrgReduxState,
+ action: ReduxAction
+ ): OrgReduxState => ({
+ ...state,
+ apiUsage: action.payload.apiUsage,
+ })
});
export interface OrgReduxState {
@@ -115,6 +124,7 @@ export interface OrgReduxState {
groupUsersFetching: boolean;
fetchOrgGroupsFinished: boolean;
orgCreateStatus: ApiRequestStatus;
+ apiUsage: number;
}
export default orgReducer;
diff --git a/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts b/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts
index 12697e352..7619798d6 100644
--- a/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts
+++ b/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts
@@ -32,6 +32,10 @@ export const fetchApplicationRecycleList = () => ({
type: ReduxActionTypes.FETCH_APPLICATION_RECYCLE_LIST_INIT,
});
+export const fetchAllMarketplaceApps = () => ({
+ type: ReduxActionTypes.FETCH_ALL_MARKETPLACE_APPS,
+});
+
export type CreateApplicationPayload = {
applicationName: string;
applicationType: AppTypeEnum;
diff --git a/client/packages/lowcoder/src/redux/reduxActions/orgActions.ts b/client/packages/lowcoder/src/redux/reduxActions/orgActions.ts
index d7326c1d7..9d2f3eb6a 100644
--- a/client/packages/lowcoder/src/redux/reduxActions/orgActions.ts
+++ b/client/packages/lowcoder/src/redux/reduxActions/orgActions.ts
@@ -151,3 +151,25 @@ export const updateOrgSuccess = (payload: UpdateOrgPayload) => {
payload: payload,
};
};
+
+export type OrgAPIUsagePayload = {
+ apiUsage: number,
+};
+
+export const fetchAPIUsageAction = (
+ orgId: string,
+ lastMonthOnly?: boolean,
+) => ({
+ type: ReduxActionTypes.FETCH_ORG_API_USAGE,
+ payload: {
+ orgId,
+ lastMonthOnly,
+ },
+});
+
+export const fetchAPIUsageSuccessAction = (apiUsage: number) => ({
+ type: ReduxActionTypes.FETCH_ORG_API_USAGE_SUCCESS,
+ payload: {
+ apiUsage,
+ },
+});
diff --git a/client/packages/lowcoder/src/redux/sagas/applicationSagas.ts b/client/packages/lowcoder/src/redux/sagas/applicationSagas.ts
index c49644182..6967c3c14 100644
--- a/client/packages/lowcoder/src/redux/sagas/applicationSagas.ts
+++ b/client/packages/lowcoder/src/redux/sagas/applicationSagas.ts
@@ -372,6 +372,24 @@ function* fetchApplicationRecycleListSaga() {
}
}
+function* fetchAllMarketplaceAppsSaga() {
+ try {
+ const response: AxiosResponse> = yield call(
+ ApplicationApi.fetchAllMarketplaceApps
+ );
+ const isValidResponse: boolean = validateResponse(response);
+ if (isValidResponse) {
+ yield put({
+ type: ReduxActionTypes.FETCH_ALL_MARKETPLACE_APPS_SUCCESS,
+ payload: response.data.data,
+ });
+ }
+ } catch (error: any) {
+ messageInstance.error(error.message);
+ log.debug("fetch marketplace apps error: ", error);
+ }
+}
+
export default function* applicationSagas() {
yield all([
takeLatest(ReduxActionTypes.FETCH_HOME_DATA, fetchHomeDataSaga),
@@ -393,5 +411,9 @@ export default function* applicationSagas() {
ReduxActionTypes.FETCH_APPLICATION_RECYCLE_LIST_INIT,
fetchApplicationRecycleListSaga
),
+ takeLatest(
+ ReduxActionTypes.FETCH_ALL_MARKETPLACE_APPS,
+ fetchAllMarketplaceAppsSaga,
+ ),
]);
}
diff --git a/client/packages/lowcoder/src/redux/sagas/orgSagas.ts b/client/packages/lowcoder/src/redux/sagas/orgSagas.ts
index 8835a2f3f..f1604241d 100644
--- a/client/packages/lowcoder/src/redux/sagas/orgSagas.ts
+++ b/client/packages/lowcoder/src/redux/sagas/orgSagas.ts
@@ -1,7 +1,7 @@
import { messageInstance } from "lowcoder-design";
import { ApiResponse, GenericApiResponse } from "api/apiResponses";
-import OrgApi, { CreateOrgResponse, GroupUsersResponse, OrgUsersResponse } from "api/orgApi";
+import OrgApi, { CreateOrgResponse, GroupUsersResponse, OrgAPIUsageResponse, OrgUsersResponse } from "api/orgApi";
import { AxiosResponse } from "axios";
import { OrgGroup } from "constants/orgConstants";
import {
@@ -280,6 +280,28 @@ export function* updateOrgSaga(action: ReduxAction) {
}
}
+export function* fetchAPIUsageSaga(action: ReduxAction<{
+ orgId: string,
+ lastMonthOnly?: boolean,
+}>) {
+ try {
+ const response: AxiosResponse = yield call(
+ OrgApi.fetchAPIUsage,
+ action.payload.orgId,
+ action.payload.lastMonthOnly,
+ );
+ const isValidResponse: boolean = validateResponse(response);
+ if (isValidResponse) {
+ yield put({
+ type: ReduxActionTypes.FETCH_ORG_API_USAGE_SUCCESS,
+ payload: response.data.data,
+ });
+ }
+ } catch (error) {
+ log.error(error);
+ }
+}
+
export default function* orgSagas() {
yield all([
takeLatest(ReduxActionTypes.UPDATE_GROUP_INFO, updateGroupSaga),
@@ -297,5 +319,6 @@ export default function* orgSagas() {
takeLatest(ReduxActionTypes.CREATE_ORG, createOrgSaga),
takeLatest(ReduxActionTypes.DELETE_ORG, deleteOrgSaga),
takeLatest(ReduxActionTypes.UPDATE_ORG, updateOrgSaga),
+ takeLatest(ReduxActionTypes.FETCH_ORG_API_USAGE, fetchAPIUsageSaga),
]);
}
diff --git a/client/packages/lowcoder/src/redux/selectors/applicationSelector.ts b/client/packages/lowcoder/src/redux/selectors/applicationSelector.ts
index 3279f65c6..2d888a9c9 100644
--- a/client/packages/lowcoder/src/redux/selectors/applicationSelector.ts
+++ b/client/packages/lowcoder/src/redux/selectors/applicationSelector.ts
@@ -8,6 +8,8 @@ export const modulesSelector = (state: AppState): ApplicationMeta[] => state.ui.
export const recycleListSelector = (state: AppState) => state.ui.application.recycleList;
+export const marketplaceSelector = (state: AppState) => state.ui.application.marketplace;
+
export const getHomeOrg = (state: AppState) => state.ui.application.homeOrg;
export const isFetchingHomeData = (state: AppState) =>
diff --git a/client/packages/lowcoder/src/redux/selectors/orgSelectors.ts b/client/packages/lowcoder/src/redux/selectors/orgSelectors.ts
index 281ff138b..8ea9aa3ec 100644
--- a/client/packages/lowcoder/src/redux/selectors/orgSelectors.ts
+++ b/client/packages/lowcoder/src/redux/selectors/orgSelectors.ts
@@ -15,3 +15,7 @@ export const getFetchOrgGroupsFinished = (state: AppState) => {
export const getOrgCreateStatus = (state: AppState) => {
return state.ui.org.orgCreateStatus;
};
+
+export const getOrgApiUsage = (state: AppState) => {
+ return state.ui.org.apiUsage;
+}
diff --git a/client/packages/lowcoder/src/util/homeResUtils.tsx b/client/packages/lowcoder/src/util/homeResUtils.tsx
index 2c37817d9..8f7e1dfe8 100644
--- a/client/packages/lowcoder/src/util/homeResUtils.tsx
+++ b/client/packages/lowcoder/src/util/homeResUtils.tsx
@@ -58,4 +58,6 @@ export const handleAppEditClick = (e: any, id: string): void => {
export const handleAppViewClick = (id: string) => window.open(APPLICATION_VIEW_URL(id, "view"));
+export const handleMarketplaceAppViewClick = (id: string) => window.open(APPLICATION_VIEW_URL(id, "view_marketplace"));
+
export const handleFolderViewClick = (id: string) => history.push(buildFolderUrl(id));
diff --git a/client/packages/lowcoder/src/util/hooks.ts b/client/packages/lowcoder/src/util/hooks.ts
index 67e397184..ca67a902f 100644
--- a/client/packages/lowcoder/src/util/hooks.ts
+++ b/client/packages/lowcoder/src/util/hooks.ts
@@ -25,7 +25,7 @@ export function isUserViewMode(params?: AppPathParams) {
return false;
}
const { viewMode } = params;
- return viewMode === "preview" || viewMode === "view";
+ return viewMode === "preview" || viewMode === "view" || viewMode === "view_marketplace";
}
/**
diff --git a/client/yarn.lock b/client/yarn.lock
index 548e5b874..95b2481e6 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -2058,6 +2058,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/aix-ppc64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/aix-ppc64@npm:0.19.12"
+ conditions: os=aix & cpu=ppc64
+ languageName: node
+ linkType: hard
+
"@esbuild/android-arm64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/android-arm64@npm:0.18.20"
@@ -2065,6 +2072,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/android-arm64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/android-arm64@npm:0.19.12"
+ conditions: os=android & cpu=arm64
+ languageName: node
+ linkType: hard
+
"@esbuild/android-arm@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/android-arm@npm:0.18.20"
@@ -2072,6 +2086,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/android-arm@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/android-arm@npm:0.19.12"
+ conditions: os=android & cpu=arm
+ languageName: node
+ linkType: hard
+
"@esbuild/android-x64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/android-x64@npm:0.18.20"
@@ -2079,6 +2100,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/android-x64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/android-x64@npm:0.19.12"
+ conditions: os=android & cpu=x64
+ languageName: node
+ linkType: hard
+
"@esbuild/darwin-arm64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/darwin-arm64@npm:0.18.20"
@@ -2086,6 +2114,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/darwin-arm64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/darwin-arm64@npm:0.19.12"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
"@esbuild/darwin-x64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/darwin-x64@npm:0.18.20"
@@ -2093,6 +2128,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/darwin-x64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/darwin-x64@npm:0.19.12"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
"@esbuild/freebsd-arm64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/freebsd-arm64@npm:0.18.20"
@@ -2100,6 +2142,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/freebsd-arm64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/freebsd-arm64@npm:0.19.12"
+ conditions: os=freebsd & cpu=arm64
+ languageName: node
+ linkType: hard
+
"@esbuild/freebsd-x64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/freebsd-x64@npm:0.18.20"
@@ -2107,6 +2156,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/freebsd-x64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/freebsd-x64@npm:0.19.12"
+ conditions: os=freebsd & cpu=x64
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-arm64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-arm64@npm:0.18.20"
@@ -2114,6 +2170,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-arm64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-arm64@npm:0.19.12"
+ conditions: os=linux & cpu=arm64
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-arm@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-arm@npm:0.18.20"
@@ -2121,6 +2184,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-arm@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-arm@npm:0.19.12"
+ conditions: os=linux & cpu=arm
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-ia32@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-ia32@npm:0.18.20"
@@ -2128,6 +2198,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-ia32@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-ia32@npm:0.19.12"
+ conditions: os=linux & cpu=ia32
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-loong64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-loong64@npm:0.18.20"
@@ -2135,6 +2212,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-loong64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-loong64@npm:0.19.12"
+ conditions: os=linux & cpu=loong64
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-mips64el@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-mips64el@npm:0.18.20"
@@ -2142,6 +2226,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-mips64el@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-mips64el@npm:0.19.12"
+ conditions: os=linux & cpu=mips64el
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-ppc64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-ppc64@npm:0.18.20"
@@ -2149,6 +2240,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-ppc64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-ppc64@npm:0.19.12"
+ conditions: os=linux & cpu=ppc64
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-riscv64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-riscv64@npm:0.18.20"
@@ -2156,6 +2254,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-riscv64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-riscv64@npm:0.19.12"
+ conditions: os=linux & cpu=riscv64
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-s390x@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-s390x@npm:0.18.20"
@@ -2163,6 +2268,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-s390x@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-s390x@npm:0.19.12"
+ conditions: os=linux & cpu=s390x
+ languageName: node
+ linkType: hard
+
"@esbuild/linux-x64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/linux-x64@npm:0.18.20"
@@ -2170,6 +2282,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/linux-x64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/linux-x64@npm:0.19.12"
+ conditions: os=linux & cpu=x64
+ languageName: node
+ linkType: hard
+
"@esbuild/netbsd-x64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/netbsd-x64@npm:0.18.20"
@@ -2177,6 +2296,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/netbsd-x64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/netbsd-x64@npm:0.19.12"
+ conditions: os=netbsd & cpu=x64
+ languageName: node
+ linkType: hard
+
"@esbuild/openbsd-x64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/openbsd-x64@npm:0.18.20"
@@ -2184,6 +2310,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/openbsd-x64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/openbsd-x64@npm:0.19.12"
+ conditions: os=openbsd & cpu=x64
+ languageName: node
+ linkType: hard
+
"@esbuild/sunos-x64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/sunos-x64@npm:0.18.20"
@@ -2191,6 +2324,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/sunos-x64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/sunos-x64@npm:0.19.12"
+ conditions: os=sunos & cpu=x64
+ languageName: node
+ linkType: hard
+
"@esbuild/win32-arm64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/win32-arm64@npm:0.18.20"
@@ -2198,6 +2338,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/win32-arm64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/win32-arm64@npm:0.19.12"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
"@esbuild/win32-ia32@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/win32-ia32@npm:0.18.20"
@@ -2205,6 +2352,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/win32-ia32@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/win32-ia32@npm:0.19.12"
+ conditions: os=win32 & cpu=ia32
+ languageName: node
+ linkType: hard
+
"@esbuild/win32-x64@npm:0.18.20":
version: 0.18.20
resolution: "@esbuild/win32-x64@npm:0.18.20"
@@ -2212,6 +2366,13 @@ __metadata:
languageName: node
linkType: hard
+"@esbuild/win32-x64@npm:0.19.12":
+ version: 0.19.12
+ resolution: "@esbuild/win32-x64@npm:0.19.12"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
"@eslint-community/eslint-utils@npm:^4.2.0":
version: 4.4.0
resolution: "@eslint-community/eslint-utils@npm:4.4.0"
@@ -3226,6 +3387,15 @@ __metadata:
languageName: node
linkType: hard
+"@remixicon/react@npm:^4.1.1":
+ version: 4.1.1
+ resolution: "@remixicon/react@npm:4.1.1"
+ peerDependencies:
+ react: ">=18.2.0"
+ checksum: 59b05b91ad9335ae531b2927ceb7c5930ec5afcdabb5d96461d3181e1f794ddbdd4a899e85eb66f1a5341f55132898b6f680f51643bd7bd7244a741f44beb0b7
+ languageName: node
+ linkType: hard
+
"@rjsf/antd@npm:^5.15.1":
version: 5.15.1
resolution: "@rjsf/antd@npm:5.15.1"
@@ -3523,6 +3693,97 @@ __metadata:
languageName: node
linkType: hard
+"@rollup/rollup-android-arm-eabi@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-android-arm-eabi@npm:4.12.0"
+ conditions: os=android & cpu=arm
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-android-arm64@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-android-arm64@npm:4.12.0"
+ conditions: os=android & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-darwin-arm64@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-darwin-arm64@npm:4.12.0"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-darwin-x64@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-darwin-x64@npm:4.12.0"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-arm-gnueabihf@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.12.0"
+ conditions: os=linux & cpu=arm
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-arm64-gnu@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.12.0"
+ conditions: os=linux & cpu=arm64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-arm64-musl@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-linux-arm64-musl@npm:4.12.0"
+ conditions: os=linux & cpu=arm64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-riscv64-gnu@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.12.0"
+ conditions: os=linux & cpu=riscv64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-x64-gnu@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-linux-x64-gnu@npm:4.12.0"
+ conditions: os=linux & cpu=x64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-linux-x64-musl@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-linux-x64-musl@npm:4.12.0"
+ conditions: os=linux & cpu=x64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-win32-arm64-msvc@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.12.0"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-win32-ia32-msvc@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.12.0"
+ conditions: os=win32 & cpu=ia32
+ languageName: node
+ linkType: hard
+
+"@rollup/rollup-win32-x64-msvc@npm:4.12.0":
+ version: 4.12.0
+ resolution: "@rollup/rollup-win32-x64-msvc@npm:4.12.0"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
"@rushstack/eslint-patch@npm:^1.1.0":
version: 1.6.1
resolution: "@rushstack/eslint-patch@npm:1.6.1"
@@ -3878,7 +4139,7 @@ __metadata:
languageName: node
linkType: hard
-"@types/estree@npm:*, @types/estree@npm:^1.0.0":
+"@types/estree@npm:*, @types/estree@npm:1.0.5, @types/estree@npm:^1.0.0":
version: 1.0.5
resolution: "@types/estree@npm:1.0.5"
checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a
@@ -7865,6 +8126,86 @@ __metadata:
languageName: node
linkType: hard
+"esbuild@npm:^0.19.3":
+ version: 0.19.12
+ resolution: "esbuild@npm:0.19.12"
+ dependencies:
+ "@esbuild/aix-ppc64": 0.19.12
+ "@esbuild/android-arm": 0.19.12
+ "@esbuild/android-arm64": 0.19.12
+ "@esbuild/android-x64": 0.19.12
+ "@esbuild/darwin-arm64": 0.19.12
+ "@esbuild/darwin-x64": 0.19.12
+ "@esbuild/freebsd-arm64": 0.19.12
+ "@esbuild/freebsd-x64": 0.19.12
+ "@esbuild/linux-arm": 0.19.12
+ "@esbuild/linux-arm64": 0.19.12
+ "@esbuild/linux-ia32": 0.19.12
+ "@esbuild/linux-loong64": 0.19.12
+ "@esbuild/linux-mips64el": 0.19.12
+ "@esbuild/linux-ppc64": 0.19.12
+ "@esbuild/linux-riscv64": 0.19.12
+ "@esbuild/linux-s390x": 0.19.12
+ "@esbuild/linux-x64": 0.19.12
+ "@esbuild/netbsd-x64": 0.19.12
+ "@esbuild/openbsd-x64": 0.19.12
+ "@esbuild/sunos-x64": 0.19.12
+ "@esbuild/win32-arm64": 0.19.12
+ "@esbuild/win32-ia32": 0.19.12
+ "@esbuild/win32-x64": 0.19.12
+ dependenciesMeta:
+ "@esbuild/aix-ppc64":
+ optional: true
+ "@esbuild/android-arm":
+ optional: true
+ "@esbuild/android-arm64":
+ optional: true
+ "@esbuild/android-x64":
+ optional: true
+ "@esbuild/darwin-arm64":
+ optional: true
+ "@esbuild/darwin-x64":
+ optional: true
+ "@esbuild/freebsd-arm64":
+ optional: true
+ "@esbuild/freebsd-x64":
+ optional: true
+ "@esbuild/linux-arm":
+ optional: true
+ "@esbuild/linux-arm64":
+ optional: true
+ "@esbuild/linux-ia32":
+ optional: true
+ "@esbuild/linux-loong64":
+ optional: true
+ "@esbuild/linux-mips64el":
+ optional: true
+ "@esbuild/linux-ppc64":
+ optional: true
+ "@esbuild/linux-riscv64":
+ optional: true
+ "@esbuild/linux-s390x":
+ optional: true
+ "@esbuild/linux-x64":
+ optional: true
+ "@esbuild/netbsd-x64":
+ optional: true
+ "@esbuild/openbsd-x64":
+ optional: true
+ "@esbuild/sunos-x64":
+ optional: true
+ "@esbuild/win32-arm64":
+ optional: true
+ "@esbuild/win32-ia32":
+ optional: true
+ "@esbuild/win32-x64":
+ optional: true
+ bin:
+ esbuild: bin/esbuild
+ checksum: 2936e29107b43e65a775b78b7bc66ddd7d76febd73840ac7e825fb22b65029422ff51038a08d19b05154f543584bd3afe7d1ef1c63900429475b17fbe61cb61f
+ languageName: node
+ linkType: hard
+
"escalade@npm:^3.1.1":
version: 3.1.1
resolution: "escalade@npm:3.1.1"
@@ -8794,7 +9135,7 @@ __metadata:
languageName: node
linkType: hard
-"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2":
+"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3":
version: 2.3.3
resolution: "fsevents@npm:2.3.3"
dependencies:
@@ -8804,7 +9145,7 @@ __metadata:
languageName: node
linkType: hard
-"fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin":
+"fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin, fsevents@patch:fsevents@~2.3.3#~builtin":
version: 2.3.3
resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1"
dependencies:
@@ -11505,7 +11846,7 @@ __metadata:
react: ^18.2.0
react-dom: ^18.2.0
typescript: 4.8.4
- vite: ^4.5.2
+ vite: ^5.0.12
vite-tsconfig-paths: ^3.6.0
languageName: unknown
linkType: soft
@@ -11589,6 +11930,7 @@ __metadata:
"@babel/preset-env": ^7.20.2
"@babel/preset-typescript": ^7.18.6
"@lottiefiles/react-lottie-player": ^3.5.3
+ "@remixicon/react": ^4.1.1
"@rollup/plugin-typescript": ^8.5.0
"@testing-library/jest-dom": ^5.16.5
"@testing-library/react": ^14.1.2
@@ -13563,6 +13905,17 @@ __metadata:
languageName: node
linkType: hard
+"postcss@npm:^8.4.35":
+ version: 8.4.35
+ resolution: "postcss@npm:8.4.35"
+ dependencies:
+ nanoid: ^3.3.7
+ picocolors: ^1.0.0
+ source-map-js: ^1.0.2
+ checksum: cf3c3124d3912a507603f6d9a49b3783f741075e9aa73eb592a6dd9194f9edab9d20a8875d16d137d4f779fe7b6fbd1f5727e39bfd1c3003724980ee4995e1da
+ languageName: node
+ linkType: hard
+
"preact@npm:~10.12.1":
version: 10.12.1
resolution: "preact@npm:10.12.1"
@@ -15650,6 +16003,60 @@ __metadata:
languageName: node
linkType: hard
+"rollup@npm:^4.2.0":
+ version: 4.12.0
+ resolution: "rollup@npm:4.12.0"
+ dependencies:
+ "@rollup/rollup-android-arm-eabi": 4.12.0
+ "@rollup/rollup-android-arm64": 4.12.0
+ "@rollup/rollup-darwin-arm64": 4.12.0
+ "@rollup/rollup-darwin-x64": 4.12.0
+ "@rollup/rollup-linux-arm-gnueabihf": 4.12.0
+ "@rollup/rollup-linux-arm64-gnu": 4.12.0
+ "@rollup/rollup-linux-arm64-musl": 4.12.0
+ "@rollup/rollup-linux-riscv64-gnu": 4.12.0
+ "@rollup/rollup-linux-x64-gnu": 4.12.0
+ "@rollup/rollup-linux-x64-musl": 4.12.0
+ "@rollup/rollup-win32-arm64-msvc": 4.12.0
+ "@rollup/rollup-win32-ia32-msvc": 4.12.0
+ "@rollup/rollup-win32-x64-msvc": 4.12.0
+ "@types/estree": 1.0.5
+ fsevents: ~2.3.2
+ dependenciesMeta:
+ "@rollup/rollup-android-arm-eabi":
+ optional: true
+ "@rollup/rollup-android-arm64":
+ optional: true
+ "@rollup/rollup-darwin-arm64":
+ optional: true
+ "@rollup/rollup-darwin-x64":
+ optional: true
+ "@rollup/rollup-linux-arm-gnueabihf":
+ optional: true
+ "@rollup/rollup-linux-arm64-gnu":
+ optional: true
+ "@rollup/rollup-linux-arm64-musl":
+ optional: true
+ "@rollup/rollup-linux-riscv64-gnu":
+ optional: true
+ "@rollup/rollup-linux-x64-gnu":
+ optional: true
+ "@rollup/rollup-linux-x64-musl":
+ optional: true
+ "@rollup/rollup-win32-arm64-msvc":
+ optional: true
+ "@rollup/rollup-win32-ia32-msvc":
+ optional: true
+ "@rollup/rollup-win32-x64-msvc":
+ optional: true
+ fsevents:
+ optional: true
+ bin:
+ rollup: dist/bin/rollup
+ checksum: a7398f072cf50804e9bdaf363792d0b7801800640434e7867c10b4e2e7be421ca2dc614ae0fc7392044eaf77d5c3a66f76a6fa2246bef97a7bc55926a8d60982
+ languageName: node
+ linkType: hard
+
"rtl-css-js@npm:^1.16.1":
version: 1.16.1
resolution: "rtl-css-js@npm:1.16.1"
@@ -17699,6 +18106,46 @@ __metadata:
languageName: node
linkType: hard
+"vite@npm:^5.0.12":
+ version: 5.1.4
+ resolution: "vite@npm:5.1.4"
+ dependencies:
+ esbuild: ^0.19.3
+ fsevents: ~2.3.3
+ postcss: ^8.4.35
+ rollup: ^4.2.0
+ peerDependencies:
+ "@types/node": ^18.0.0 || >=20.0.0
+ less: "*"
+ lightningcss: ^1.21.0
+ sass: "*"
+ stylus: "*"
+ sugarss: "*"
+ terser: ^5.4.0
+ dependenciesMeta:
+ fsevents:
+ optional: true
+ peerDependenciesMeta:
+ "@types/node":
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ bin:
+ vite: bin/vite.js
+ checksum: fb8b944c69fd738b412ad10471f01db01ed59b5d7fdf182b836b420b221a8bd5ada74d225a87aaa80cf8d2b693cc4a89ab7c291254a8b4e6faefd93843ebb9d3
+ languageName: node
+ linkType: hard
+
"vlq@npm:^0.2.2":
version: 0.2.3
resolution: "vlq@npm:0.2.3"