From cf6ab2e64c9fde24ae2008761d27f4fd122403c2 Mon Sep 17 00:00:00 2001 From: Falk Wolsky Date: Sat, 22 Mar 2025 18:50:48 +0100 Subject: [PATCH 01/13] Update netlify.toml - to enable the build --- client/netlify.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/netlify.toml b/client/netlify.toml index 1cb2010f3e..4d549283cf 100644 --- a/client/netlify.toml +++ b/client/netlify.toml @@ -2,3 +2,5 @@ from = "/*" to = "/" status = 200 +[[plugins]] + package = "@netlify/plugin-cache" From 3347226ad24f1cb488d1a9891f484154d8796aff Mon Sep 17 00:00:00 2001 From: Falk Wolsky Date: Sat, 22 Mar 2025 18:56:48 +0100 Subject: [PATCH 02/13] Update netlify.toml --- client/netlify.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/netlify.toml b/client/netlify.toml index 4d549283cf..1cb2010f3e 100644 --- a/client/netlify.toml +++ b/client/netlify.toml @@ -2,5 +2,3 @@ from = "/*" to = "/" status = 200 -[[plugins]] - package = "@netlify/plugin-cache" From 10d78a9ac321a18373647e6e2636a19c623d8f68 Mon Sep 17 00:00:00 2001 From: 1DontEx1st Date: Mon, 24 Mar 2025 21:42:30 -0400 Subject: [PATCH 03/13] Update transformers.md typo fix --- docs/business-logic-in-apps/write-javascript/transformers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/business-logic-in-apps/write-javascript/transformers.md b/docs/business-logic-in-apps/write-javascript/transformers.md index 0c195ed413..0c0c3cd747 100644 --- a/docs/business-logic-in-apps/write-javascript/transformers.md +++ b/docs/business-logic-in-apps/write-javascript/transformers.md @@ -6,7 +6,7 @@ Compared with inline code in `{{ }}`, transformer supports multi-line code block ## Quickstart -Click **+ New > Transfromer** in a query editor to create a transformer. +Click **+ New > Transformer** in a query editor to create a transformer. Then write your JS code in the transformer. You can click **Preview** to get the return value and access it by `transformerName.value` in your app. From a47b153ffcd8430130002a5150edad724e0465a3 Mon Sep 17 00:00:00 2001 From: 1DontEx1st Date: Mon, 31 Mar 2025 20:59:39 -0400 Subject: [PATCH 04/13] Update README.md fix typo --- .../use-third-party-libraries-in-apps/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md b/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md index 6e60d0488a..616e29621f 100644 --- a/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md +++ b/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md @@ -16,7 +16,7 @@ Lowcoder provides some JavaScript built-in libraries for use. Built-in Libraries can be used directly everywhere where you can use JavaScript. ``` -// loadash +// lodash return _.chunk(['a', 'b', 'c', 'd'], 2); // => [['a', 'b'], ['c', 'd']] From b7ff3f02032b2ad655d28c8d8bb9e85613506e6f Mon Sep 17 00:00:00 2001 From: 1DontEx1st Date: Mon, 31 Mar 2025 21:21:32 -0400 Subject: [PATCH 05/13] Add files via upload --- docs/.gitbook/assets/chrome_iLpFHdTIje.png | Bin 0 -> 45852 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/.gitbook/assets/chrome_iLpFHdTIje.png diff --git a/docs/.gitbook/assets/chrome_iLpFHdTIje.png b/docs/.gitbook/assets/chrome_iLpFHdTIje.png new file mode 100644 index 0000000000000000000000000000000000000000..8c2598f1cb337d00da091ad091c769658ed318ee GIT binary patch literal 45852 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 Date: Mon, 31 Mar 2025 21:23:25 -0400 Subject: [PATCH 06/13] Rename chrome_iLpFHdTIje.png to Individualization JavaScript Libraries --- ...e.png => Individualization JavaScript Libraries} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/.gitbook/assets/{chrome_iLpFHdTIje.png => Individualization JavaScript Libraries} (100%) diff --git a/docs/.gitbook/assets/chrome_iLpFHdTIje.png b/docs/.gitbook/assets/Individualization JavaScript Libraries similarity index 100% rename from docs/.gitbook/assets/chrome_iLpFHdTIje.png rename to docs/.gitbook/assets/Individualization JavaScript Libraries From d6dd1c702d1dd68fa7fe7b3cc2d7ff86d44c25ce Mon Sep 17 00:00:00 2001 From: 1DontEx1st Date: Mon, 31 Mar 2025 21:25:25 -0400 Subject: [PATCH 07/13] Update README.md change doc graphic for adding JS library locally to app --- .../use-third-party-libraries-in-apps/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md b/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md index 616e29621f..ae0759dc9c 100644 --- a/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md +++ b/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md @@ -107,11 +107,11 @@ You can check popular CDNs if they host your desired library as a minified packa ### Import / bind at the app level -Navigate to the settings page and then click the plus sign **+** under the **JavaScript library** tab. Paste the **library** link and click **Add New**. Lowcoder will now check, if the external library will be compatible and securely usable. +Navigate to the Individualization page and then click the plus sign **+** under the **JavaScript library** tab. Paste the **library** link and click **Add New**. Lowcoder will now check, if the external library will be compatible and securely usable. You can also click the download icon to quickly download any recommended JS library. -

Bind an external JS Library to an individual App

+

Bind an external JS Library to an individual App

Now, you can create a JS query and insert code. From 2234edabd1d8a1fd73fd90e91316c98e273ac515 Mon Sep 17 00:00:00 2001 From: Falk Wolsky Date: Sat, 19 Apr 2025 14:26:23 +0200 Subject: [PATCH 08/13] Update sonarcloud.yml We update the workflow file to increase memory heap size, as former runs did stop working because of the memory. --- .github/workflows/sonarcloud.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index f5cdd52809..4a2e939f81 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -30,3 +30,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_SCANNER_OPTS: "-Dsonar.javascript.node.maxspace=6144" From c174d6bbf6084d7f69fb58b7e344ac1e4f12d6e9 Mon Sep 17 00:00:00 2001 From: Falk Wolsky Date: Sat, 19 Apr 2025 14:41:40 +0200 Subject: [PATCH 09/13] Update sonarcloud.yml Adding more ram for the sonarcude server --- .github/workflows/sonarcloud.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 4a2e939f81..55e2fcebc3 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -30,4 +30,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_SCANNER_OPTS: "-Dsonar.javascript.node.maxspace=6144" + SONAR_SCANNER_OPTS: "-Dsonar.javascript.node.maxspace=8192 -Xmx512m" From d2a7bccdd672933c6bd4c8a56661cc95e1b59f38 Mon Sep 17 00:00:00 2001 From: Kamal Qureshi Date: Thu, 15 May 2025 14:05:55 +0500 Subject: [PATCH 10/13] App Publish and Versioning --- .../lowcoder-design/src/components/Switch.tsx | 40 +- .../lowcoder/src/api/applicationApi.ts | 123 +++-- .../PermissionDialog/AppPermissionDialog.tsx | 426 +++++++++++++----- .../PermissionDialog/PermissionDialog.tsx | 77 +--- .../PermissionDialog/PermissionList.tsx | 29 +- .../lowcoder/src/components/StepModal.tsx | 4 +- .../lowcoder/src/pages/common/header.tsx | 187 ++++---- .../src/pages/common/versionDataForm.tsx | 35 ++ .../pages/queryLibrary/QueryLibraryEditor.tsx | 161 +++---- .../redux/reduxActions/applicationActions.ts | 10 +- .../lowcoder/src/util/versionOptions.ts | 25 + translations/locales/en.js | 5 + 12 files changed, 715 insertions(+), 407 deletions(-) create mode 100644 client/packages/lowcoder/src/pages/common/versionDataForm.tsx create mode 100644 client/packages/lowcoder/src/util/versionOptions.ts diff --git a/client/packages/lowcoder-design/src/components/Switch.tsx b/client/packages/lowcoder-design/src/components/Switch.tsx index 576d304112..ae8a3e884d 100644 --- a/client/packages/lowcoder-design/src/components/Switch.tsx +++ b/client/packages/lowcoder-design/src/components/Switch.tsx @@ -52,6 +52,24 @@ const SwitchStyle: any = styled.input` border-radius: 20px; background-color: #ffffff; } + + &:disabled { + background-color: #e0e0e0; + opacity: 0.6; + cursor: not-allowed; + } + + &:disabled::before { + background-color: #cccccc; + } + + &:disabled:checked { + background-color: #a0a0a0; + } + + &:disabled:hover { + cursor: not-allowed; + } `; const SwitchDiv = styled.div<{ @@ -101,25 +119,31 @@ const JsIconGray = styled(jsIconGray)` ${IconCss} `; -interface SwitchProps extends Omit, "value" | "onChange"> { +interface SwitchProps + extends Omit, "value" | "onChange"> { value: boolean; onChange: (value: boolean) => void; + disabled?: boolean; } export const Switch = (props: SwitchProps) => { - const { value, onChange, ...inputChanges } = props; + const { value, onChange, disabled, ...inputChanges } = props; return ( props.onChange(!props.value)} + checked={value} + onClick={() => onChange(!value)} onChange={() => {}} + disabled={disabled} {...inputChanges} /> ); }; -export const SwitchJsIcon = (props: { checked: boolean; onChange: (value: boolean) => void }) => { +export const SwitchJsIcon = (props: { + checked: boolean; + onChange: (value: boolean) => void; +}) => { const toggleShow = () => { props.onChange(!props.checked); }; @@ -154,15 +178,17 @@ export const SwitchWrapper = (props: { export function TacoSwitch(props: { label: string; checked: boolean; - onChange: (checked: boolean) => void; + disabled?: boolean; + onChange?: (checked: boolean) => void; }) { return ( { - props.onChange(value); + props.onChange ? props.onChange(value) : null; }} value={props.checked} + disabled={props.disabled} /> ); diff --git a/client/packages/lowcoder/src/api/applicationApi.ts b/client/packages/lowcoder/src/api/applicationApi.ts index 2411b50d80..1aba07fbf4 100644 --- a/client/packages/lowcoder/src/api/applicationApi.ts +++ b/client/packages/lowcoder/src/api/applicationApi.ts @@ -12,7 +12,7 @@ import { SetAppEditingStatePayload, UpdateAppPermissionPayload, } from "redux/reduxActions/applicationActions"; -import {ApiResponse, GenericApiResponse} from "./apiResponses"; +import { ApiResponse, GenericApiResponse } from "./apiResponses"; import { JSONObject, JSONValue } from "util/jsonTypes"; import { ApplicationDetail, @@ -24,7 +24,10 @@ import { } from "constants/applicationConstants"; import { CommonSettingResponseData } from "./commonSettingApi"; import { ResourceType } from "@lowcoder-ee/constants/queryConstants"; -import {fetchAppRequestType, GenericApiPaginationResponse} from "@lowcoder-ee/util/pagination/type"; +import { + fetchAppRequestType, + GenericApiPaginationResponse, +} from "@lowcoder-ee/util/pagination/type"; export interface HomeOrgMeta { id: string; @@ -70,6 +73,11 @@ export interface ApplicationResp extends ApiResponse { data: ApplicationDetail; } +export interface ApplicationPublishRequest { + commitMessage?: string; + tag: string; +} + interface GrantAppPermissionReq { applicationId: string; role: ApplicationRoleType; @@ -82,38 +90,63 @@ class ApplicationApi extends Api { static fetchHomeDataURL = "/applications/home"; static createApplicationURL = "/applications"; static fetchAllMarketplaceAppsURL = "/applications/marketplace-apps"; - static deleteApplicationURL = (applicationId: string) => `/applications/${applicationId}`; - static getAppPublishInfoURL = (applicationId: string) => `/applications/${applicationId}/view`; - static getAppEditingInfoURL = (applicationId: string) => `/applications/${applicationId}`; - static updateApplicationURL = (applicationId: string) => `/applications/${applicationId}`; + static deleteApplicationURL = (applicationId: string) => + `/applications/${applicationId}`; + static getAppPublishInfoURL = (applicationId: string) => + `/applications/${applicationId}/view`; + static getAppEditingInfoURL = (applicationId: string) => + `/applications/${applicationId}`; + static updateApplicationURL = (applicationId: string) => + `/applications/${applicationId}`; static getApplicationPermissionURL = (applicationId: string) => `/applications/${applicationId}/permissions`; static grantAppPermissionURL = (applicationId: string) => `/applications/${applicationId}/permissions`; static publishApplicationURL = (applicationId: string) => `/applications/${applicationId}/publish`; - static updateAppPermissionURL = (applicationId: string, permissionId: string) => - `/applications/${applicationId}/permissions/${permissionId}`; + static updateAppPermissionURL = ( + applicationId: string, + permissionId: string + ) => `/applications/${applicationId}/permissions/${permissionId}`; static createFromTemplateURL = `/applications/createFromTemplate`; - static publicToAllURL = (applicationId: string) => `/applications/${applicationId}/public-to-all`; - static publicToMarketplaceURL = (applicationId: string) => `/applications/${applicationId}/public-to-marketplace`; - static getMarketplaceAppURL = (applicationId: string) => `/applications/${applicationId}/view_marketplace`; - static setAppEditingStateURL = (applicationId: string) => `/applications/editState/${applicationId}`; + static publicToAllURL = (applicationId: string) => + `/applications/${applicationId}/public-to-all`; + static publicToMarketplaceURL = (applicationId: string) => + `/applications/${applicationId}/public-to-marketplace`; + static getMarketplaceAppURL = (applicationId: string) => + `/applications/${applicationId}/view_marketplace`; + static setAppEditingStateURL = (applicationId: string) => + `/applications/editState/${applicationId}`; static serverSettingsURL = () => `/serverSettings`; - static fetchHomeData(request: HomeDataPayload): AxiosPromise { + static fetchHomeData( + request: HomeDataPayload + ): AxiosPromise { return Api.get(ApplicationApi.fetchHomeDataURL, request); } - static fetchAllApplications(request: HomeDataPayload): AxiosPromise { - return Api.get(ApplicationApi.newURLPrefix + "/list", { ...request, withContainerSize: false }); + static fetchAllApplications( + request: HomeDataPayload + ): AxiosPromise { + return Api.get(ApplicationApi.newURLPrefix + "/list", { + ...request, + withContainerSize: false, + }); } - static fetchAllApplicationsPagination(request: fetchAppRequestType): AxiosPromise> { - return Api.get(ApplicationApi.newURLPrefix + "/list", { ...request, withContainerSize: false, applicationStatus: "RECYCLED" }); + static fetchAllApplicationsPagination( + request: fetchAppRequestType + ): AxiosPromise> { + return Api.get(ApplicationApi.newURLPrefix + "/list", { + ...request, + withContainerSize: false, + applicationStatus: "RECYCLED", + }); } - static fetchAllModules(request: HomeDataPayload): AxiosPromise { + static fetchAllModules( + request: HomeDataPayload + ): AxiosPromise { return Api.get(ApplicationApi.newURLPrefix + "/list", { applicationType: AppTypeEnum.Module, applicationStatus: "NORMAL", @@ -122,11 +155,15 @@ class ApplicationApi extends Api { }); } - static fetchRecycleList(): AxiosPromise> { + static fetchRecycleList(): AxiosPromise< + GenericApiResponse + > { return Api.get(ApplicationApi.newURLPrefix + "/recycle/list"); } - static createApplication(request: CreateApplicationPayload): AxiosPromise { + static createApplication( + request: CreateApplicationPayload + ): AxiosPromise { return Api.post(ApplicationApi.createApplicationURL, { orgId: request.orgId, name: request.applicationName, @@ -145,19 +182,25 @@ class ApplicationApi extends Api { static recycleApplication( request: RecycleApplicationPayload ): AxiosPromise> { - return Api.put(ApplicationApi.newURLPrefix + `/recycle/${request.applicationId}`); + return Api.put( + ApplicationApi.newURLPrefix + `/recycle/${request.applicationId}` + ); } static restoreApplication( request: RestoreApplicationPayload ): AxiosPromise> { - return Api.put(ApplicationApi.newURLPrefix + `/restore/${request.applicationId}`); + return Api.put( + ApplicationApi.newURLPrefix + `/restore/${request.applicationId}` + ); } static deleteApplication( request: DeleteApplicationPayload ): AxiosPromise> { - return Api.delete(ApplicationApi.deleteApplicationURL(request.applicationId)); + return Api.delete( + ApplicationApi.deleteApplicationURL(request.applicationId) + ); } static updateApplication(request: { @@ -170,11 +213,18 @@ class ApplicationApi extends Api { return Api.put(ApplicationApi.updateApplicationURL(applicationId), rest); } - static publishApplication(request: PublishApplicationPayload): AxiosPromise { - return Api.post(ApplicationApi.publishApplicationURL(request.applicationId)); + static publishApplication( + request: PublishApplicationPayload + ): AxiosPromise { + return Api.post( + ApplicationApi.publishApplicationURL(request.applicationId), + request?.request + ); } - static getApplicationDetail(request: FetchAppInfoPayload): AxiosPromise { + static getApplicationDetail( + request: FetchAppInfoPayload + ): AxiosPromise { const { type, applicationId } = request; const url = type === "published" @@ -185,13 +235,20 @@ class ApplicationApi extends Api { return Api.get(url); } - static getApplicationPermissions(applicationId: string): AxiosPromise { + static getApplicationPermissions( + applicationId: string + ): AxiosPromise { return Api.get(ApplicationApi.getApplicationPermissionURL(applicationId)); } - static grantAppPermission(request: GrantAppPermissionReq): AxiosPromise { + static grantAppPermission( + request: GrantAppPermissionReq + ): AxiosPromise { const { applicationId, ...requestParam } = request; - return Api.put(ApplicationApi.grantAppPermissionURL(applicationId), requestParam); + return Api.put( + ApplicationApi.grantAppPermissionURL(applicationId), + requestParam + ); } static updateAppPermission( @@ -208,7 +265,9 @@ class ApplicationApi extends Api { request: DeleteAppPermissionPayload ): AxiosPromise { const { applicationId, permissionId } = request; - return Api.delete(ApplicationApi.updateAppPermissionURL(applicationId, permissionId)); + return Api.delete( + ApplicationApi.updateAppPermissionURL(applicationId, permissionId) + ); } static createFromTemplate(templateId: string): AxiosPromise { @@ -240,7 +299,9 @@ class ApplicationApi extends Api { return Api.get(ApplicationApi.getMarketplaceAppURL(appId)); } - static setAppEditingState(request: SetAppEditingStatePayload): AxiosPromise { + static setAppEditingState( + request: SetAppEditingStatePayload + ): AxiosPromise { const { applicationId, editingFinished } = request; return Api.put(ApplicationApi.setAppEditingStateURL(applicationId), { editingFinished, diff --git a/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx b/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx index 3a22c96a43..e36e3d6ab3 100644 --- a/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx +++ b/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx @@ -12,6 +12,7 @@ import { fetchApplicationPermissions, updateAppPermission, updateAppPermissionInfo, + publishApplication, } from "../../redux/reduxActions/applicationActions"; import { PermissionItemsType } from "./PermissionList"; import { trans } from "../../i18n"; @@ -30,125 +31,263 @@ import { PermissionRole } from "./Permission"; import { SHARE_TITLE } from "../../constants/apiConstants"; import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; import { default as Divider } from "antd/es/divider"; +import { default as Form } from "antd/es/form"; +import { Typography } from "antd"; +import StepModal from "../StepModal"; +import { AddIcon } from "icons"; +import { GreyTextColor } from "constants/style"; +import { VersionDataForm } from "@lowcoder-ee/pages/common/versionDataForm"; -export const AppPermissionDialog = React.memo((props: { - applicationId: string; - visible: boolean; - onVisibleChange: (visible: boolean) => void; -}) => { - const { applicationId } = props; - const dispatch = useDispatch(); - const appPermissionInfo = useSelector(getAppPermissionInfo); +const BottomWrapper = styled.div` + margin: 12px 16px 0 16px; + display: flex; + justify-content: space-between; +`; - const { appType } = useContext(ExternalEditorContext); - const isModule = appType === AppTypeEnum.Module; +const AddPermissionButton = styled(TacoButton)` + &, + &:hover, + &:focus { + border: none; + box-shadow: none; + padding: 0; + display: flex; + align-items: center; + font-size: 14px; + line-height: 14px; + background: #ffffff; + transition: unset; + } - useEffect(() => { - dispatch(fetchApplicationPermissions({ applicationId: applicationId })); - }, [applicationId, dispatch]); + svg { + margin-right: 4px; + } - let permissions: PermissionItemsType = []; - if (appPermissionInfo) { - const creator = appPermissionInfo.permissions.find( - (p) => p.type === "USER" && p.id === appPermissionInfo.creatorId - ); + &:hover { + color: #315efb; - permissions = [ - { - permissionItem: { - permissionId: "orgAdmin", - id: "orgAdmin", - role: "owner", - name: trans("home.orgName", { orgName: appPermissionInfo.orgName }), - type: "ORG_ADMIN", - }, - }, - ...appPermissionInfo.permissions - .filter((p) => !(p.type === "USER" && p.id === appPermissionInfo.creatorId)) - .map((p) => ({ - permissionItem: p, - })), - ]; - if (creator) { - permissions = [ - { - isCreator: true, - permissionItem: creator, - }, - ...permissions, - ]; + svg g path { + fill: #315efb; } } +`; - return ( - { - if (!appPermissionInfo) { - return ; - } - return ( - <> - - {list} - - ); - }} - supportRoles={[ - { label: trans("share.viewer"), value: PermissionRole.Viewer }, - { - label: trans("share.editor"), - value: PermissionRole.Editor, - }, +export const AppPermissionDialog = React.memo( + (props: { + applicationId: string; + visible: boolean; + onVisibleChange: (visible: boolean) => void; + }) => { + const [form] = Form.useForm(); + const { appType } = useContext(ExternalEditorContext); + const isModule = appType === AppTypeEnum.Module; + const { applicationId } = props; + + const dispatch = useDispatch(); + const appPermissionInfo = useSelector(getAppPermissionInfo); + const [activeStepKey, setActiveStepKey] = useState("permission"); + + useEffect(() => { + dispatch(fetchApplicationPermissions({ applicationId: applicationId })); + }, [applicationId, dispatch]); + + let permissions: PermissionItemsType = []; + if (appPermissionInfo) { + const creator = appPermissionInfo.permissions.find( + (p) => p.type === "USER" && p.id === appPermissionInfo.creatorId + ); + + permissions = [ { - label: trans("share.owner"), - value: PermissionRole.Owner, + permissionItem: { + permissionId: "orgAdmin", + id: "orgAdmin", + role: "owner", + name: trans("home.orgName", { orgName: appPermissionInfo.orgName }), + type: "ORG_ADMIN", + }, }, - ]} - permissionItems={permissions} - addPermission={(userIds, groupIds, role, onSuccess) => - ApplicationApi.grantAppPermission({ - applicationId: applicationId, - userIds: userIds, - groupIds: groupIds, - role: role as any, - }) - .then((resp) => { - if (validateResponse(resp)) { - dispatch(fetchApplicationPermissions({ applicationId: applicationId })); - onSuccess(); - } - }) - .catch((e) => { - messageInstance.error(trans("home.addPermissionErrorMessage", { message: e.message })); - }) - } - updatePermission={(permissionId, role) => - dispatch( - updateAppPermission({ - applicationId: applicationId, - role: role as ApplicationRoleType, - permissionId: permissionId, - }) - ) - } - deletePermission={(permissionId) => - dispatch( - deleteAppPermission({ - applicationId: applicationId, - permissionId: permissionId, - }) - ) + ...appPermissionInfo.permissions + .filter( + (p) => !(p.type === "USER" && p.id === appPermissionInfo.creatorId) + ) + .map((p) => ({ + permissionItem: p, + })), + ]; + if (creator) { + permissions = [ + { + isCreator: true, + permissionItem: creator, + }, + ...permissions, + ]; } - /> - ); -}); + } + + return ( + { + setActiveStepKey("permission"); + props.onVisibleChange(false); + }} + showOkButton={true} + showBackLink={true} + showCancelButton={true} + width="440px" + onStepChange={setActiveStepKey} + activeStepKey={activeStepKey} + steps={[ + { + key: "permission", + titleRender: () => null, + bodyRender: (modalProps) => ( + { + if (!appPermissionInfo) { + return ; + } + return <>{list}; + }} + supportRoles={[ + { + label: trans("share.viewer"), + value: PermissionRole.Viewer, + }, + { + label: trans("share.editor"), + value: PermissionRole.Editor, + }, + { + label: trans("share.owner"), + value: PermissionRole.Owner, + }, + ]} + permissionItems={permissions} + addPermission={(userIds, groupIds, role, onSuccess) => + ApplicationApi.grantAppPermission({ + applicationId: applicationId, + userIds: userIds, + groupIds: groupIds, + role: role as any, + }) + .then((resp) => { + if (validateResponse(resp)) { + dispatch( + fetchApplicationPermissions({ + applicationId: applicationId, + }) + ); + onSuccess(); + } + }) + .catch((e) => { + messageInstance.error( + trans("home.addPermissionErrorMessage", { + message: e.message, + }) + ); + }) + } + updatePermission={(permissionId, role) => + dispatch( + updateAppPermission({ + applicationId: applicationId, + role: role as ApplicationRoleType, + permissionId: permissionId, + }) + ) + } + deletePermission={(permissionId) => + dispatch( + deleteAppPermission({ + applicationId: applicationId, + permissionId: permissionId, + }) + ) + } + viewFooterRender={(primaryModelProps, props) => ( + + } + onClick={() => { + props.next(); + }} + > + {trans("home.addMember")} + + + { + primaryModelProps.next(); + }} + > + {trans("event.next") + " "} + + + )} + primaryModelProps={modalProps} + /> + ), + footerRender: () => null, + }, + { + key: "versions", + titleRender: () => trans("home.versions"), + bodyRender: () => ( + + ), + footerRender: (modalProps) => ( + + { + modalProps.back(); + }} + > + {trans("back")} + + { + form.validateFields().then(() => { + dispatch( + publishApplication({ + applicationId: applicationId, + request: form.getFieldsValue(), + }) + ); + modalProps.back(); + props.onVisibleChange(false); + }); + }} + > + {trans("queryLibrary.publish")} + + + ), + }, + ]} + /> + ); + } +); const InviteInputBtn = styled.div` display: flex; @@ -162,10 +301,13 @@ const InviteInputBtn = styled.div` `; const AppInviteView = (props: { appId: string }) => { - const inviteLink = window.location.origin + APPLICATION_VIEW_URL(props.appId, "view"); + const inviteLink = + window.location.origin + APPLICATION_VIEW_URL(props.appId, "view"); return ( <> - {trans("home.shareLink")} + + {trans("home.shareLink")} + { setPublic(permissionInfo.publicToAll); @@ -206,9 +351,20 @@ function AppShareView(props: { useEffect(() => { setPublicToMarketplace(permissionInfo.publicToMarketplace); }, [permissionInfo.publicToMarketplace]); + return (
- + + + - {isPublic && + {isPublic && ( { validateResponse(resp); - dispatch(updateAppPermissionInfo({ publicToMarketplace: checked })); + dispatch( + updateAppPermissionInfo({ publicToMarketplace: checked }) + ); }) .catch((e) => { messageInstance.error(e.message); }); - } } - label={isModule ? trans("home.moduleMarketplaceMessage") : trans("home.appMarketplaceMessage")} /> - } - { isPublicToMarketplace && <>
- {trans("home.marketplaceGoodPublishing")} -
} + }} + label={ + isModule + ? trans("home.moduleMarketplaceMessage") + : trans("home.appMarketplaceMessage") + } + /> + + )} + {isPublicToMarketplace && isPublic && ( +
+ + {trans("home.marketplaceGoodPublishing")} + + +
+ )} {isPublic && } + + + + +
+ + {trans("home.publishVersionDescription")} + +
); } diff --git a/client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx b/client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx index 0834cf2d9e..274fb496ca 100644 --- a/client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx +++ b/client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx @@ -2,44 +2,7 @@ import React, { ReactNode, useState } from "react"; import { PermissionItemsType, PermissionList } from "./PermissionList"; import StepModal from "../StepModal"; import { trans } from "../../i18n"; -import { TacoButton } from "components/button"; -import { AddIcon } from "icons"; -import { GreyTextColor } from "constants/style"; import { Permission, PermissionRole } from "./Permission"; -import styled from "styled-components"; - -const BottomWrapper = styled.div` - margin: 12px 16px 0 16px; - display: flex; -`; - -const AddPermissionButton = styled(TacoButton)` - &, - &:hover, - &:focus { - border: none; - box-shadow: none; - padding: 0; - display: flex; - align-items: center; - font-size: 14px; - line-height: 14px; - background: #ffffff; - transition: unset; - } - - svg { - margin-right: 4px; - } - - &:hover { - color: #315efb; - - svg g path { - fill: #315efb; - } - } -`; export const PermissionDialog = (props: { title: string; @@ -47,6 +10,7 @@ export const PermissionDialog = (props: { visible: boolean; onVisibleChange: (visible: boolean) => void; viewBodyRender?: (list: ReactNode) => ReactNode; + viewFooterRender?: (primaryModelProps: any, props: any) => ReactNode; permissionItems: PermissionItemsType; supportRoles: { label: string; value: PermissionRole }[]; addPermission: ( @@ -57,9 +21,18 @@ export const PermissionDialog = (props: { ) => void; updatePermission: (permissionId: string, role: string) => void; deletePermission: (permissionId: string) => void; + primaryModelProps?: {}; }) => { - const { supportRoles, permissionItems, visible, onVisibleChange, addPermission, viewBodyRender } = - props; + const { + supportRoles, + permissionItems, + visible, + onVisibleChange, + addPermission, + viewBodyRender, + viewFooterRender, + primaryModelProps, + } = props; const [activeStepKey, setActiveStepKey] = useState("view"); return ( @@ -85,26 +58,10 @@ export const PermissionDialog = (props: { ) : ( ), - footerRender: (props) => ( - - } - onClick={() => { - props.next(); - }} - > - {trans("home.addMember")} - - onVisibleChange(false)} - style={{ marginLeft: "auto", width: "76px", height: "28px" }} - > - {trans("finish") + " "} - - - ), + footerRender: (props) => + viewFooterRender + ? viewFooterRender(primaryModelProps, props) + : null, }, { key: "add", @@ -119,7 +76,7 @@ export const PermissionDialog = (props: { } /> ), - footerRender: (props) => null, + footerRender: () => null, }, ]} /> diff --git a/client/packages/lowcoder/src/components/PermissionDialog/PermissionList.tsx b/client/packages/lowcoder/src/components/PermissionDialog/PermissionList.tsx index 4fd3abb9ef..0f821cd8b5 100644 --- a/client/packages/lowcoder/src/components/PermissionDialog/PermissionList.tsx +++ b/client/packages/lowcoder/src/components/PermissionDialog/PermissionList.tsx @@ -1,5 +1,8 @@ import { ASSETS_URI } from "constants/apiConstants"; -import { ApplicationPermissionType, ApplicationRoleType } from "constants/applicationConstants"; +import { + ApplicationPermissionType, + ApplicationRoleType, +} from "constants/applicationConstants"; import { CommonErrorLabel, CommonGrayLabel, @@ -101,15 +104,22 @@ function PermissionLiItem(props: { side={32} userName={permissionItem.name} source={permissionItem.avatar && ASSETS_URI(permissionItem.avatar)} - svg={SvgIcon && } + svg={ + SvgIcon && ( + + ) + } /> - {permissionItem.type === "GROUP" && trans("home.groupWithSquareBrackets")} + {permissionItem.type === "GROUP" && + trans("home.groupWithSquareBrackets")} {permissionItem.name} {isCreator && {trans("home.creator")}} {isCreator || permissionItem.type === "ORG_ADMIN" ? ( - + {props.ownerLabel} ) : ( @@ -145,7 +155,9 @@ function PermissionLiItem(props: { value="delete" permissionid={permissionItem.permissionId} > - {trans("remove")} + + {trans("remove")} + )} @@ -153,7 +165,10 @@ function PermissionLiItem(props: { ); } -export type PermissionItemsType = { permissionItem: PermissionItem; isCreator?: boolean }[]; +export type PermissionItemsType = { + permissionItem: PermissionItem; + isCreator?: boolean; +}[]; export const PermissionList = (props: { ownerLabel: string; supportRoles: { label: string; value: PermissionRole }[]; @@ -163,7 +178,7 @@ export const PermissionList = (props: { }) => ( <> - {trans("home.memberPermissionList")} + {`${trans("memberSettings.title")}:`} {props.permissionItems.map((item, index) => ( diff --git a/client/packages/lowcoder/src/components/StepModal.tsx b/client/packages/lowcoder/src/components/StepModal.tsx index 13d08319b3..2983b26628 100644 --- a/client/packages/lowcoder/src/components/StepModal.tsx +++ b/client/packages/lowcoder/src/components/StepModal.tsx @@ -25,7 +25,9 @@ export interface StepModalProps extends CustomModalProps { export default function StepModal(props: StepModalProps) { const { steps, activeStepKey, onStepChange, ...modalProps } = props; const [current, setCurrent] = useState(steps[0]?.key); - const currentStepIndex = steps.findIndex((i) => i.key === activeStepKey ?? current); + const currentStepIndex = steps.findIndex( + (i) => i.key === activeStepKey ?? current + ); const currentStep = currentStepIndex >= 0 ? steps[currentStepIndex] : null; const handleChangeStep = (key: string) => { diff --git a/client/packages/lowcoder/src/pages/common/header.tsx b/client/packages/lowcoder/src/pages/common/header.tsx index 0b32ef3966..36cb352eeb 100644 --- a/client/packages/lowcoder/src/pages/common/header.tsx +++ b/client/packages/lowcoder/src/pages/common/header.tsx @@ -1,8 +1,8 @@ import { default as Dropdown } from "antd/es/dropdown"; import { default as Skeleton } from "antd/es/skeleton"; import { default as Radio, RadioChangeEvent } from "antd/es/radio"; -import { default as Statistic} from "antd/es/statistic"; -import { default as Flex} from "antd/es/flex"; +import { default as Statistic } from "antd/es/statistic"; +import { default as Flex } from "antd/es/flex"; import { default as Popover } from "antd/es/popover"; import { default as Typography } from "antd/es/typography"; import LayoutHeader from "components/layout/Header"; @@ -40,7 +40,10 @@ import { recoverSnapshotAction, setShowAppSnapshot, } from "redux/reduxActions/appSnapshotActions"; -import { currentApplication, isPublicApplication } from "redux/selectors/applicationSelector"; +import { + currentApplication, + isPublicApplication, +} from "redux/selectors/applicationSelector"; import { getSelectedAppSnapshot, showAppSnapshotSelector, @@ -59,8 +62,8 @@ import { getBrandingConfig } from "../../redux/selectors/configSelectors"; import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; import { EditorContext } from "../../comps/editorState"; import Tooltip from "antd/es/tooltip"; -import { LockOutlined, ExclamationCircleOutlined } from '@ant-design/icons'; -import Avatar from 'antd/es/avatar'; +import { LockOutlined, ExclamationCircleOutlined } from "@ant-design/icons"; +import Avatar from "antd/es/avatar"; import UserApi from "@lowcoder-ee/api/userApi"; import { validateResponse } from "@lowcoder-ee/api/apiUtils"; import ProfileImage from "./profileImage"; @@ -194,7 +197,7 @@ const GrayBtn = styled(TacoButton)` color: #ffffff; border: none; } - + &[disabled] { cursor: not-allowed; } @@ -314,10 +317,8 @@ const StyledRefreshIcon = styled(RefreshIcon)` // Add the lock icon logic for disabled options const DropdownMenuStyled = styled(DropdownMenu)` .ant-dropdown-menu-item:hover { - background: ${(props) => - props.disabled ? 'inherit' : '#edf4fa'}; - cursor: ${(props) => - props.disabled ? 'not-allowed' : 'pointer'}; + background: ${(props) => (props.disabled ? "inherit" : "#edf4fa")}; + cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")}; } `; @@ -343,7 +344,7 @@ function HeaderProfile(props: { user: User }) { ); } -const setCountdown = () => dayjs().add(3, 'minutes').toISOString(); +const setCountdown = () => dayjs().add(3, "minutes").toISOString(); export type PanelStatus = { left: boolean; bottom: boolean; right: boolean }; export type TogglePanel = (panel?: keyof PanelStatus) => void; @@ -373,27 +374,28 @@ export default function Header(props: HeaderProps) { const applicationId = useApplicationId(); const dispatch = useDispatch(); const showAppSnapshot = useSelector(showAppSnapshotSelector); - const {selectedSnapshot, isArchivedSnapshot} = useSelector(getSelectedAppSnapshot); + const { selectedSnapshot, isArchivedSnapshot } = useSelector( + getSelectedAppSnapshot + ); const { appType } = useContext(ExternalEditorContext); const [editName, setEditName] = useState(false); const [editing, setEditing] = useState(false); const [permissionDialogVisible, setPermissionDialogVisible] = useState(false); const [editingUser, setEditingUser] = useState(); - const [enableCheckEditingStatus, setEnableCheckEditingStatus] = useState(false); + const [enableCheckEditingStatus, setEnableCheckEditingStatus] = + useState(false); const editingCountdown = useRef(setCountdown()); const isModule = appType === AppTypeEnum.Module; useEffect(() => { - if(blockEditing && application && Boolean(application?.editingUserId)) { - UserApi.getUserDetail(application.editingUserId!) - .then(resp => { - if (validateResponse(resp)) { - - console.log('editing user', resp.data.data); - setEditingUser(resp.data.data); - } - }); + if (blockEditing && application && Boolean(application?.editingUserId)) { + UserApi.getUserDetail(application.editingUserId!).then((resp) => { + if (validateResponse(resp)) { + console.log("editing user", resp.data.data); + setEditingUser(resp.data.data); + } + }); } }, [blockEditing]); @@ -424,7 +426,6 @@ export default function Header(props: HeaderProps) { editorState.setEditorModeStatus(value); }; - const headerStart = ( <> history.push(ALL_APPLICATIONS_URL)}> @@ -514,7 +515,7 @@ export default function Header(props: HeaderProps) { application.applicationId, selectedSnapshot.snapshotId, selectedSnapshot.createTime, - isArchivedSnapshot, + isArchivedSnapshot ) ); }, @@ -539,52 +540,65 @@ export default function Header(props: HeaderProps) { {/* Display a hint about who is editing the app */} {blockEditing && Boolean(applicationId) && ( <> - { - return ( - - - {trans("header.AppEditingBlockedHint")} - - { - setEnableCheckEditingStatus(true) - }} - /> - { + return ( + - { - fetchApplication?.(); - setEnableCheckEditingStatus(false); - editingCountdown.current = setCountdown(); + + {trans("header.AppEditingBlockedHint")} + + { + setEnableCheckEditingStatus(true); }} + /> + - - {trans("header.AppEditingBlockedCheckStatus")} - - - - ) - }} - trigger="hover" - > - - - - {`${editingUser?.email || trans("header.AppEditingBlockedSomeone")}` + " " + trans("header.AppEditingBlockedMessageSnipped")} - - - - + { + fetchApplication?.(); + setEnableCheckEditingStatus(false); + editingCountdown.current = setCountdown(); + }} + > + + + {trans("header.AppEditingBlockedCheckStatus")} + + + + + ); + }} + trigger="hover" + > + + + + {`${editingUser?.email || trans("header.AppEditingBlockedSomeone")}` + + " " + + trans("header.AppEditingBlockedMessageSnipped")} + + + + )} @@ -598,15 +612,18 @@ export default function Header(props: HeaderProps) { /> )} {canManageApp(user, application) && ( - setPermissionDialogVisible(true)} disabled={blockEditing}> - {SHARE_TITLE} + setPermissionDialogVisible(true)} + disabled={blockEditing} + > + {trans("header.deploy")} )} - + preview(applicationId)}> {trans("header.preview")} - + { if (blockEditing) return; // Prevent clicks if the app is being edited by someone else - if (e.key === "deploy") { - dispatch(publishApplication({ applicationId })); - } else if (e.key === "snapshot") { + if (e.key === "snapshot") { dispatch(setShowAppSnapshot(true)); } }} items={[ - { - key: "deploy", - label: ( -
- {blockEditing && } - - {trans("header.deploy")} - -
- ), - disabled: blockEditing, - }, { key: "snapshot", label: ( -
- {blockEditing && } - +
+ {blockEditing && ( + + )} + {trans("header.snapshot")}
@@ -655,7 +662,7 @@ export default function Header(props: HeaderProps) { - + ); diff --git a/client/packages/lowcoder/src/pages/common/versionDataForm.tsx b/client/packages/lowcoder/src/pages/common/versionDataForm.tsx new file mode 100644 index 0000000000..7093b5f0fb --- /dev/null +++ b/client/packages/lowcoder/src/pages/common/versionDataForm.tsx @@ -0,0 +1,35 @@ +import React from "react"; +import { + DatasourceForm, + FormInputItem, + FormRadioItem, + FormSection, +} from "lowcoder-design"; +import { getVersionOptions } from "@lowcoder-ee/util/versionOptions"; +import { trans } from "../../i18n"; + +export const VersionDataForm = (props: { form: any; preserve: boolean }) => { + const { form, preserve } = props; + const versionOptions = getVersionOptions(); + + return ( + + + + + + + ); +}; diff --git a/client/packages/lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx b/client/packages/lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx index 48e8f2e29b..cb18005d57 100644 --- a/client/packages/lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx +++ b/client/packages/lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx @@ -1,5 +1,8 @@ import React, { useEffect, useMemo, useState } from "react"; -import { fetchDatasource, fetchDataSourceTypes } from "../../redux/reduxActions/datasourceActions"; +import { + fetchDatasource, + fetchDataSourceTypes, +} from "../../redux/reduxActions/datasourceActions"; import { useDispatch, useSelector } from "react-redux"; import { getUser } from "../../redux/selectors/usersSelectors"; import { @@ -22,7 +25,7 @@ import { useCompInstance } from "../../comps/utils/useCompInstance"; import { QueryLibraryComp } from "../../comps/comps/queryLibrary/queryLibraryComp"; import { useSearchParam, useThrottle } from "react-use"; import { Comp } from "lowcoder-core"; -import {LibraryQuery} from "../../api/queryLibraryApi"; +import { LibraryQuery } from "../../api/queryLibraryApi"; import { NameGenerator } from "../../comps/utils"; import { QueryLibraryHistoryView } from "./QueryLibraryHistoryView"; import { default as Form } from "antd/es/form"; @@ -46,8 +49,10 @@ import { importQueryLibrary } from "./importQueryLibrary"; import { registryDataSourcePlugin } from "constants/queryConstants"; import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; import { Helmet } from "react-helmet"; -import {fetchQLPaginationByOrg} from "@lowcoder-ee/util/pagination/axios"; +import { fetchQLPaginationByOrg } from "@lowcoder-ee/util/pagination/axios"; import { isEmpty } from "lodash"; +import { getVersionOptions } from "@lowcoder-ee/util/versionOptions"; +import { VersionDataForm } from "../common/versionDataForm"; const Wrapper = styled.div` display: flex; @@ -68,7 +73,7 @@ interface ElementsState { function transformData(input: LibraryQuery[]) { const output: any = {}; - input.forEach(item => { + input.forEach((item) => { output[item.id] = item; }); return output; @@ -84,11 +89,16 @@ export const QueryLibraryEditor = () => { const forwardQueryId = useSearchParam("forwardQueryId"); const [isCreatePanelShow, showCreatePanel] = useState(false); - const [selectedQuery, setSelectedQuery] = useState(forwardQueryId ?? ""); + const [selectedQuery, setSelectedQuery] = useState( + forwardQueryId ?? "" + ); const [publishModalVisible, setPublishModalVisible] = useState(false); const [showHistory, setShowHistory] = useState(false); const [isDataSourceReady, setIsDataSourceReady] = useState(false); - const [elements, setElements] = useState({ elements: [], total: 0 }); + const [elements, setElements] = useState({ + elements: [], + total: 0, + }); const [queryLibrary, setQueryLibrary] = useState({}); const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); @@ -119,29 +129,28 @@ export const QueryLibraryEditor = () => { useSaveQueryLibrary(libraryQuery, comp); useEffect(() => { - try { - fetchQLPaginationByOrg( - { - name: searchValues, - pageNum: currentPage, - pageSize: pageSize, - } - ).then(result => { - if (result.success){ - setElements({elements: result.data || [], total: result.total || 1}) - setQueryLibrary(transformData(result.data || [])); - } - }); - } catch (error) { - console.error(error) + try { + fetchQLPaginationByOrg({ + name: searchValues, + pageNum: currentPage, + pageSize: pageSize, + }).then((result) => { + if (result.success) { + setElements({ + elements: result.data || [], + total: result.total || 1, + }); + setQueryLibrary(transformData(result.data || [])); } - }, [currentPage, pageSize, searchValues, modify]) + }); + } catch (error) { + console.error(error); + } + }, [currentPage, pageSize, searchValues, modify]); - useEffect( () => { - if (searchValues !== "") - setCurrentPage(1); - }, [searchValues] - ); + useEffect(() => { + if (searchValues !== "") setCurrentPage(1); + }, [searchValues]); useEffect(() => { if (orgId) { @@ -169,7 +178,7 @@ export const QueryLibraryEditor = () => { useEffect(() => { if (!forwardQueryId && !queryLibrary[selectedQuery]) { // @ts-ignore - setSelectedQuery(Object.values(queryLibrary)?.[0]?.id); + setSelectedQuery(Object.values(queryLibrary)?.[0]?.id); } }, [dispatch, Object.keys(queryLibrary).length]); @@ -189,13 +198,13 @@ export const QueryLibraryEditor = () => { }) .map((info) => info.datasource); - const recentlyUsed = Object.values(queryLibrary) + const recentlyUsed = Object.values(queryLibrary) .map((i: any) => i.libraryQueryDSL?.query.datasourceId) .map((id) => datasource.find((d) => d.id === id)) .filter((i) => !!i) as Datasource[]; const nameGenerator = new NameGenerator(); - nameGenerator.init(Object.values(queryLibrary).map((t: any) => t.name)); + nameGenerator.init(Object.values(queryLibrary).map((t: any) => t.name)); const newName = nameGenerator.genItemName(trans("queryLibrary.unnamed")); const handleAdd = (type: BottomResTypeEnum, extraInfo?: any) => { @@ -218,7 +227,6 @@ export const QueryLibraryEditor = () => { setModify(!modify); }, 200); setCurrentPage(Math.ceil(elements.total / pageSize)); - }, () => {} ) @@ -229,7 +237,7 @@ export const QueryLibraryEditor = () => { return ( <> {{trans("home.queryLibrary")}} - + { onSelect={(id) => { setSelectedQuery(id); showCreatePanel(false); - } } + }} setCurrentPage={setCurrentPage} setPageSize={setPageSize} currentPage={currentPage} @@ -255,13 +263,14 @@ export const QueryLibraryEditor = () => { setShowHistory(false)} /> + onClose={() => setShowHistory(false)} + /> ) : ( comp.propertyView({ onPublish: () => setPublishModalVisible(true), onHistoryShow: () => setShowHistory(true), setModify: setModify, - modify: modify + modify: modify, }) )} @@ -272,26 +281,30 @@ export const QueryLibraryEditor = () => { onSelect={handleAdd} onClose={() => showCreatePanel(false)} placement={"queryLibrary"} - onImport={(options) => importQueryLibrary({ - dispatch: dispatch, - options: options, - orgId: orgId, - onSuccess: (resp) => { - setSelectedQuery(resp.data.data.id); - showCreatePanel(false); - setTimeout(() => { - setModify(!modify); - }, 200); - setCurrentPage(Math.ceil(elements.total / pageSize)); - }, - })} /> + onImport={(options) => + importQueryLibrary({ + dispatch: dispatch, + options: options, + orgId: orgId, + onSuccess: (resp) => { + setSelectedQuery(resp.data.data.id); + showCreatePanel(false); + setTimeout(() => { + setModify(!modify); + }, 200); + setCurrentPage(Math.ceil(elements.total / pageSize)); + }, + }) + } + /> )} setPublishModalVisible(false)} - latestVersion={Object.values(selectedRecords)?.[0]?.tag} /> + latestVersion={Object.values(selectedRecords)?.[0]?.tag} + /> ); @@ -319,7 +332,13 @@ const PublishModal = (props: { width="600px" title={trans("queryLibrary.publishNewVersion")} footer={ -
+
{ props.onClose(); setLoading(false); - messageInstance.success(trans("queryLibrary.publishSuccess")); + messageInstance.success( + trans("queryLibrary.publishSuccess") + ); }, onErrorCallback: () => setLoading(false), }) @@ -346,45 +367,11 @@ const PublishModal = (props: {
} > - - - - - - + ); }; -function getVersionOptions(version?: string): Array { - if (!version) { - return [ - { label: "v1.0.0", value: "v1.0.0" }, - { label: "v0.1.0", value: "v0.1.0" }, - ]; - } - const [major, minor, patch] = version.slice(1).split("."); - return [ - { - label: ["v" + (Number(major) + 1), 0, 0].join("."), - value: ["v" + (Number(major) + 1), 0, 0].join("."), - }, - { - label: ["v" + major, Number(minor) + 1, 0].join("."), - value: ["v" + major, Number(minor) + 1, 0].join("."), - }, - { - label: ["v" + major, minor, Number(patch) + 1].join("."), - value: ["v" + major, minor, Number(patch) + 1].join("."), - }, - ]; -} - function useSaveQueryLibrary( query: LibraryQuery, instance: InstanceType | null @@ -419,7 +406,7 @@ function useSaveQueryLibrary( return setPrevQueryId(queryId); } if (!Boolean(prevJsonStr) && Boolean(curJsonStr)) { - setPrevComp(comp) + setPrevComp(comp); return setPrevJsonStr(curJsonStr); } if (prevJsonStr === curJsonStr) { diff --git a/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts b/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts index 83be6cdbb1..eeb9a89d0a 100644 --- a/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts +++ b/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts @@ -8,6 +8,7 @@ import { } from "constants/applicationConstants"; import { JSONValue } from "util/jsonTypes"; import { CommonSettingResponseData } from "api/commonSettingApi"; +import { ApplicationPublishRequest } from "@lowcoder-ee/api/applicationApi"; export interface HomeDataPayload { applicationType?: AppTypeEnum; @@ -114,6 +115,7 @@ export const updateAppMetaAction = (payload: UpdateAppMetaPayload) => ({ export type PublishApplicationPayload = { applicationId: string; + request: ApplicationPublishRequest; }; export const publishApplication = (payload: PublishApplicationPayload) => ({ type: ReduxActionTypes.PUBLISH_APPLICATION, @@ -148,7 +150,9 @@ export const fetchApplicationInfo = (payload: FetchAppInfoPayload) => ({ export type FetchAppPermissionPayload = { applicationId: string; }; -export const fetchApplicationPermissions = (payload: FetchAppPermissionPayload) => ({ +export const fetchApplicationPermissions = ( + payload: FetchAppPermissionPayload +) => ({ type: ReduxActionTypes.FETCH_APP_PERMISSIONS, payload: payload, }); @@ -163,7 +167,9 @@ export const updateAppPermission = (payload: UpdateAppPermissionPayload) => ({ payload: payload, }); -export const updateAppPermissionInfo = (payload: Partial) => ({ +export const updateAppPermissionInfo = ( + payload: Partial +) => ({ type: ReduxActionTypes.UPDATE_APP_PERMISSION_INFO, payload: payload, }); diff --git a/client/packages/lowcoder/src/util/versionOptions.ts b/client/packages/lowcoder/src/util/versionOptions.ts new file mode 100644 index 0000000000..44e43b730f --- /dev/null +++ b/client/packages/lowcoder/src/util/versionOptions.ts @@ -0,0 +1,25 @@ +import { CheckboxOptionType } from "antd"; + +export function getVersionOptions(version?: string): Array { + if (!version) { + return [ + { label: "v1.0.0", value: "v1.0.0" }, + { label: "v0.1.0", value: "v0.1.0" }, + ]; + } + const [major, minor, patch] = version.slice(1).split("."); + return [ + { + label: ["v" + (Number(major) + 1), 0, 0].join("."), + value: ["v" + (Number(major) + 1), 0, 0].join("."), + }, + { + label: ["v" + major, Number(minor) + 1, 0].join("."), + value: ["v" + major, Number(minor) + 1, 0].join("."), + }, + { + label: ["v" + major, minor, Number(patch) + 1].join("."), + value: ["v" + major, minor, Number(patch) + 1].join("."), + }, + ]; +} diff --git a/translations/locales/en.js b/translations/locales/en.js index aafb078ed8..e63567cf4c 100644 --- a/translations/locales/en.js +++ b/translations/locales/en.js @@ -2949,11 +2949,14 @@ export const en = { "fileFormatError": "File format error", "groupWithSquareBrackets": "[Group] ", "allPermissions": "Owner", + "managePermissions": "Manage permissions", "shareLink": "Share link: ", "copyLink": "Copy link", "appPublicMessage": "Make the app public. Anyone can view.", "modulePublicMessage": "Make the module public. Anyone can view.", "marketplaceURL": "https://api-service.lowcoder.cloud", + "appMemberMessage": "All shared members can view this app.", + "moduleMemberMessage": "All shared members can view this module.", "appMarketplaceMessage": "Publish your App on the Public Marketplace. Anyone can view and copy it from there.", "moduleMarketplaceMessage": "Publish your Module on the Public 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.", @@ -2975,6 +2978,8 @@ export const en = { "createNavigation": "Create Navigation", "howToUseAPI": "How to use the Open Rest API", "support": "Support", + "versions": "Versions", + "publishVersionDescription": "By publishing, your users will see the current state of your app. Further editing will not be visible until you publish again", }, "support": { "supportTitle": "Lowcoder Support", From e987a60aa982397ac95981718d9214a240b2fe50 Mon Sep 17 00:00:00 2001 From: Kamal Qureshi Date: Thu, 15 May 2025 15:45:39 +0500 Subject: [PATCH 11/13] Removed unnecessary files --- .github/workflows/sonarcloud.yml | 1 - .../Individualization JavaScript Libraries | Bin 45852 -> 0 bytes .../write-javascript/transformers.md | 2 +- .../use-third-party-libraries-in-apps/README.md | 2 +- 4 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 docs/.gitbook/assets/Individualization JavaScript Libraries diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 55e2fcebc3..f5cdd52809 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -30,4 +30,3 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_SCANNER_OPTS: "-Dsonar.javascript.node.maxspace=8192 -Xmx512m" diff --git a/docs/.gitbook/assets/Individualization JavaScript Libraries b/docs/.gitbook/assets/Individualization JavaScript Libraries deleted file mode 100644 index 8c2598f1cb337d00da091ad091c769658ed318ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45852 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 Transformer** in a query editor to create a transformer. +Click **+ New > Transfromer** in a query editor to create a transformer. Then write your JS code in the transformer. You can click **Preview** to get the return value and access it by `transformerName.value` in your app. diff --git a/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md b/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md index ae0759dc9c..11b85ddf08 100644 --- a/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md +++ b/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md @@ -16,7 +16,7 @@ Lowcoder provides some JavaScript built-in libraries for use. Built-in Libraries can be used directly everywhere where you can use JavaScript. ``` -// lodash +// loadash return _.chunk(['a', 'b', 'c', 'd'], 2); // => [['a', 'b'], ['c', 'd']] From d7b0a0d37f50b15dbab1c8a12c39441e288ea9d3 Mon Sep 17 00:00:00 2001 From: Kamal Qureshi Date: Thu, 15 May 2025 15:49:19 +0500 Subject: [PATCH 12/13] bug fix --- .../use-third-party-libraries-in-apps/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md b/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md index 11b85ddf08..6e60d0488a 100644 --- a/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md +++ b/docs/lowcoder-extension/use-third-party-libraries-in-apps/README.md @@ -107,11 +107,11 @@ You can check popular CDNs if they host your desired library as a minified packa ### Import / bind at the app level -Navigate to the Individualization page and then click the plus sign **+** under the **JavaScript library** tab. Paste the **library** link and click **Add New**. Lowcoder will now check, if the external library will be compatible and securely usable. +Navigate to the settings page and then click the plus sign **+** under the **JavaScript library** tab. Paste the **library** link and click **Add New**. Lowcoder will now check, if the external library will be compatible and securely usable. You can also click the download icon to quickly download any recommended JS library. -

Bind an external JS Library to an individual App

+

Bind an external JS Library to an individual App

Now, you can create a JS query and insert code. From 2d08d1ea75cb3da20b3dc62d027640e1a27743de Mon Sep 17 00:00:00 2001 From: Kamal Qureshi Date: Thu, 15 May 2025 18:40:46 +0500 Subject: [PATCH 13/13] fix:- Added a prop for latest version in VersionDataForm --- .../packages/lowcoder/src/pages/common/versionDataForm.tsx | 6 +++--- .../lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/packages/lowcoder/src/pages/common/versionDataForm.tsx b/client/packages/lowcoder/src/pages/common/versionDataForm.tsx index 7093b5f0fb..c513ae8bd3 100644 --- a/client/packages/lowcoder/src/pages/common/versionDataForm.tsx +++ b/client/packages/lowcoder/src/pages/common/versionDataForm.tsx @@ -8,9 +8,9 @@ import { import { getVersionOptions } from "@lowcoder-ee/util/versionOptions"; import { trans } from "../../i18n"; -export const VersionDataForm = (props: { form: any; preserve: boolean }) => { - const { form, preserve } = props; - const versionOptions = getVersionOptions(); +export const VersionDataForm = (props: { form: any; preserve: boolean, latestVersion?: string }) => { + const { form, preserve, latestVersion } = props; + const versionOptions = getVersionOptions(latestVersion); return ( } > - + ); };