多维表格
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
7.3 KiB

<script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core'
import type { ViewType } from 'nocodb-sdk'
import { viewTypeAlias } from 'nocodb-sdk'
import { LockType } from '#imports'
const props = defineProps<{
modelValue?: boolean
view?: ViewType
changeType?: LockType
}>()
const emits = defineEmits(['update:modelValue'])
const dialogShow = useVModel(props, 'modelValue', emits, { defaultValue: false })
const isForm = inject(IsFormInj, ref(false))
const { $api, $e } = useNuxtApp()
const { isUIAllowed } = useRoles()
const { user } = useGlobal()
const { idUserMap } = storeToRefs(useBase())
const { activeView } = storeToRefs(useViewsStore())
const view = computed(() => props.view || activeView.value)
const changeType = computed(() =>
view.value?.lock_type !== LockType.Locked ? LockType.Locked : props.changeType || LockType.Collaborative,
)
const focusInput: VNodeRef = (el) => el && el?.focus?.()
const formValidator = ref()
const isErrored = ref(false)
const form = reactive({
description: '',
})
const formRules = {
description: [{ max: 1000, message: 'Value must be at most 1000 characters long' }],
}
const isLoading = ref(false)
const changeLockType = async () => {
if (!view.value) return
if (changeType.value === LockType.Locked) {
const valid = await formValidator.value.validate()
if (!valid) return
}
const payload = {
lockedViewDescription: changeType.value === LockType.Locked ? form.description : '',
lockedByUserId: changeType.value === LockType.Locked ? user.value?.id : '',
}
isLoading.value = true
try {
await $api.dbView.update(view.value.id as string, {
lock_type: changeType.value,
meta: {
...parseProp(view.value.meta),
...payload,
},
})
view.value.meta = {
...parseProp(view.value.meta),
...payload,
}
view.value.lock_type = changeType.value
message.success(`Successfully Switched to ${view.value.lock_type} view`)
$e(`a:${viewTypeAlias[view.value.type] || 'view'}:lock`, { lockType: view.value.lock_type, title: view.value.title })
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
} finally {
dialogShow.value = false
isLoading.value = false
}
}
onKeyStroke('Enter', () => {
if (isLoading.value || !dialogShow.value || isForm.value || !(changeType.value !== LockType.Locked)) return
changeLockType()
})
watch(dialogShow, (newValue) => {
if (!newValue) {
form.description = ''
isErrored.value = false
}
})
watch(
() => form.description,
async () => {
if (changeType.value !== LockType.Locked) return
try {
isErrored.value = !(await formValidator.value.validate())
} catch (e: any) {
isErrored.value = true
}
},
)
</script>
<template>
<div v-if="isForm" class="nc-unlock-view-wrapper rounded-2xl bg-white p-6 w-full max-w-[384px] flex flex-col gap-5">
<div class="flex flex-col gap-2">
<div class="text-base font-bold text-nc-content-gray-emphasis">
{{ $t('title.thisFormIsLocked') }}
</div>
<div v-if="view?.meta?.lockedViewDescription" class="text-sm bg-nc-bg-gray-light rounded-lg px-2 py-2">
{{ view?.meta?.lockedViewDescription }}
</div>
<div class="text-sm text-nc-content-gray">{{ $t('title.unlockThisVieToMakeChanges') }}</div>
<div class="text-sm text-nc-content-gray">
{{ $t('title.unlockViewTitleSubtitle') }}
<span v-if="idUserMap[view?.meta?.lockedByUserId]?.id === user.id" class="font-bold"> {{ t('general.you') }} </span>
<span v-else class="font-bold">
{{ idUserMap[view?.meta?.lockedByUserId]?.display_name || idUserMap[view?.meta?.lockedByUserId]?.email }}
</span>
</div>
</div>
<NcButton
v-if="isUIAllowed('fieldAdd')"
type="secondary"
size="small"
class="!w-full"
:loading="isLoading"
:disabled="isLoading"
@click="changeLockType"
>
<template #icon>
<GeneralIcon icon="ncUnlock" class="flex-none" />
</template>
{{ $t('labels.unlockView') }}
</NcButton>
</div>
<NcModal
v-else
v-model:visible="dialogShow"
:show-separator="false"
:header="$t('activity.createTable')"
size="small"
wrap-class-name="nc-lock-view-modal-wrapper"
@keydown.esc="dialogShow = false"
>
<template v-if="changeType === LockType.Locked" #header>
<div class="flex flex-col gap-2 w-full">
<div class="text-base font-bold text-nc-content-gray-emphasis">
{{ $t('title.lockThisView') }}
</div>
<div class="text-sm font-normal text-nc-content-gray-subtle">
{{ $t('title.lockThisViewSubtle') }}
</div>
</div>
</template>
<a-form
ref="formValidator"
:model="form"
layout="vertical"
name="create-new-table-form"
class="flex flex-col gap-5 !mt-1 font-normal"
@finish="changeLockType"
>
<div v-if="changeType === LockType.Locked" class="flex flex-col gap-5">
<a-form-item name="description" :rules="formRules.description">
<a-textarea
:ref="focusInput"
v-model:value="form.description"
class="!rounded-lg !text-sm nc-input-shadow !min-h-[120px] max-h-[500px] nc-scrollbar-thin"
size="large"
hide-details
data-testid="nc-lock-view-description-input"
:placeholder="$t('placeholder.lockViewDescription')"
/>
</a-form-item>
</div>
<div v-else class="flex flex-col gap-2">
<div class="text-base font-bold text-nc-content-gray-emphasis">
{{ $t('title.unlockViewTitle') }}
</div>
<div v-if="view?.meta?.lockedViewDescription" class="text-sm bg-nc-bg-gray-light rounded-lg px-2 py-2">
{{ view?.meta?.lockedViewDescription }}
</div>
<div class="text-sm text-nc-content-gray">
{{ $t('title.unlockViewTitleSubtitle') }}
<span v-if="idUserMap[view?.meta?.lockedByUserId]?.id === user.id" class="font-bold"> {{ $t('general.you') }} </span>
<span v-else class="font-bold">
{{ idUserMap[view?.meta?.lockedByUserId]?.display_name || idUserMap[view?.meta?.lockedByUserId]?.email }}
</span>
</div>
</div>
<div class="flex gap-2 items-center justify-end">
<NcButton type="secondary" size="small" :disabled="isLoading" data-testid="nc-cancel-btn" @click="dialogShow = false">{{
$t('general.cancel')
}}</NcButton>
<NcButton
type="primary"
html-type="submit"
size="small"
:loading="isLoading"
:disabled="isLoading || isErrored"
data-testid="nc-lock-or-unlock-btn"
>
<template #icon>
<GeneralIcon :icon="changeType === LockType.Locked ? 'ncLock' : 'ncUnlock'" class="flex-none" />
</template>
<div
class="flex"
:class="{
'-ml-1': !isLoading,
}"
>
{{ changeType === LockType.Locked ? $t('labels.lockView') : $t('labels.unlockView') }}
</div>
</NcButton>
</div>
</a-form>
</NcModal>
</template>
<style scoped lang="scss">
.ant-form-item {
@apply mb-0;
}
.nc-unlock-view-wrapper {
box-shadow: 0px 8px 8px -4px rgba(0, 0, 0, 0.04), 0px 20px 24px -4px rgba(0, 0, 0, 0.1);
}
</style>