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.
357 lines
9.5 KiB
357 lines
9.5 KiB
import type { IntegrationType, PaginatedType } from 'nocodb-sdk' |
|
import { IntegrationsType } from 'nocodb-sdk' |
|
import { ClientType } from '../lib/enums' |
|
import GeneralBaseLogo from '~/components/general/BaseLogo.vue' |
|
import type { IntegrationStoreEvents as IntegrationStoreEventsTypes } from '#imports' |
|
|
|
enum IntegrationsPageMode { |
|
LIST, |
|
ADD, |
|
EDIT, |
|
} |
|
|
|
const integrationType: Record<'PostgreSQL' | 'MySQL', ClientType> = { |
|
PostgreSQL: ClientType.PG, |
|
MySQL: ClientType.MYSQL, |
|
} |
|
|
|
type IntegrationsSubType = (typeof integrationType)[keyof typeof integrationType] |
|
|
|
function defaultValues(type: IntegrationsSubType) { |
|
const genericValues = { |
|
payload: {}, |
|
} |
|
|
|
switch (type) { |
|
case integrationType.PostgreSQL: |
|
return { |
|
...genericValues, |
|
type: integrationType.PostgreSQL, |
|
title: 'PostgreSQL', |
|
logo: h(GeneralBaseLogo, { |
|
'source-type': 'pg', |
|
'class': 'logo', |
|
}), |
|
} |
|
case integrationType.MySQL: |
|
return { |
|
...genericValues, |
|
type: integrationType.MySQL, |
|
title: 'MySQL', |
|
logo: h(GeneralBaseLogo, { |
|
'source-type': 'mysql2', |
|
'class': 'logo', |
|
}), |
|
} |
|
} |
|
} |
|
|
|
const [useProvideIntegrationViewStore, _useIntegrationStore] = useInjectionState(() => { |
|
const router = useRouter() |
|
const route = router.currentRoute |
|
|
|
const { api } = useApi() |
|
const pageMode = ref<IntegrationsPageMode | null>(null) |
|
const activeIntegration = ref<IntegrationType | null>(null) |
|
|
|
const workspaceStore = useWorkspace() |
|
const { activeWorkspaceId } = storeToRefs(workspaceStore) |
|
|
|
const integrations = ref<IntegrationType[]>([]) |
|
|
|
const searchQuery = ref('') |
|
|
|
const integrationPaginationData = ref<PaginatedType>({ page: 1, pageSize: 25, totalRows: 0 }) |
|
|
|
const deleteConfirmText = ref<string | null>() |
|
|
|
const isLoadingIntegrations = ref(false) |
|
|
|
const eventBus = useEventBus<IntegrationStoreEventsTypes>(Symbol('integrationStore')) |
|
|
|
const { $e } = useNuxtApp() |
|
|
|
const { t } = useI18n() |
|
|
|
const isFromIntegrationPage = ref(false) |
|
|
|
const successConfirmModal = ref({ |
|
isOpen: false, |
|
title: t('msg.success.connectionAdded'), |
|
connectionTitle: '', |
|
description: t('msg.success.connectionAddedDesc'), |
|
}) |
|
|
|
const requestIntegration = ref({ |
|
isOpen: false, |
|
msg: '', |
|
isLoading: false, |
|
}) |
|
|
|
const activeViewTab = computed({ |
|
get() { |
|
return (route.value.query?.tab as string) ?? 'integrations' |
|
}, |
|
set(tab: string) { |
|
if (requestIntegration.value.isOpen) { |
|
requestIntegration.value.isOpen = false |
|
} |
|
|
|
router.push({ query: { ...route.value.query, tab } }) |
|
}, |
|
}) |
|
|
|
const loadIntegrations = async ( |
|
databaseOnly = false, |
|
baseId = undefined, |
|
page: number = integrationPaginationData.value.page!, |
|
limit: number = integrationPaginationData.value.pageSize!, |
|
) => { |
|
try { |
|
if (!activeWorkspaceId.value) return |
|
isLoadingIntegrations.value = true |
|
|
|
if (!databaseOnly && limit * (page - 1) > integrationPaginationData.value.totalRows!) { |
|
integrationPaginationData.value.page = 1 |
|
page = 1 |
|
} |
|
|
|
const { list, pageInfo } = await api.integration.list( |
|
databaseOnly |
|
? { |
|
type: IntegrationsType.Database, |
|
includeDatabaseInfo: true, |
|
baseId, |
|
} |
|
: { |
|
offset: limit * (page - 1), |
|
limit, |
|
...(searchQuery.value.trim() ? { query: searchQuery.value } : {}), |
|
}, |
|
) |
|
|
|
integrations.value = list |
|
if (!databaseOnly) { |
|
integrationPaginationData.value.totalRows = pageInfo.totalRows ?? 0 |
|
} |
|
} catch (e) { |
|
await message.error(await extractSdkResponseErrorMsg(e)) |
|
integrations.value = [] |
|
integrationPaginationData.value.totalRows = 0 |
|
integrationPaginationData.value.page = 1 |
|
} finally { |
|
isLoadingIntegrations.value = false |
|
} |
|
} |
|
const addIntegration = (type: IntegrationsSubType) => { |
|
activeIntegration.value = defaultValues(type) |
|
pageMode.value = IntegrationsPageMode.ADD |
|
$e('c:integration:add') |
|
} |
|
|
|
const deleteIntegration = async (integration: IntegrationType, force = false) => { |
|
if (!integration?.id) return |
|
|
|
try { |
|
await api.integration.delete(integration.id, { |
|
query: force ? { force: 'true' } : {}, |
|
}) |
|
|
|
$e('a:integration:delete') |
|
await loadIntegrations() |
|
|
|
// await message.success(`Connection ${integration.title} deleted successfully`) |
|
|
|
return true |
|
} catch (e) { |
|
const error = await extractSdkResponseErrorMsgv2(e) |
|
|
|
if (error.error === NcErrorType.INTEGRATION_NOT_FOUND) { |
|
await message.error(error.message?.replace(integration.id, integration.title!)) |
|
window.location.reload() |
|
return |
|
} |
|
|
|
await message.error(await extractSdkResponseErrorMsg(e)) |
|
} |
|
deleteConfirmText.value = null |
|
} |
|
|
|
const updateIntegration = async (integration: IntegrationType) => { |
|
if (!integration.id) return |
|
|
|
try { |
|
await api.integration.update(integration.id, integration) |
|
|
|
$e('a:integration:update') |
|
await loadIntegrations() |
|
|
|
pageMode.value = null |
|
activeIntegration.value = null |
|
|
|
await message.success(`Connection "${integration.title}" updated successfully`) |
|
} catch (e) { |
|
await message.error(await extractSdkResponseErrorMsg(e)) |
|
} |
|
} |
|
|
|
const saveIntegration = async ( |
|
integration: IntegrationType, |
|
mode: 'create' | 'duplicate' = 'create', |
|
loadDatasourceInfo = false, |
|
baseId: string | undefined = undefined, |
|
) => { |
|
try { |
|
const response = await api.integration.create(integration) |
|
if (mode === 'create') { |
|
$e('a:integration:create') |
|
} else { |
|
$e('a:integration:duplicate') |
|
} |
|
|
|
if (response && response?.id) { |
|
if (!loadDatasourceInfo) { |
|
integrations.value.push(response) |
|
} |
|
} |
|
|
|
await loadIntegrations(loadDatasourceInfo, baseId) |
|
|
|
if (mode === 'create') { |
|
eventBus.emit(IntegrationStoreEvents.INTEGRATION_ADD, response) |
|
} |
|
|
|
pageMode.value = null |
|
activeIntegration.value = null |
|
|
|
if (response?.title && mode === 'create') { |
|
if (isFromIntegrationPage.value) { |
|
activeViewTab.value = 'connections' |
|
|
|
successConfirmModal.value.connectionTitle = response.title ?? '' |
|
successConfirmModal.value.isOpen = true |
|
} else { |
|
await message.success(`Connection "${response.title}" created successfully`) |
|
} |
|
} |
|
} catch (e) { |
|
await message.error(await extractSdkResponseErrorMsg(e)) |
|
} |
|
} |
|
|
|
const duplicateIntegration = async (integration: IntegrationType) => { |
|
if (!integration?.id) return |
|
|
|
try { |
|
isLoadingIntegrations.value = true |
|
|
|
saveIntegration( |
|
{ |
|
title: integration.title, |
|
config: {}, |
|
type: integration.type, |
|
copy_from_id: integration.id, |
|
}, |
|
'duplicate', |
|
) |
|
} catch (e) { |
|
await message.error(await extractSdkResponseErrorMsg(e)) |
|
} finally { |
|
isLoadingIntegrations.value = false |
|
} |
|
} |
|
|
|
const getIntegration = async ( |
|
integration: IntegrationType, |
|
options?: { |
|
includeConfig?: boolean |
|
includeSources?: boolean |
|
}, |
|
) => { |
|
if (!integration?.id) return |
|
|
|
try { |
|
const integrationWithConfig = await api.integration.read(integration.id, { |
|
...(options || {}), |
|
}) |
|
return integrationWithConfig |
|
} catch (e) { |
|
const error = await extractSdkResponseErrorMsgv2(e) |
|
|
|
if (error.error === NcErrorType.INTEGRATION_NOT_FOUND) { |
|
await message.error(error.message?.replace(integration.id!, integration.title!)) |
|
window.location.reload() |
|
return |
|
} |
|
await message.error(await extractSdkResponseErrorMsg(e)) |
|
} |
|
} |
|
|
|
const editIntegration = async (integration: IntegrationType) => { |
|
if (!integration?.id) return |
|
|
|
try { |
|
const integrationWithConfig = await getIntegration(integration, { includeConfig: true }) |
|
activeIntegration.value = integrationWithConfig |
|
pageMode.value = IntegrationsPageMode.EDIT |
|
|
|
$e('c:integration:edit') |
|
} catch {} |
|
} |
|
|
|
const saveIntegraitonRequest = async (msg: string) => { |
|
if (!msg?.trim()) return |
|
|
|
requestIntegration.value.isLoading = true |
|
try { |
|
$e('a:integration:new-request', { |
|
value: requestIntegration.value.msg, |
|
}) |
|
|
|
requestIntegration.value.isLoading = false |
|
requestIntegration.value.isOpen = false |
|
requestIntegration.value.msg = '' |
|
|
|
await message.success('Your request has been successfully submitted') |
|
} catch (e) { |
|
requestIntegration.value.isLoading = false |
|
await message.error(await extractSdkResponseErrorMsg(e)) |
|
} |
|
} |
|
|
|
return { |
|
IntegrationsPageMode, |
|
integrationType, |
|
pageMode, |
|
activeIntegration, |
|
integrations, |
|
isLoadingIntegrations, |
|
deleteConfirmText, |
|
eventBus, |
|
requestIntegration, |
|
integrationPaginationData, |
|
activeViewTab, |
|
isFromIntegrationPage, |
|
successConfirmModal, |
|
searchQuery, |
|
addIntegration, |
|
loadIntegrations, |
|
deleteIntegration, |
|
updateIntegration, |
|
saveIntegration, |
|
editIntegration, |
|
duplicateIntegration, |
|
saveIntegraitonRequest, |
|
getIntegration, |
|
} |
|
}, 'integrations-store') |
|
|
|
export { useProvideIntegrationViewStore } |
|
|
|
export function useIntegrationStore() { |
|
const integrationStore = _useIntegrationStore() |
|
|
|
if (integrationStore == null) return useProvideIntegrationViewStore() |
|
|
|
return integrationStore |
|
}
|
|
|