mirror of
https://github.com/nocodb/nocodb.git
synced 2026-02-01 23:48:33 +00:00
fix: use dropdown for version controling
This commit is contained in:
@@ -96,7 +96,7 @@ const { formState, isLoading, submit } = useProvideFormBuilderHelper({
|
||||
model: 'visibility',
|
||||
category: FORM_BUILDER_NON_CATEGORIZED,
|
||||
options: [
|
||||
{ label: 'Public', value: 'public', icon: 'eye' },
|
||||
// { label: 'Public', value: 'public', icon: 'eye' },
|
||||
{ label: 'Private', value: 'private', icon: 'lock' },
|
||||
{ label: 'Unlisted', value: 'unlisted', icon: 'ncEyeOff' },
|
||||
],
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
label: string
|
||||
subtext?: string
|
||||
icon?: IconMapKey
|
||||
iconWrapperClass?: string
|
||||
clickable?: boolean
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :tabindex="clickable ? 0 : undefined" class="nc-managed-app-status-menu-item" :class="{ 'nc-clickable': clickable }">
|
||||
<div class="nc-icon-wrapper" :class="iconWrapperClass">
|
||||
<slot name="icon">
|
||||
<GeneralIcon v-if="icon" :icon="icon" class="h-4 w-4 flex-none" />
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="nc-content-wrapper flex-1">
|
||||
<div v-if="$slots.label || label" class="nc-content-label">
|
||||
<slot name="label">{{ label }}</slot>
|
||||
</div>
|
||||
<div v-if="$slots.subtext || subtext" class="nc-content-subtext">
|
||||
<slot name="subtext">{{ subtext }}</slot>
|
||||
</div>
|
||||
</div>
|
||||
<slot name="extraRight"> </slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nc-managed-app-status-menu-item {
|
||||
@apply flex items-center gap-3 px-3 py-2.5 my-0.5 mx-2 rounded-lg transition-colors group;
|
||||
|
||||
&.nc-clickable {
|
||||
@apply cursor-pointer select-none hover:bg-nc-bg-gray-extralight;
|
||||
}
|
||||
}
|
||||
.nc-icon-wrapper {
|
||||
@apply w-8 h-8 rounded-lg flex items-center justify-center children:flex-none;
|
||||
}
|
||||
|
||||
.nc-content-label {
|
||||
@apply text-caption font-600 text-nc-content-gray-subtle2;
|
||||
}
|
||||
|
||||
.nc-content-subtext {
|
||||
@apply text-captionSm text-nc-content-gray-muted;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,240 @@
|
||||
<script setup lang="ts">
|
||||
const baseStore = useBase()
|
||||
|
||||
const { loadManagedApp, loadCurrentVersion } = baseStore
|
||||
|
||||
const { base, isManagedAppMaster, isManagedAppInstaller, managedApp, currentVersion, liveVersion } = storeToRefs(baseStore)
|
||||
|
||||
const isModalVisible = ref(false)
|
||||
const initialTab = ref<'publish' | 'fork' | 'deployments' | undefined>(undefined)
|
||||
|
||||
const isOpenDropdown = ref<boolean>(false)
|
||||
|
||||
const isDraft = computed(() => currentVersion.value?.status === 'draft')
|
||||
|
||||
const openModal = (tab?: 'publish' | 'fork' | 'deployments') => {
|
||||
initialTab.value = tab
|
||||
isModalVisible.value = true
|
||||
}
|
||||
|
||||
const loadManagedAppAndCurrentVersion = async () => {
|
||||
await loadManagedApp()
|
||||
await loadCurrentVersion()
|
||||
}
|
||||
|
||||
const handlePublished = async () => {
|
||||
await loadManagedAppAndCurrentVersion()
|
||||
}
|
||||
|
||||
const handleForked = async () => {
|
||||
await loadManagedAppAndCurrentVersion()
|
||||
}
|
||||
|
||||
watch(
|
||||
() => (base.value as any)?.managed_app_id,
|
||||
async (managedAppId) => {
|
||||
if (!managedAppId) return
|
||||
|
||||
await loadManagedAppAndCurrentVersion()
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
watchEffect(() => {
|
||||
console.log('managed App', managedApp.value)
|
||||
console.log('currentVersion', currentVersion.value)
|
||||
console.log('liveVersion', liveVersion.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NcDropdown
|
||||
v-if="isManagedAppMaster || isManagedAppInstaller"
|
||||
v-model:visible="isOpenDropdown"
|
||||
placement="bottomRight"
|
||||
overlay-class-name="!rounded-xl"
|
||||
>
|
||||
<div class="flex items-center gap-2" @click="openModal()">
|
||||
<!-- Version Badge (clickable to open modal) -->
|
||||
<div
|
||||
class="flex items-center gap-1.5 px-2.5 py-1 bg-nc-bg-gray-light rounded-md border-1 border-nc-border-gray-medium cursor-pointer hover:(bg-nc-bg-gray-medium border-nc-border-gray-dark) transition-colors"
|
||||
>
|
||||
<GeneralIcon icon="ncInfoSolid" class="w-3.5 h-3.5 text-nc-content-gray nc-managed-app-status-info-icon" />
|
||||
<span class="text-xs font-mono font-semibold text-nc-content-gray-emphasis"
|
||||
>v{{ currentVersion?.version || '1.0.0' }}</span
|
||||
>
|
||||
<div
|
||||
v-if="currentVersion?.status === 'draft'"
|
||||
class="ml-1 px-1.5 py-0.5 text-xs rounded bg-nc-bg-orange-light text-nc-content-orange-dark font-medium"
|
||||
>
|
||||
{{ $t('labels.draft') }}
|
||||
</div>
|
||||
<div
|
||||
v-else-if="currentVersion?.status === 'published'"
|
||||
class="ml-1 px-1.5 py-0.5 text-xs rounded bg-nc-bg-green-dark text-nc-content-green-dark font-medium"
|
||||
>
|
||||
{{ $t('labels.published') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #overlay>
|
||||
<div class="nc-managed-app-status-menu flex flex-col">
|
||||
<div class="nc-managed-app-status-menu-header">
|
||||
<span class="uppercase">{{ isManagedAppInstaller ? 'Installed Version' : 'Current State' }}</span>
|
||||
<span v-if="currentVersion?.status === 'draft' && liveVersion">Live: v{{ liveVersion.version }} </span>
|
||||
</div>
|
||||
|
||||
<!-- Publisher application -->
|
||||
<template v-if="isManagedAppMaster">
|
||||
<!-- Live state -->
|
||||
<template v-if="liveVersion && !isDraft">
|
||||
<SmartsheetTopbarManagedAppStatusMenuItem
|
||||
:label="`v${liveVersion.version || '1.0.0'}`"
|
||||
icon-wrapper-class="bg-green-50 dark:bg-nc-green-20"
|
||||
>
|
||||
<template #icon>
|
||||
<GeneralIcon icon="circleCheck3" class="text-green-600" />
|
||||
</template>
|
||||
<template #subtext>
|
||||
<span class="text-green-600"> Live & Serving Users </span>
|
||||
</template>
|
||||
</SmartsheetTopbarManagedAppStatusMenuItem>
|
||||
|
||||
<NcDivider />
|
||||
<SmartsheetTopbarManagedAppStatusMenuItem
|
||||
clickable
|
||||
label="Fork to Draft"
|
||||
:subtext="`Create v${liveVersion.version || '1.0.0'} to make changes`"
|
||||
icon-wrapper-class="bg-nc-bg-gray-light dakr:bg-nc-bg-gray-light/75"
|
||||
>
|
||||
<template #icon>
|
||||
<GeneralIcon icon="ncCopy" class="text-nc-content-gray-muted" />
|
||||
</template>
|
||||
</SmartsheetTopbarManagedAppStatusMenuItem>
|
||||
</template>
|
||||
|
||||
<!-- Draft state -->
|
||||
<template v-if="isDraft">
|
||||
<SmartsheetTopbarManagedAppStatusMenuItem
|
||||
:label="`v${currentVersion.version || '1.0.0'}`"
|
||||
icon-wrapper-class="bg-orange-50 dark:bg-nc-orange-20"
|
||||
>
|
||||
<template #icon>
|
||||
<GeneralIcon icon="edit" class="text-orange-600" />
|
||||
</template>
|
||||
<template #subtext>
|
||||
<span class="text-orange-600"> Editing Draft </span>
|
||||
</template>
|
||||
</SmartsheetTopbarManagedAppStatusMenuItem>
|
||||
<NcDivider />
|
||||
|
||||
<SmartsheetTopbarManagedAppStatusMenuItem clickable icon-wrapper-class="bg-green-50 dark:bg-nc-green-20">
|
||||
<template #icon>
|
||||
<GeneralIcon icon="ncArrowUp" class="text-green-600" />
|
||||
</template>
|
||||
<template #label>
|
||||
<span class="text-green-600"> Publish v{{ currentVersion.version || '1.0.0' }} </span>
|
||||
</template>
|
||||
<template #subtext>
|
||||
{{ liveVersion ? `Replace v${liveVersion.version || '1.0.0'} and go live` : `Go live` }}
|
||||
</template>
|
||||
</SmartsheetTopbarManagedAppStatusMenuItem>
|
||||
</template>
|
||||
|
||||
<!-- Initial draft state -->
|
||||
<SmartsheetTopbarManagedAppStatusMenuItem
|
||||
v-if="liveVersion && isDraft"
|
||||
clickable
|
||||
label="Discard Draft"
|
||||
:subtext="`Return to v${liveVersion.version || '1.0.0'}`"
|
||||
icon-wrapper-class="bg-nc-bg-gray-light"
|
||||
>
|
||||
<template #icon>
|
||||
<GeneralIcon icon="delete" class="text-nc-content-gray-muted" />
|
||||
</template>
|
||||
</SmartsheetTopbarManagedAppStatusMenuItem>
|
||||
<NcDivider />
|
||||
|
||||
<!-- Version history -->
|
||||
<div class="flex items-center gap-2 px-5 py-2 text-captionSm text-nc-content-gray-muted cursor-pointer select-none">
|
||||
<GeneralIcon icon="ncClock" />
|
||||
View version history
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Installer application -->
|
||||
<template v-if="isManagedAppInstaller">
|
||||
<SmartsheetTopbarManagedAppStatusMenuItem
|
||||
:label="`v${liveVersion?.version || '1.0.0'}`"
|
||||
icon-wrapper-class="bg-green-50 dark:bg-nc-green-20"
|
||||
>
|
||||
<template #icon>
|
||||
<GeneralIcon icon="circleCheck3" class="text-green-600" />
|
||||
</template>
|
||||
|
||||
<template #subtext>
|
||||
<span class="text-green-600">
|
||||
<!-- Todo: @rameshmane7218 - Update text -->
|
||||
Installed Jan 10, 2025
|
||||
</span>
|
||||
</template>
|
||||
</SmartsheetTopbarManagedAppStatusMenuItem>
|
||||
|
||||
<div class="bg-nc-brand-20 dark:bg-nc-brand-20/40 -mb-1.5">
|
||||
<SmartsheetTopbarManagedAppStatusMenuItem
|
||||
:label="`v${liveVersion?.version || '1.0.0'}`"
|
||||
icon-wrapper-class="bg-brand-50 dark:bg-nc-brand-50"
|
||||
>
|
||||
<template #icon>
|
||||
<GeneralIcon icon="ncDownload" class="text-brand-600" />
|
||||
</template>
|
||||
|
||||
<template #subtext>
|
||||
<span class="text-brand-600"> New version available </span>
|
||||
</template>
|
||||
<template #extraRight>
|
||||
<NcButton size="small"> Update </NcButton>
|
||||
</template>
|
||||
</SmartsheetTopbarManagedAppStatusMenuItem>
|
||||
</div>
|
||||
|
||||
<NcDivider />
|
||||
<SmartsheetTopbarManagedAppStatusMenuItem
|
||||
clickable
|
||||
label="View Changelog"
|
||||
subtext="See what's new in each version"
|
||||
icon-wrapper-class="bg-nc-bg-gray-light"
|
||||
>
|
||||
<template #icon>
|
||||
<GeneralIcon icon="file" class="text-nc-content-gray-muted" />
|
||||
</template>
|
||||
</SmartsheetTopbarManagedAppStatusMenuItem>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</NcDropdown>
|
||||
|
||||
<!-- Managed App Modal -->
|
||||
<SmartsheetTopbarManagedAppModal
|
||||
v-model:visible="isModalVisible"
|
||||
:managed-app="managedApp"
|
||||
:current-version="currentVersion"
|
||||
:initial-tab="initialTab"
|
||||
@published="handlePublished"
|
||||
@forked="handleForked"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.nc-managed-app-status-info-icon path.nc-icon-inner) {
|
||||
stroke: var(--nc-bg-gray-light) !important;
|
||||
}
|
||||
|
||||
.nc-managed-app-status-menu {
|
||||
@apply w-[318px] pb-2;
|
||||
}
|
||||
|
||||
.nc-managed-app-status-menu-header {
|
||||
@apply flex items-center justify-between gap-2 pt-3 px-5 mb-1 text-nc-content-gray-muted text-captionSm;
|
||||
}
|
||||
</style>
|
||||
@@ -168,7 +168,7 @@ const { formState, isLoading, submit } = useProvideFormBuilderHelper({
|
||||
model: 'visibility',
|
||||
category: FORM_BUILDER_NON_CATEGORIZED,
|
||||
options: [
|
||||
{ label: 'Public', value: 'public', icon: 'eye' },
|
||||
// { label: 'Public', value: 'public', icon: 'eye' },
|
||||
{ label: 'Private', value: 'private', icon: 'lock' },
|
||||
{ label: 'Unlisted', value: 'unlisted', icon: 'ncEyeOff' },
|
||||
],
|
||||
|
||||
@@ -18,8 +18,16 @@ export const useBase = defineStore('baseStore', () => {
|
||||
|
||||
const basesStore = useBases()
|
||||
|
||||
const managedApp = ref<any>(null)
|
||||
|
||||
const currentVersion = ref<any>(null)
|
||||
|
||||
const liveVersion = ref<any>(null)
|
||||
|
||||
const isManagedAppMaster = ref(false)
|
||||
|
||||
const isManagedAppInstaller = ref(false)
|
||||
|
||||
const baseId = computed(() => {
|
||||
// In shared base mode, use activeProjectId from basesStore which has the correct base ID
|
||||
if (route.value.params.typeOrId === 'base') {
|
||||
@@ -268,6 +276,10 @@ export const useBase = defineStore('baseStore', () => {
|
||||
return `${basUrl}${projectPage ? `?page=${projectPage}` : ''}`
|
||||
}
|
||||
|
||||
const loadManagedApp = async () => {}
|
||||
|
||||
const loadCurrentVersion = async () => {}
|
||||
|
||||
watch(
|
||||
() => route.value.params.baseType,
|
||||
(n) => {
|
||||
@@ -343,6 +355,12 @@ export const useBase = defineStore('baseStore', () => {
|
||||
isPrivateBase,
|
||||
showBaseAccessRequestOverlay,
|
||||
isManagedAppMaster,
|
||||
isManagedAppInstaller,
|
||||
managedApp,
|
||||
loadManagedApp,
|
||||
currentVersion,
|
||||
liveVersion,
|
||||
loadCurrentVersion,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user