mirror of
https://github.com/nocodb/nocodb.git
synced 2026-02-02 02:57:23 +00:00
fix: refactor managed app modal
This commit is contained in:
226
packages/nc-gui/components/dlg/ManagedApp/DraftOrPublish.vue
Normal file
226
packages/nc-gui/components/dlg/ManagedApp/DraftOrPublish.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
visible: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {})
|
||||
|
||||
const emits = defineEmits(['update:visible'])
|
||||
|
||||
const vVisible = useVModel(props, 'visible', emits)
|
||||
|
||||
const { $api } = useNuxtApp()
|
||||
const baseStore = useBase()
|
||||
|
||||
const { loadManagedApp, loadCurrentVersion } = baseStore
|
||||
|
||||
const { base, managedApp, managedAppVersionsInfo } = storeToRefs(baseStore)
|
||||
|
||||
const isDraft = computed(() => managedAppVersionsInfo.value.current?.status === 'draft')
|
||||
|
||||
const isLoading = ref(false)
|
||||
|
||||
const title = computed(() => {
|
||||
if (isDraft.value) {
|
||||
return `Publish v${managedAppVersionsInfo.value.current?.version || '1.0.0'}?`
|
||||
} else {
|
||||
return `Fork to Draft`
|
||||
}
|
||||
})
|
||||
|
||||
const subTitle = computed(() => {
|
||||
if (isDraft.value) {
|
||||
return managedAppVersionsInfo.value.published
|
||||
? `Replace v${managedAppVersionsInfo.value.published.version || '1.0.0'} and go live`
|
||||
: `Go live`
|
||||
} else {
|
||||
return `Create v${suggestManagedAppNextVersion(managedAppVersionsInfo.value.published?.version || '1.0.0')} to make changes`
|
||||
}
|
||||
})
|
||||
|
||||
// Publish form (for draft versions)
|
||||
const publishForm = reactive({
|
||||
releaseNotes: '',
|
||||
})
|
||||
|
||||
// Fork form (for creating new draft from published)
|
||||
const forkForm = reactive({
|
||||
version: '',
|
||||
releaseNotes: '',
|
||||
})
|
||||
|
||||
const loadManagedAppAndCurrentVersion = async () => {
|
||||
await loadManagedApp()
|
||||
await loadCurrentVersion()
|
||||
}
|
||||
|
||||
const publishCurrentDraft = async () => {
|
||||
if (!base.value?.fk_workspace_id || !base.value?.id || !managedAppVersionsInfo.value.current?.id) return
|
||||
|
||||
isLoading.value = true
|
||||
try {
|
||||
await $api.internal.postOperation(
|
||||
base.value.fk_workspace_id,
|
||||
base.value.id,
|
||||
{
|
||||
operation: 'managedAppPublish',
|
||||
},
|
||||
{
|
||||
managedAppVersionId: managedAppVersionsInfo.value.current.id,
|
||||
},
|
||||
)
|
||||
|
||||
// Reload base to get updated managed app version info
|
||||
if (base.value?.id) {
|
||||
await baseStore.loadProject()
|
||||
}
|
||||
|
||||
await loadManagedAppAndCurrentVersion()
|
||||
|
||||
message.success(`Version ${managedAppVersionsInfo.value.current?.version || '1.0.0'} published successfully!`)
|
||||
|
||||
vVisible.value = false
|
||||
} catch (e: any) {
|
||||
message.error(await extractSdkResponseErrorMsg(e))
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const createNewDraft = async () => {
|
||||
if (!base.value?.fk_workspace_id || !base.value?.id || !managedApp.value?.id) return
|
||||
if (!forkForm.version) {
|
||||
message.error('Please provide a version')
|
||||
return
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
try {
|
||||
await $api.internal.postOperation(
|
||||
base.value.fk_workspace_id,
|
||||
base.value.id,
|
||||
{
|
||||
operation: 'managedAppCreateDraft',
|
||||
},
|
||||
{
|
||||
managedAppId: managedApp.value.id,
|
||||
version: forkForm.version,
|
||||
},
|
||||
)
|
||||
|
||||
// Reload base to get updated managed app version info
|
||||
if (base.value?.id) {
|
||||
await baseStore.loadProject()
|
||||
}
|
||||
|
||||
await loadManagedAppAndCurrentVersion()
|
||||
|
||||
message.success(`New draft version ${forkForm.version} created successfully!`)
|
||||
|
||||
vVisible.value = false
|
||||
} catch (e: any) {
|
||||
message.error(await extractSdkResponseErrorMsg(e))
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
isDraft,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
forkForm.version = managedAppVersionsInfo.value.current?.version || '1.0.0'
|
||||
} else {
|
||||
forkForm.version = suggestManagedAppNextVersion(managedAppVersionsInfo.value.current?.version)
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col h-full">
|
||||
<DlgManagedAppHeader v-model:visible="vVisible" :title="title" :subTitle="subTitle" />
|
||||
|
||||
<div class="flex-1 p-6 nc-scrollbar-thin">
|
||||
<NcAlert
|
||||
type="info"
|
||||
align="top"
|
||||
class="!p-3 !items-start bg-nc-bg-blue-light border-1 !border-nc-blue-200 rounded-lg p-3 mb-4"
|
||||
>
|
||||
<template #icon>
|
||||
<GeneralIcon icon="info" class="w-4 h-4 mt-0.5 text-nc-content-blue-dark flex-none" />
|
||||
</template>
|
||||
|
||||
<template v-if="isDraft" #description>
|
||||
Publishing version <strong>{{ managedAppVersionsInfo.current?.version }}</strong> will make it available in the App
|
||||
Store and automatically update all installations.
|
||||
</template>
|
||||
<template v-else #description>
|
||||
Create a new draft version to work on updates. Current published version
|
||||
<strong>{{ managedAppVersionsInfo.current?.version }}</strong> will remain unchanged.
|
||||
</template>
|
||||
</NcAlert>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="text-nc-content-gray text-sm font-medium mb-2 block">
|
||||
<template v-if="isDraft"> Version </template>
|
||||
<template v-else> New Version <span class="text-nc-content-red-dark">*</span> </template>
|
||||
</label>
|
||||
<a-input
|
||||
v-model:value="forkForm.version"
|
||||
placeholder="e.g., 2.0.0"
|
||||
size="large"
|
||||
:disabled="isDraft"
|
||||
class="rounded-lg nc-input-sm nc-input-shadow"
|
||||
>
|
||||
<template #prefix>
|
||||
<span class="text-nc-content-gray-subtle2">v</span>
|
||||
</template>
|
||||
</a-input>
|
||||
<div v-if="!isDraft" class="text-xs text-nc-content-gray-subtle2 mt-1.5">
|
||||
Use semantic versioning (e.g., 2.0.0, 2.1.0)
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isDraft">
|
||||
<label class="text-nc-content-gray text-sm font-medium mb-2 block">Release Notes (Optional)</label>
|
||||
<a-textarea
|
||||
v-model:value="publishForm.releaseNotes"
|
||||
placeholder="Describe what's new in this version"
|
||||
:rows="6"
|
||||
size="large"
|
||||
class="rounded-lg nc-input-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nc-dlg-managed-app-footer">
|
||||
<div class="flex justify-end gap-2">
|
||||
<NcButton type="secondary" size="small" @click="vVisible = false">{{ $t('general.cancel') }} </NcButton>
|
||||
|
||||
<NcButton v-if="isDraft" type="primary" size="small" :loading="isLoading" @click="publishCurrentDraft">
|
||||
<template #icon>
|
||||
<GeneralIcon icon="upload" />
|
||||
</template>
|
||||
Publish
|
||||
</NcButton>
|
||||
|
||||
<NcButton v-else type="primary" size="small" :loading="isLoading" :disabled="!forkForm.version" @click="createNewDraft">
|
||||
<template #icon>
|
||||
<GeneralIcon icon="plus" />
|
||||
</template>
|
||||
Create Draft
|
||||
</NcButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nc-dlg-managed-app-footer {
|
||||
@apply px-6 py-3 border-t-1 border-nc-border-gray-medium;
|
||||
}
|
||||
</style>
|
||||
@@ -4,7 +4,7 @@ interface Props {
|
||||
modalSize: 'small' | 'medium' | 'large' | keyof typeof modalSizes
|
||||
title?: string
|
||||
subTitle?: string
|
||||
variant?: 'convertToManagedApp'
|
||||
variant?: 'draftOrPublish'
|
||||
contentClass?: string
|
||||
maskClosable?: boolean
|
||||
}
|
||||
@@ -19,7 +19,7 @@ const emits = defineEmits(['update:visible'])
|
||||
|
||||
const vVisible = useVModel(props, 'visible', emits)
|
||||
|
||||
const { modalSize } = toRefs(props)
|
||||
const { modalSize, variant } = toRefs(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -30,7 +30,10 @@ const { modalSize } = toRefs(props)
|
||||
:mask-closable="maskClosable"
|
||||
nc-modal-class-name="nc-modal-dlg-managed-app"
|
||||
>
|
||||
<slot v-if="$slots.default"> </slot>
|
||||
<template v-if="variant === 'draftOrPublish'">
|
||||
<DlgManagedAppDraftOrPublish v-model:visible="vVisible" />
|
||||
</template>
|
||||
<slot v-else-if="$slots.default"> </slot>
|
||||
<template v-else>
|
||||
<slot name="header">
|
||||
<NcDlgManagedAppHeader :visible="vVisible" :modalSize="modalSize" :title="title" :subTitle="subTitle" />
|
||||
|
||||
@@ -206,34 +206,6 @@ const modalSize = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabs (Segmented Control) -->
|
||||
<div class="nc-managed-app-tabs">
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
v-if="isDraft"
|
||||
class="nc-managed-app-tab"
|
||||
:class="{ selected: activeTab === 'publish' }"
|
||||
@click="activeTab = 'publish'"
|
||||
>
|
||||
<GeneralIcon icon="upload" class="h-4 w-4 flex-none opacity-75" />
|
||||
<span>Publish</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="isPublished"
|
||||
class="nc-managed-app-tab"
|
||||
:class="{ selected: activeTab === 'fork' }"
|
||||
@click="activeTab = 'fork'"
|
||||
>
|
||||
<GeneralIcon icon="ncGitBranch" class="h-4 w-4 flex-none opacity-75" />
|
||||
<span>Fork</span>
|
||||
</div>
|
||||
<div class="nc-managed-app-tab" :class="{ selected: activeTab === 'deployments' }" @click="activeTab = 'deployments'">
|
||||
<GeneralIcon icon="ncServer" class="h-4 w-4 flex-none opacity-75" />
|
||||
<span>Deployments</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NcButton size="small" type="text" @click="emit('update:visible', false)">
|
||||
<GeneralIcon icon="close" class="text-nc-content-gray-muted h-4 w-4" />
|
||||
</NcButton>
|
||||
|
||||
@@ -229,8 +229,12 @@ watch(
|
||||
</template>
|
||||
</NcDropdown>
|
||||
|
||||
<DlgManagedApp v-if="initialTab !== 'deployments'" v-model:visible="isModalVisible" modal-size="sm" variant="draftOrPublish">
|
||||
</DlgManagedApp>
|
||||
|
||||
<!-- Managed App Modal -->
|
||||
<SmartsheetTopbarManagedAppModal
|
||||
v-if="initialTab === 'deployments'"
|
||||
v-model:visible="isModalVisible"
|
||||
:managed-app="managedApp"
|
||||
:current-version="managedAppVersionsInfo.current"
|
||||
|
||||
Reference in New Issue
Block a user