| import cn from '@/utils/classnames' | |||||
| import React, { useMemo } from 'react' | |||||
| type CredentialIconProps = { | |||||
| avatar_url?: string | |||||
| name: string | |||||
| size?: number | |||||
| className?: string | |||||
| } | |||||
| const ICON_BG_COLORS = [ | |||||
| 'bg-components-icon-bg-orange-dark-solid', | |||||
| 'bg-components-icon-bg-pink-solid', | |||||
| 'bg-components-icon-bg-indigo-solid', | |||||
| 'bg-components-icon-bg-teal-solid', | |||||
| ] | |||||
| export const CredentialIcon: React.FC<CredentialIconProps> = ({ | |||||
| avatar_url, | |||||
| name, | |||||
| size = 20, | |||||
| className = '', | |||||
| }) => { | |||||
| const firstLetter = useMemo(() => name.charAt(0).toUpperCase(), [name]) | |||||
| const bgColor = useMemo(() => ICON_BG_COLORS[firstLetter.charCodeAt(0) % ICON_BG_COLORS.length], [firstLetter]) | |||||
| if (avatar_url && avatar_url !== 'default') { | |||||
| return ( | |||||
| <img | |||||
| src={avatar_url} | |||||
| alt={`${name} logo`} | |||||
| width={size} | |||||
| height={size} | |||||
| className={cn('shrink-0 rounded-md border border-divider-regular object-contain', className)} | |||||
| /> | |||||
| ) | |||||
| } | |||||
| return ( | |||||
| <div | |||||
| className={cn( | |||||
| 'flex shrink-0 items-center justify-center rounded-md border border-divider-regular', | |||||
| bgColor, | |||||
| className, | |||||
| )} | |||||
| style={{ width: `${size}px`, height: `${size}px` }} | |||||
| > | |||||
| <span className='bg-gradient-to-b from-components-avatar-shape-fill-stop-0 to-components-avatar-shape-fill-stop-100 bg-clip-text text-[13px] font-semibold leading-[1.2] text-transparent opacity-90'> | |||||
| {firstLetter} | |||||
| </span> | |||||
| </div> | |||||
| ) | |||||
| } |
| import React, { useCallback } from 'react' | |||||
| import React, { useCallback, useEffect, useMemo } from 'react' | |||||
| import { | import { | ||||
| PortalToFollowElem, | PortalToFollowElem, | ||||
| PortalToFollowElemContent, | PortalToFollowElemContent, | ||||
| }: CredentialSelectorProps) => { | }: CredentialSelectorProps) => { | ||||
| const [open, { toggle }] = useBoolean(false) | const [open, { toggle }] = useBoolean(false) | ||||
| const currentCredential = credentials.find(cred => cred.id === currentCredentialId) as DataSourceCredential | |||||
| const currentCredential = useMemo(() => { | |||||
| return credentials.find(cred => cred.id === currentCredentialId) | |||||
| }, [credentials, currentCredentialId]) | |||||
| useEffect(() => { | |||||
| if (!currentCredential && credentials.length) | |||||
| onCredentialChange(credentials[0].id) | |||||
| }, [currentCredential, credentials]) | |||||
| const handleCredentialChange = useCallback((credentialId: string) => { | const handleCredentialChange = useCallback((credentialId: string) => { | ||||
| onCredentialChange(credentialId) | onCredentialChange(credentialId) |
| import { CredentialIcon } from '@/app/components/datasets/common/credential-icon' | |||||
| import type { DataSourceCredential } from '@/types/pipeline' | import type { DataSourceCredential } from '@/types/pipeline' | ||||
| import { RiCheckLine } from '@remixicon/react' | import { RiCheckLine } from '@remixicon/react' | ||||
| import React, { useCallback } from 'react' | import React, { useCallback } from 'react' | ||||
| className='flex cursor-pointer items-center gap-x-2 rounded-lg p-2 hover:bg-state-base-hover' | className='flex cursor-pointer items-center gap-x-2 rounded-lg p-2 hover:bg-state-base-hover' | ||||
| onClick={handleCredentialChange} | onClick={handleCredentialChange} | ||||
| > | > | ||||
| <img src={avatar_url} className='size-5 shrink-0 rounded-md border border-divider-regular object-contain' /> | |||||
| <span className='system-sm-medium grow text-text-secondary'> | |||||
| <CredentialIcon | |||||
| avatar_url={avatar_url} | |||||
| name={name} | |||||
| size={20} | |||||
| /> | |||||
| <span className='system-sm-medium grow truncate text-text-secondary'> | |||||
| {t('datasetPipeline.credentialSelector.name', { | {t('datasetPipeline.credentialSelector.name', { | ||||
| credentialName: name, | credentialName: name, | ||||
| pluginName, | pluginName, |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { RiArrowDownSLine } from '@remixicon/react' | import { RiArrowDownSLine } from '@remixicon/react' | ||||
| import cn from '@/utils/classnames' | import cn from '@/utils/classnames' | ||||
| import { CredentialIcon } from '@/app/components/datasets/common/credential-icon' | |||||
| type TriggerProps = { | type TriggerProps = { | ||||
| currentCredential: DataSourceCredential | |||||
| currentCredential: DataSourceCredential | undefined | |||||
| pluginName: string | pluginName: string | ||||
| isOpen: boolean | isOpen: boolean | ||||
| } | } | ||||
| const { | const { | ||||
| avatar_url, | avatar_url, | ||||
| name, | |||||
| } = currentCredential | |||||
| name = '', | |||||
| } = currentCredential || {} | |||||
| return ( | return ( | ||||
| <div className={cn( | |||||
| 'flex cursor-pointer items-center gap-x-2 rounded-md p-1 pr-2', | |||||
| isOpen ? 'bg-state-base-hover' : 'hover:bg-state-base-hover', | |||||
| )}> | |||||
| <img src={avatar_url} className='size-5 shrink-0 rounded-md border border-divider-regular object-contain' /> | |||||
| <div className='flex grow items-center gap-x-1'> | |||||
| <span className='system-md-semibold text-text-secondary'> | |||||
| <div | |||||
| className={cn( | |||||
| 'flex cursor-pointer items-center gap-x-2 rounded-md p-1 pr-2', | |||||
| isOpen ? 'bg-state-base-hover' : 'hover:bg-state-base-hover', | |||||
| )} | |||||
| > | |||||
| <CredentialIcon | |||||
| avatar_url={avatar_url} | |||||
| name={name} | |||||
| size={20} | |||||
| /> | |||||
| <div className='flex items-center gap-x-1'> | |||||
| <span className='system-md-semibold min-w-0 truncate text-text-secondary'> | |||||
| {t('datasetPipeline.credentialSelector.name', { | {t('datasetPipeline.credentialSelector.name', { | ||||
| credentialName: name, | credentialName: name, | ||||
| pluginName, | pluginName, | ||||
| })} | })} | ||||
| </span> | </span> | ||||
| <RiArrowDownSLine className='size-4 text-text-secondary' /> | |||||
| <RiArrowDownSLine className='size-4 shrink-0 text-text-secondary' /> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| ) | ) |
| return ( | return ( | ||||
| <div className='flex items-center gap-x-2'> | <div className='flex items-center gap-x-2'> | ||||
| <div className='flex shrink-0 grow items-center gap-x-1'> | |||||
| <div className='flex grow items-center gap-x-1'> | |||||
| <CredentialSelector | <CredentialSelector | ||||
| {...rest} | {...rest} | ||||
| /> | /> | ||||
| <Divider type='vertical' className='mx-1 h-3.5' /> | |||||
| <Divider type='vertical' className='mx-1 h-3.5 shrink-0' /> | |||||
| <Tooltip | <Tooltip | ||||
| popupContent={t('datasetPipeline.configurationTip', { pluginName: rest.pluginName })} | popupContent={t('datasetPipeline.configurationTip', { pluginName: rest.pluginName })} | ||||
| position='top' | position='top' | ||||
| <Button | <Button | ||||
| variant='ghost' | variant='ghost' | ||||
| size='small' | size='small' | ||||
| className='size-6 px-1' | |||||
| className='size-6 shrink-0 px-1' | |||||
| > | > | ||||
| <RiEqualizer2Line | <RiEqualizer2Line | ||||
| className='h-4 w-4' | className='h-4 w-4' | ||||
| </Tooltip> | </Tooltip> | ||||
| </div> | </div> | ||||
| <a | <a | ||||
| className='system-xs-medium flex items-center gap-x-1 overflow-hidden text-text-accent' | |||||
| className='system-xs-medium flex shrink-0 items-center gap-x-1 text-text-accent' | |||||
| href={docLink} | href={docLink} | ||||
| target='_blank' | target='_blank' | ||||
| rel='noopener noreferrer' | rel='noopener noreferrer' | ||||
| > | > | ||||
| <RiBookOpenLine className='size-3.5 shrink-0' /> | <RiBookOpenLine className='size-3.5 shrink-0' /> | ||||
| <span className='grow truncate' title={docTitle}>{docTitle}</span> | |||||
| <span title={docTitle}>{docTitle}</span> | |||||
| </a> | </a> | ||||
| </div> | </div> | ||||
| ) | ) |
| import { useShallow } from 'zustand/react/shallow' | import { useShallow } from 'zustand/react/shallow' | ||||
| import { useModalContextSelector } from '@/context/modal-context' | import { useModalContextSelector } from '@/context/modal-context' | ||||
| import Title from './title' | import Title from './title' | ||||
| import { CredentialTypeEnum } from '@/app/components/plugins/plugin-auth' | |||||
| import { noop } from 'lodash-es' | |||||
| import { useGetDataSourceAuth } from '@/service/use-datasource' | |||||
| import Loading from '@/app/components/base/loading' | |||||
| type OnlineDocumentsProps = { | type OnlineDocumentsProps = { | ||||
| isInPipeline?: boolean | isInPipeline?: boolean | ||||
| searchValue, | searchValue, | ||||
| selectedPagesId, | selectedPagesId, | ||||
| currentWorkspaceId, | currentWorkspaceId, | ||||
| currentCredentialId, | |||||
| } = useDataSourceStoreWithSelector(useShallow(state => ({ | } = useDataSourceStoreWithSelector(useShallow(state => ({ | ||||
| documentsData: state.documentsData, | documentsData: state.documentsData, | ||||
| searchValue: state.searchValue, | searchValue: state.searchValue, | ||||
| selectedPagesId: state.selectedPagesId, | selectedPagesId: state.selectedPagesId, | ||||
| currentWorkspaceId: state.currentWorkspaceId, | currentWorkspaceId: state.currentWorkspaceId, | ||||
| currentCredentialId: state.currentCredentialId, | |||||
| }))) | }))) | ||||
| const { data: dataSourceAuth } = useGetDataSourceAuth({ | |||||
| pluginId: nodeData.plugin_id, | |||||
| provider: nodeData.provider_name, | |||||
| }) | |||||
| const dataSourceStore = useDataSourceStore() | const dataSourceStore = useDataSourceStore() | ||||
| const PagesMapAndSelectedPagesId: DataSourceNotionPageMap = useMemo(() => { | const PagesMapAndSelectedPagesId: DataSourceNotionPageMap = useMemo(() => { | ||||
| }) | }) | ||||
| }, [setShowAccountSettingModal]) | }, [setShowAccountSettingModal]) | ||||
| if (!documentsData?.length) | |||||
| return null | |||||
| return ( | return ( | ||||
| <div className='flex flex-col gap-y-2'> | <div className='flex flex-col gap-y-2'> | ||||
| <Header | <Header | ||||
| // todo: delete mock data | |||||
| docTitle='How to use?' | docTitle='How to use?' | ||||
| docLink='https://docs.dify.ai' | docLink='https://docs.dify.ai' | ||||
| onClickConfiguration={handleSetting} | onClickConfiguration={handleSetting} | ||||
| pluginName={nodeData.datasource_label} | pluginName={nodeData.datasource_label} | ||||
| currentCredentialId={'12345678'} | |||||
| onCredentialChange={noop} | |||||
| credentials={[{ | |||||
| avatar_url: 'https://cloud.dify.ai/logo/logo.svg', | |||||
| credential: { | |||||
| credentials: '......', | |||||
| }, | |||||
| id: '12345678', | |||||
| is_default: true, | |||||
| name: 'test123', | |||||
| type: CredentialTypeEnum.API_KEY, | |||||
| }]} | |||||
| currentCredentialId={currentCredentialId} | |||||
| onCredentialChange={dataSourceStore.getState().setCurrentCredentialId} | |||||
| credentials={dataSourceAuth?.result || []} | |||||
| /> | /> | ||||
| <div className='rounded-xl border border-components-panel-border bg-background-default-subtle'> | <div className='rounded-xl border border-components-panel-border bg-background-default-subtle'> | ||||
| <div className='flex items-center gap-x-2 rounded-t-xl border-b border-b-divider-regular bg-components-panel-bg p-1 pl-3'> | <div className='flex items-center gap-x-2 rounded-t-xl border-b border-b-divider-regular bg-components-panel-bg p-1 pl-3'> | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| <div className='overflow-hidden rounded-b-xl'> | <div className='overflow-hidden rounded-b-xl'> | ||||
| <PageSelector | |||||
| checkedIds={selectedPagesId} | |||||
| disabledValue={new Set()} | |||||
| searchValue={searchValue} | |||||
| list={currentWorkspace?.pages || []} | |||||
| pagesMap={PagesMapAndSelectedPagesId} | |||||
| onSelect={handleSelectPages} | |||||
| canPreview={!isInPipeline} | |||||
| onPreview={handlePreviewPage} | |||||
| isMultipleChoice={!isInPipeline} | |||||
| currentWorkspaceId={currentWorkspaceId} | |||||
| /> | |||||
| {documentsData?.length ? ( | |||||
| <PageSelector | |||||
| checkedIds={selectedPagesId} | |||||
| disabledValue={new Set()} | |||||
| searchValue={searchValue} | |||||
| list={currentWorkspace?.pages || []} | |||||
| pagesMap={PagesMapAndSelectedPagesId} | |||||
| onSelect={handleSelectPages} | |||||
| canPreview={!isInPipeline} | |||||
| onPreview={handlePreviewPage} | |||||
| isMultipleChoice={!isInPipeline} | |||||
| currentWorkspaceId={currentWorkspaceId} | |||||
| /> | |||||
| ) : ( | |||||
| <div className='flex h-[296px] items-center justify-center'> | |||||
| <Loading type='app' /> | |||||
| </div> | |||||
| )} | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> |
| import type { OnlineDriveSliceShape } from './slices/online-drive' | import type { OnlineDriveSliceShape } from './slices/online-drive' | ||||
| import { createOnlineDriveSlice } from './slices/online-drive' | import { createOnlineDriveSlice } from './slices/online-drive' | ||||
| export type DataSourceShape = | |||||
| CommonShape & | |||||
| LocalFileSliceShape & | |||||
| OnlineDocumentSliceShape & | |||||
| WebsiteCrawlSliceShape & | |||||
| OnlineDriveSliceShape | |||||
| export type DataSourceShape = CommonShape | |||||
| & LocalFileSliceShape | |||||
| & OnlineDocumentSliceShape | |||||
| & WebsiteCrawlSliceShape | |||||
| & OnlineDriveSliceShape | |||||
| export const createDataSourceStore = () => { | export const createDataSourceStore = () => { | ||||
| return createStore<DataSourceShape>((...args) => ({ | return createStore<DataSourceShape>((...args) => ({ |
| const DataSourceProvider = ({ | const DataSourceProvider = ({ | ||||
| children, | children, | ||||
| }: DataSourceProviderProps) => { | }: DataSourceProviderProps) => { | ||||
| const storeRef = useRef<DataSourceStoreApi>() | |||||
| const storeRef = useRef<DataSourceStoreApi>(null) | |||||
| if (!storeRef.current) | if (!storeRef.current) | ||||
| storeRef.current = createDataSourceStore() | storeRef.current = createDataSourceStore() |
| import type { StateCreator } from 'zustand' | import type { StateCreator } from 'zustand' | ||||
| export type CommonShape = { | export type CommonShape = { | ||||
| currentNodeIdRef: React.MutableRefObject<string | undefined> | |||||
| currentNodeIdRef: React.RefObject<string> | |||||
| currentCredentialId: string | |||||
| setCurrentCredentialId: (credentialId: string) => void | |||||
| currentCredentialIdRef: React.RefObject<string> | |||||
| } | } | ||||
| export const createCommonSlice: StateCreator<CommonShape> = () => { | |||||
| export const createCommonSlice: StateCreator<CommonShape> = (set) => { | |||||
| return ({ | return ({ | ||||
| currentNodeIdRef: { current: undefined }, | |||||
| currentNodeIdRef: { current: '' }, | |||||
| currentCredentialId: '', | |||||
| setCurrentCredentialId: (credentialId: string) => { | |||||
| set({ currentCredentialId: credentialId }) | |||||
| }, | |||||
| currentCredentialIdRef: { current: '' }, | |||||
| }) | }) | ||||
| } | } |
| setLocalFileList: (fileList: FileItem[]) => void | setLocalFileList: (fileList: FileItem[]) => void | ||||
| currentLocalFile: File | undefined | currentLocalFile: File | undefined | ||||
| setCurrentLocalFile: (file: File | undefined) => void | setCurrentLocalFile: (file: File | undefined) => void | ||||
| previewLocalFileRef: React.MutableRefObject<DocumentItem | undefined> | |||||
| previewLocalFileRef: React.RefObject<DocumentItem | undefined> | |||||
| } | } | ||||
| export const createLocalFileSlice: StateCreator<LocalFileSliceShape> = (set, get) => { | export const createLocalFileSlice: StateCreator<LocalFileSliceShape> = (set, get) => { |
| setCurrentDocument: (document: NotionPage | undefined) => void | setCurrentDocument: (document: NotionPage | undefined) => void | ||||
| selectedPagesId: Set<string> | selectedPagesId: Set<string> | ||||
| setSelectedPagesId: (selectedPagesId: Set<string>) => void | setSelectedPagesId: (selectedPagesId: Set<string>) => void | ||||
| previewOnlineDocumentRef: React.MutableRefObject<NotionPage | undefined> | |||||
| previewOnlineDocumentRef: React.RefObject<NotionPage | undefined> | |||||
| } | } | ||||
| export const createOnlineDocumentSlice: StateCreator<OnlineDocumentSliceShape> = (set, get) => { | export const createOnlineDocumentSlice: StateCreator<OnlineDocumentSliceShape> = (set, get) => { |
| setFileList: (fileList: OnlineDriveFile[]) => void | setFileList: (fileList: OnlineDriveFile[]) => void | ||||
| bucket: string | bucket: string | ||||
| setBucket: (bucket: string) => void | setBucket: (bucket: string) => void | ||||
| startAfter: React.MutableRefObject<string> | |||||
| isTruncated: React.MutableRefObject<boolean> | |||||
| previewOnlineDriveFileRef: React.MutableRefObject<OnlineDriveFile | undefined> | |||||
| startAfter: React.RefObject<string> | |||||
| isTruncated: React.RefObject<boolean> | |||||
| previewOnlineDriveFileRef: React.RefObject<OnlineDriveFile | undefined> | |||||
| } | } | ||||
| export const createOnlineDriveSlice: StateCreator<OnlineDriveSliceShape> = (set, get) => { | export const createOnlineDriveSlice: StateCreator<OnlineDriveSliceShape> = (set, get) => { |
| setStep: (step: CrawlStep) => void | setStep: (step: CrawlStep) => void | ||||
| previewIndex: number | previewIndex: number | ||||
| setPreviewIndex: (index: number) => void | setPreviewIndex: (index: number) => void | ||||
| previewWebsitePageRef: React.MutableRefObject<CrawlResultItem | undefined> | |||||
| previewWebsitePageRef: React.RefObject<CrawlResultItem | undefined> | |||||
| } | } | ||||
| export const createWebsiteCrawlSlice: StateCreator<WebsiteCrawlSliceShape> = (set, get) => { | export const createWebsiteCrawlSlice: StateCreator<WebsiteCrawlSliceShape> = (set, get) => { |
| documentId, | documentId, | ||||
| params: { metadata: 'without' }, | params: { metadata: 'without' }, | ||||
| }) | }) | ||||
| console.log('🚀 ~ DocumentDetail ~ documentDetail:', documentDetail) | |||||
| const { data: documentMetadata } = useDocumentMetadata({ | const { data: documentMetadata } = useDocumentMetadata({ | ||||
| datasetId, | datasetId, |
| category: AuthCategory.datasource, | category: AuthCategory.datasource, | ||||
| provider: `${item.plugin_id}/${item.name}`, | provider: `${item.plugin_id}/${item.name}`, | ||||
| } | } | ||||
| const { handleAuthUpdate } = useDataSourceAuthUpdate() | |||||
| const { handleAuthUpdate } = useDataSourceAuthUpdate({ | |||||
| pluginId: item.plugin_id, | |||||
| provider: item.name, | |||||
| }) | |||||
| const { | const { | ||||
| deleteCredentialId, | deleteCredentialId, | ||||
| doingAction, | doingAction, |
| import { useCallback } from 'react' | import { useCallback } from 'react' | ||||
| import { useInvalidDataSourceListAuth } from '@/service/use-datasource' | |||||
| import { useInvalidDataSourceAuth, useInvalidDataSourceListAuth } from '@/service/use-datasource' | |||||
| import { useInvalidDefaultDataSourceListAuth } from '@/service/use-datasource' | import { useInvalidDefaultDataSourceListAuth } from '@/service/use-datasource' | ||||
| import { useInvalidDataSourceList } from '@/service/use-pipeline' | import { useInvalidDataSourceList } from '@/service/use-pipeline' | ||||
| export const useDataSourceAuthUpdate = () => { | |||||
| export const useDataSourceAuthUpdate = ({ | |||||
| pluginId, | |||||
| provider, | |||||
| }: { | |||||
| pluginId: string | |||||
| provider: string | |||||
| }) => { | |||||
| const invalidateDataSourceListAuth = useInvalidDataSourceListAuth() | const invalidateDataSourceListAuth = useInvalidDataSourceListAuth() | ||||
| const invalidDefaultDataSourceListAuth = useInvalidDefaultDataSourceListAuth() | const invalidDefaultDataSourceListAuth = useInvalidDefaultDataSourceListAuth() | ||||
| const invalidateDataSourceList = useInvalidDataSourceList() | const invalidateDataSourceList = useInvalidDataSourceList() | ||||
| const invalidateDataSourceAuth = useInvalidDataSourceAuth({ | |||||
| pluginId, | |||||
| provider, | |||||
| }) | |||||
| const handleAuthUpdate = useCallback(() => { | const handleAuthUpdate = useCallback(() => { | ||||
| invalidateDataSourceListAuth() | invalidateDataSourceListAuth() | ||||
| invalidDefaultDataSourceListAuth() | invalidDefaultDataSourceListAuth() | ||||
| invalidateDataSourceList() | invalidateDataSourceList() | ||||
| }, [invalidateDataSourceListAuth, invalidateDataSourceList]) | |||||
| invalidateDataSourceAuth() | |||||
| }, [invalidateDataSourceListAuth, invalidateDataSourceList, invalidateDataSourceAuth, invalidDefaultDataSourceListAuth]) | |||||
| return { | return { | ||||
| handleAuthUpdate, | handleAuthUpdate, |
| } from '@tanstack/react-query' | } from '@tanstack/react-query' | ||||
| import { get } from './base' | import { get } from './base' | ||||
| import { useInvalid } from './use-base' | import { useInvalid } from './use-base' | ||||
| import type { DataSourceAuth } from '@/app/components/header/account-setting/data-source-page-new/types' | |||||
| import type { | |||||
| DataSourceAuth, | |||||
| DataSourceCredential, | |||||
| } from '@/app/components/header/account-setting/data-source-page-new/types' | |||||
| const NAME_SPACE = 'data-source-auth' | const NAME_SPACE = 'data-source-auth' | ||||
| ) => { | ) => { | ||||
| return useInvalid([NAME_SPACE, 'default-list']) | return useInvalid([NAME_SPACE, 'default-list']) | ||||
| } | } | ||||
| export const useGetDataSourceOAuthUrl = ( | export const useGetDataSourceOAuthUrl = ( | ||||
| provider: string, | provider: string, | ||||
| ) => { | ) => { | ||||
| mutationKey: [NAME_SPACE, 'oauth-url', provider], | mutationKey: [NAME_SPACE, 'oauth-url', provider], | ||||
| mutationFn: (credentialId?: string) => { | mutationFn: (credentialId?: string) => { | ||||
| return get< | return get< | ||||
| { | |||||
| authorization_url: string | |||||
| state: string | |||||
| context_id: string | |||||
| }>(`/oauth/plugin/${provider}/datasource/get-authorization-url?credential_id=${credentialId}`) | |||||
| { | |||||
| authorization_url: string | |||||
| state: string | |||||
| context_id: string | |||||
| }>(`/oauth/plugin/${provider}/datasource/get-authorization-url?credential_id=${credentialId}`) | |||||
| }, | }, | ||||
| }) | }) | ||||
| } | } | ||||
| export const useGetDataSourceAuth = ({ | |||||
| pluginId, | |||||
| provider, | |||||
| }: { | |||||
| pluginId: string | |||||
| provider: string | |||||
| }) => { | |||||
| return useQuery({ | |||||
| queryKey: [NAME_SPACE, 'specific-data-source', pluginId, provider], | |||||
| queryFn: () => get<{ result: DataSourceCredential[] }>(`/auth/plugin/datasource/${pluginId}/${provider}`), | |||||
| retry: 0, | |||||
| }) | |||||
| } | |||||
| export const useInvalidDataSourceAuth = ({ | |||||
| pluginId, | |||||
| provider, | |||||
| }: { | |||||
| pluginId: string | |||||
| provider: string | |||||
| }) => { | |||||
| return useInvalid([NAME_SPACE, 'specific-data-source', pluginId, provider]) | |||||
| } |