From 121de6cdf196cb9b1f3983be4ad5fa73339af98d Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Wed, 24 Dec 2025 17:42:08 +0500 Subject: [PATCH 1/2] [Feat]: merge app version --- .../lowcoder-design/src/components/Switch.tsx | 32 +- .../lowcoder/src/api/applicationApi.ts | 14 +- .../PermissionDialog/AppPermissionDialog.tsx | 366 +++++++++++++----- .../PermissionDialog/PermissionDialog.tsx | 79 +--- .../PermissionDialog/PermissionList.tsx | 2 +- .../lowcoder/src/components/StepModal.tsx | 2 +- .../src/constants/applicationConstants.ts | 2 + .../packages/lowcoder/src/i18n/locales/en.ts | 5 + .../lowcoder/src/pages/common/header.tsx | 41 +- .../src/pages/common/versionDataForm.tsx | 35 ++ .../pages/queryLibrary/QueryLibraryEditor.tsx | 40 +- .../redux/reduxActions/applicationActions.ts | 2 + .../src/redux/sagas/applicationSagas.ts | 16 +- .../lowcoder/src/util/versionOptions.ts | 25 ++ 14 files changed, 429 insertions(+), 232 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..83dbfba5b6 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<{ @@ -104,16 +122,18 @@ const JsIconGray = styled(jsIconGray)` 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} /> ); @@ -154,15 +174,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 8ed818b371..9e5234a69a 100644 --- a/client/packages/lowcoder/src/api/applicationApi.ts +++ b/client/packages/lowcoder/src/api/applicationApi.ts @@ -70,6 +70,11 @@ export interface ApplicationResp extends ApiResponse { data: ApplicationDetail; } +export interface ApplicationPublishRequest { + commitMessage?: string; + tag: string; +} + interface GrantAppPermissionReq { applicationId: string; role: ApplicationRoleType; @@ -171,8 +176,13 @@ 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 { diff --git a/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx b/client/packages/lowcoder/src/components/PermissionDialog/AppPermissionDialog.tsx index 69a9afe883..be9abcc463 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"; @@ -29,19 +30,62 @@ import { StyledLoading } from "./commonComponents"; import { PermissionRole } from "./Permission"; import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"; import { default as Divider } from "antd/es/divider"; -import { SocialShareButtons } from "components/SocialShareButtons"; +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 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; + } - const { appType } = useContext(ExternalEditorContext); - const isModule = appType === AppTypeEnum.Module; + &:hover { + color: #315efb; + + svg g path { + fill: #315efb; + } + } +`; + +export const AppPermissionDialog = React.memo( + (props: { + applicationId: string; + visible: boolean; + onVisibleChange: (visible: boolean) => void; + publishedVersion?: string | undefined; + }) => { + const [form] = Form.useForm(); + const { appType } = useContext(ExternalEditorContext); + const isModule = appType === AppTypeEnum.Module; + const { applicationId, publishedVersion } = props; + + const dispatch = useDispatch(); + const appPermissionInfo = useSelector(getAppPermissionInfo); + const [activeStepKey, setActiveStepKey] = useState("permission"); useEffect(() => { dispatch(fetchApplicationPermissions({ applicationId: applicationId })); @@ -80,76 +124,169 @@ export const AppPermissionDialog = React.memo((props: { } } - return ( - { - 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, - }) - ) - } - /> - ); -}); + 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; @@ -196,8 +333,16 @@ function AppShareView(props: { applicationId: string; permissionInfo: AppPermissionInfo; isModule: boolean; + form: any; + publishedVersion?: string; }) { - const { applicationId, permissionInfo, isModule } = props; + const { + applicationId, + permissionInfo, + isModule, + form, + publishedVersion, + } = props; const [isPublic, setPublic] = useState(permissionInfo.publicToAll); const [isPublicToMarketplace, setPublicToMarketplace] = useState(permissionInfo.publicToMarketplace); const dispatch = useDispatch(); @@ -207,11 +352,20 @@ function AppShareView(props: { useEffect(() => { setPublicToMarketplace(permissionInfo.publicToMarketplace); }, [permissionInfo.publicToMarketplace]); - const inviteLink = window.location.origin + APPLICATION_VIEW_URL(props.applicationId, "view"); return (
- + + + - {isPublic && + {isPublic && ( { 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 && } + {isPublic && } + - {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 42fb2a070a..d43ba4e318 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,11 +21,22 @@ export const PermissionDialog = (props: { ) => void; updatePermission: (permissionId: string, role: string) => void; deletePermission: (permissionId: string) => void; + primaryModelProps?: {}; contextType?: "application" | "organization"; organizationId?: string; }) => { - const { supportRoles, permissionItems, visible, onVisibleChange, addPermission, viewBodyRender, contextType, organizationId } = - props; + const { + supportRoles, + permissionItems, + visible, + onVisibleChange, + addPermission, + viewBodyRender, + viewFooterRender, + primaryModelProps, + contextType, + organizationId, + } = props; const [activeStepKey, setActiveStepKey] = useState("view"); return ( @@ -87,26 +62,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", @@ -123,7 +82,7 @@ export const PermissionDialog = (props: { organizationId={organizationId} /> ), - 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 f29ef424e5..dd44f247c4 100644 --- a/client/packages/lowcoder/src/components/PermissionDialog/PermissionList.tsx +++ b/client/packages/lowcoder/src/components/PermissionDialog/PermissionList.tsx @@ -165,7 +165,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..5636b2c24e 100644 --- a/client/packages/lowcoder/src/components/StepModal.tsx +++ b/client/packages/lowcoder/src/components/StepModal.tsx @@ -25,7 +25,7 @@ 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/constants/applicationConstants.ts b/client/packages/lowcoder/src/constants/applicationConstants.ts index f685eeb8e6..136b3be9d7 100644 --- a/client/packages/lowcoder/src/constants/applicationConstants.ts +++ b/client/packages/lowcoder/src/constants/applicationConstants.ts @@ -107,6 +107,8 @@ export interface ApplicationMeta { applicationStatus: "NORMAL" | "RECYCLED" | "DELETED"; editingUserId: string | null; lastEditedAt: number; + publishedVersion?: string; + lastPublishedTime?: number; } export interface FolderMeta { diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 47e93620ff..a9a7686b88 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -4048,6 +4048,7 @@ export const en = { "fileUploadError": "File upload error", "fileFormatError": "File format error", "groupWithSquareBrackets": "[Group] ", + "managePermissions": "Manage permissions", "allPermissions": "Owner", "appSharingDialogueTitle" : "App Sharing and Permissions", "appSocialSharing" : "Share Your App and Experience on:", @@ -4058,6 +4059,8 @@ export const en = { "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.", @@ -4080,6 +4083,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" : { diff --git a/client/packages/lowcoder/src/pages/common/header.tsx b/client/packages/lowcoder/src/pages/common/header.tsx index dc17ccb373..8dd758386d 100644 --- a/client/packages/lowcoder/src/pages/common/header.tsx +++ b/client/packages/lowcoder/src/pages/common/header.tsx @@ -60,7 +60,6 @@ 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 UserApi from "@lowcoder-ee/api/userApi"; import { validateResponse } from "@lowcoder-ee/api/apiUtils"; import ProfileImage from "./profileImage"; @@ -612,18 +611,22 @@ export default function Header(props: HeaderProps) { onVisibleChange={(visible) => !visible && setPermissionDialogVisible(false) } + publishedVersion={application?.publishedVersion} /> )} {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")}
@@ -672,7 +665,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..c513ae8bd3 --- /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, latestVersion?: string }) => { + const { form, preserve, latestVersion } = props; + const versionOptions = getVersionOptions(latestVersion); + + return ( + + + + + + + ); +}; diff --git a/client/packages/lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx b/client/packages/lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx index 706c544b46..8f494f21d1 100644 --- a/client/packages/lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx +++ b/client/packages/lowcoder/src/pages/queryLibrary/QueryLibraryEditor.tsx @@ -48,6 +48,8 @@ import { messageInstance } from "lowcoder-design/src/components/GlobalInstances" import { Helmet } from "react-helmet"; import {fetchQLPaginationByOrg} from "@lowcoder-ee/util/pagination/axios"; import { isEmpty } from "lodash"; +import { getVersionOptions } from "@lowcoder-ee/util/versionOptions"; +import { VersionDataForm } from "../common/versionDataForm"; import { processCurlData } from "../../util/curlUtils"; const Wrapper = styled.div` @@ -69,7 +71,7 @@ interface ElementsState { function transformData(input: LibraryQuery[]) { const output: any = {}; - input.forEach(item => { + input.forEach((item) => { output[item.id] = item; }); return output; @@ -369,45 +371,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 diff --git a/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts b/client/packages/lowcoder/src/redux/reduxActions/applicationActions.ts index 83be6cdbb1..c07ce8c7b8 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, diff --git a/client/packages/lowcoder/src/redux/sagas/applicationSagas.ts b/client/packages/lowcoder/src/redux/sagas/applicationSagas.ts index 062f38145f..ef5e22e857 100644 --- a/client/packages/lowcoder/src/redux/sagas/applicationSagas.ts +++ b/client/packages/lowcoder/src/redux/sagas/applicationSagas.ts @@ -179,7 +179,7 @@ export function* updateApplicationMetaSaga(action: ReduxAction) { try { - const response: AxiosResponse = yield call( + const response: AxiosResponse = yield call( ApplicationApi.publishApplication, action.payload ); @@ -189,6 +189,20 @@ export function* publishApplicationSaga(action: ReduxAction { + 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("."), + }, + ]; +} From 59784202fad995747e0dbe7dd48260595adb0af8 Mon Sep 17 00:00:00 2001 From: Faran Javed Date: Wed, 24 Dec 2025 22:22:50 +0500 Subject: [PATCH 2/2] fix UI of select component inside permission dialog --- .../src/components/PermissionDialog/commonComponents.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/packages/lowcoder/src/components/PermissionDialog/commonComponents.tsx b/client/packages/lowcoder/src/components/PermissionDialog/commonComponents.tsx index f5a9f884ad..8a06b39cad 100644 --- a/client/packages/lowcoder/src/components/PermissionDialog/commonComponents.tsx +++ b/client/packages/lowcoder/src/components/PermissionDialog/commonComponents.tsx @@ -9,8 +9,10 @@ export const StyledRoleSelect = styled(CustomSelect)` right: 0; } - .ant-select-selector { - border: none !important; + .ant-select .ant-select-selector { + margin-right: 0 !important; + padding: 0 !important; + padding: 12px !important; } .ant-select:hover {