mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-25 02:31:59 -05:00
parent
6a721d4dab
commit
c9012d5e6d
2 changed files with 96 additions and 10 deletions
82
apps/admin-x-settings/src/api/integrations.ts
Normal file
82
apps/admin-x-settings/src/api/integrations.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
import {Meta, createQuery} from '../utils/apiRequests';
|
||||
|
||||
// Types
|
||||
|
||||
export type IntegrationApiKey = {
|
||||
id: string;
|
||||
type: string;
|
||||
secret: string;
|
||||
role_id: string;
|
||||
integration_id: string;
|
||||
user_id: string | null;
|
||||
last_seen_at: string | null;
|
||||
last_seen_version: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export type IntegrationWebhook = {
|
||||
id: string;
|
||||
event: string;
|
||||
target_url: string;
|
||||
name: string;
|
||||
secret: string | null;
|
||||
api_version: string;
|
||||
integration_id: string;
|
||||
last_triggered_at: string | null;
|
||||
last_triggered_status: string | null;
|
||||
last_triggered_error: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export type Integration = {
|
||||
id: string;
|
||||
type: 'builtin' | 'core' | 'custom';
|
||||
name: string;
|
||||
slug: string;
|
||||
icon_image: string | null;
|
||||
description: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
api_keys: IntegrationApiKey[];
|
||||
webhooks: IntegrationWebhook[];
|
||||
}
|
||||
|
||||
export interface IntegrationsResponseType {
|
||||
meta?: Meta;
|
||||
integrations: Integration[];
|
||||
}
|
||||
|
||||
// Requests
|
||||
|
||||
const dataType = 'IntegrationsResponseType';
|
||||
|
||||
export const useBrowseIntegrations = createQuery<IntegrationsResponseType>({
|
||||
dataType,
|
||||
path: '/integrations/',
|
||||
defaultSearchParams: {include: 'api_keys,webhooks'}
|
||||
});
|
||||
|
||||
// export const useEditIntegration = createMutation<IntegrationsResponseType, Integration>({
|
||||
// method: 'PUT',
|
||||
// path: integration => `/integrations/${integration.id}/`,
|
||||
// body: integration => ({integrations: [integration]}),
|
||||
// searchParams: () => ({include: 'roles'}),
|
||||
// updateQueries: {
|
||||
// dataType,
|
||||
// update: () => {} // TODO
|
||||
// }
|
||||
// });
|
||||
|
||||
// export const useDeleteIntegration = createMutation<DeleteIntegrationResponse, string>({
|
||||
// method: 'DELETE',
|
||||
// path: id => `/integrations/${id}/`,
|
||||
// updateQueries: {
|
||||
// dataType,
|
||||
// update: (_, currentData, id) => ({
|
||||
// ...(currentData as IntegrationsResponseType),
|
||||
// integrations: (currentData as IntegrationsResponseType).integrations.filter(user => user.id !== id)
|
||||
// })
|
||||
// }
|
||||
// });
|
|
@ -7,12 +7,13 @@ import TabView from '../../../admin-x-ds/global/TabView';
|
|||
import useRouting from '../../../hooks/useRouting';
|
||||
import {ReactComponent as AmpIcon} from '../../../assets/icons/amp.svg';
|
||||
import {ReactComponent as FirstPromoterIcon} from '../../../assets/icons/firstpromoter.svg';
|
||||
import {Integration, useBrowseIntegrations} from '../../../api/integrations';
|
||||
import {ReactComponent as PinturaIcon} from '../../../assets/icons/pintura.svg';
|
||||
import {ReactComponent as SlackIcon} from '../../../assets/icons/slack.svg';
|
||||
import {ReactComponent as UnsplashIcon} from '../../../assets/icons/unsplash.svg';
|
||||
import {ReactComponent as ZapierIcon} from '../../../assets/icons/zapier.svg';
|
||||
|
||||
const Integration: React.FC<{icon?: React.ReactNode, title: string, detail:string, action:() => void}> = ({
|
||||
const IntegrationItem: React.FC<{icon?: React.ReactNode, title: string, detail:string, action:() => void}> = ({
|
||||
icon,
|
||||
title,
|
||||
detail,
|
||||
|
@ -36,7 +37,7 @@ const BuiltInIntegrations: React.FC = () => {
|
|||
|
||||
return (
|
||||
<List titleSeparator={false}>
|
||||
<Integration
|
||||
<IntegrationItem
|
||||
action={() => {
|
||||
openModal('integrations/zapier');
|
||||
}}
|
||||
|
@ -44,7 +45,7 @@ const BuiltInIntegrations: React.FC = () => {
|
|||
icon={<ZapierIcon className='h-8 w-8' />}
|
||||
title='Zapier' />
|
||||
|
||||
<Integration
|
||||
<IntegrationItem
|
||||
action={() => {
|
||||
openModal('integrations/slack');
|
||||
}}
|
||||
|
@ -52,7 +53,7 @@ const BuiltInIntegrations: React.FC = () => {
|
|||
icon={<SlackIcon className='h-8 w-8' />}
|
||||
title='Slack' />
|
||||
|
||||
<Integration
|
||||
<IntegrationItem
|
||||
action={() => {
|
||||
openModal('integrations/amp');
|
||||
}}
|
||||
|
@ -60,7 +61,7 @@ const BuiltInIntegrations: React.FC = () => {
|
|||
icon={<AmpIcon className='h-8 w-8' />}
|
||||
title='AMP' />
|
||||
|
||||
<Integration
|
||||
<IntegrationItem
|
||||
action={() => {
|
||||
openModal('integrations/unsplash');
|
||||
}}
|
||||
|
@ -68,7 +69,7 @@ const BuiltInIntegrations: React.FC = () => {
|
|||
icon={<UnsplashIcon className='h-8 w-8' />}
|
||||
title='Unsplash' />
|
||||
|
||||
<Integration
|
||||
<IntegrationItem
|
||||
action={() => {
|
||||
openModal('integrations/firstpromoter');
|
||||
}}
|
||||
|
@ -76,7 +77,7 @@ const BuiltInIntegrations: React.FC = () => {
|
|||
icon={<FirstPromoterIcon className='h-8 w-8' />}
|
||||
title='FirstPromoter' />
|
||||
|
||||
<Integration
|
||||
<IntegrationItem
|
||||
action={() => {
|
||||
openModal('integrations/pintura');
|
||||
}}
|
||||
|
@ -87,16 +88,19 @@ const BuiltInIntegrations: React.FC = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const CustomIntegrations: React.FC = () => {
|
||||
const CustomIntegrations: React.FC<{integrations: Integration[]}> = ({integrations}) => {
|
||||
return (
|
||||
<List>
|
||||
<Integration action={() => {}} detail='Here we go' title='A custom integration' />
|
||||
{integrations.map(integration => (
|
||||
<IntegrationItem action={() => {}} detail={integration.description || 'No description'} title={integration.name} />)
|
||||
)}
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
const Integrations: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
||||
const [selectedTab, setSelectedTab] = useState<'built-in' | 'custom'>('built-in');
|
||||
const {data: {integrations} = {integrations: []}} = useBrowseIntegrations();
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
|
@ -107,7 +111,7 @@ const Integrations: React.FC<{ keywords: string[] }> = ({keywords}) => {
|
|||
{
|
||||
id: 'custom',
|
||||
title: 'Custom',
|
||||
contents: <CustomIntegrations />
|
||||
contents: <CustomIntegrations integrations={integrations.filter(integration => integration.type === 'custom')} />
|
||||
}
|
||||
] as const;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue