多维表格
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.

179 lines
4.8 KiB

<script lang="ts" setup>
import { IntegrationCategoryType, type SyncDataType } from '#imports'
import { clientTypes as _clientTypes } from '#imports'
const props = defineProps<{
open: boolean
integrationType: IntegrationCategoryType
integrationSubType: SyncDataType
}>()
const emit = defineEmits(['update:open'])
const vOpen = useVModel(props, 'open', emit)
const {
isFromIntegrationPage,
pageMode,
IntegrationsPageMode,
activeIntegration,
activeIntegrationItem,
saveIntegration,
updateIntegration,
} = useIntegrationStore()
const { loadAiIntegrations } = useNocoAi()
const isEditMode = computed(() => pageMode.value === IntegrationsPageMode.EDIT)
const initState = ref({
type: props.integrationType,
sub_type: props.integrationSubType,
})
const { form, formState, isLoading, initialState, submit } = useProvideFormBuilderHelper({
formSchema: activeIntegrationItem.value?.form,
initialState: initState,
onSubmit: async () => {
// if it is edit mode and activeIntegration id is not present then return
if (isEditMode.value && !activeIntegration.value?.id) return
isLoading.value = true
try {
if (pageMode.value === IntegrationsPageMode.ADD) {
await saveIntegration(formState.value)
if (props.integrationType === IntegrationCategoryType.AI) {
loadAiIntegrations()
}
} else {
await updateIntegration({
id: activeIntegration.value?.id,
...formState.value,
})
}
} catch (e) {
console.error(e)
} finally {
isLoading.value = false
}
},
})
// select and focus title field on load
onMounted(async () => {
isLoading.value = true
if (pageMode.value === IntegrationsPageMode.ADD) {
formState.value.title = activeIntegration.value?.title || ''
} else {
if (!activeIntegration.value) return
formState.value = {
title: activeIntegration.value.title || '',
config: activeIntegration.value.config,
is_private: !!activeIntegration.value?.is_private,
...initState.value,
}
initialState.value = JSON.parse(JSON.stringify(formState.value))
}
nextTick(() => {
// todo: replace setTimeout and follow better approach
setTimeout(() => {
const input = form.value?.$el?.querySelector('input[type=text]')
input?.setSelectionRange(0, formState.value.title.length)
input?.focus()
}, 500)
})
isLoading.value = false
})
</script>
<template>
<div v-if="activeIntegration" class="h-full">
<div class="p-4 w-full flex items-center justify-between gap-3 border-b-1 border-gray-200">
<div class="flex-1 flex items-center gap-3">
<NcButton
v-if="!isEditMode && !isFromIntegrationPage"
type="text"
size="small"
@click="pageMode = IntegrationsPageMode.LIST"
>
<GeneralIcon icon="arrowLeft" />
</NcButton>
<WorkspaceIntegrationsIcon :integration-item="activeIntegrationItem" size="xs" />
<div class="flex-1 text-base font-weight-700">{{ activeIntegration?.title }}</div>
</div>
<div class="flex items-center gap-3">
<NcButton
size="small"
type="primary"
:disabled="isLoading"
:loading="isLoading"
class="nc-extdb-btn-submit"
@click="submit"
>
{{ pageMode === IntegrationsPageMode.ADD ? 'Create integration' : 'Update integration' }}
</NcButton>
<NcButton size="small" type="text" @click="vOpen = false">
<GeneralIcon icon="close" class="text-gray-600" />
</NcButton>
</div>
</div>
<div class="h-[calc(100%_-_66px)] flex">
<div class="nc-edit-or-add-integration-left-panel nc-scrollbar-thin relative !px-4">
<div class="w-full gap-4 max-w-[784px]">
<div class="nc-edit-or-add-integration bg-white relative flex flex-col justify-center gap-2 w-full">
<NcFormBuilder class="px-2" />
<div class="mt-10"></div>
</div>
</div>
</div>
<div class="nc-edit-or-add-integration-right-panel">
<WorkspaceIntegrationsSupportedDocs />
<NcDivider />
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.nc-form-item {
padding-right: 24px;
margin-bottom: 12px;
}
:deep(.ant-collapse-header) {
@apply !-mt-4 !p-0 flex items-center !cursor-default children:first:flex;
}
:deep(.ant-collapse-icon-position-right > .ant-collapse-item > .ant-collapse-header .ant-collapse-arrow) {
@apply !right-0;
}
:deep(.ant-collapse-content-box) {
@apply !px-0 !pb-0 !pt-3;
}
:deep(.ant-form-item-explain-error) {
@apply !text-xs;
}
:deep(.ant-divider) {
@apply m-0;
}
:deep(.ant-form-item-with-help .ant-form-item-explain) {
@apply !min-h-0;
}
:deep(.ant-select .ant-select-selector .ant-select-selection-item) {
@apply font-weight-400;
}
</style>
<style lang="scss"></style>