mirror of https://github.com/nocodb/nocodb
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
179 lines
4.8 KiB
2 weeks ago
|
<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>
|