From 35a4564b21f5a064901a14e75d3e7a5830d6a59d Mon Sep 17 00:00:00 2001 From: ajnart Date: Mon, 3 Jul 2023 21:09:23 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20integration=20delete=20and=20?= =?UTF-8?q?testing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Config/Integration/IntegrationModal.tsx | 238 +++++++++++++++--- src/server/api/routers/system.ts | 14 ++ 2 files changed, 220 insertions(+), 32 deletions(-) diff --git a/src/components/Config/Integration/IntegrationModal.tsx b/src/components/Config/Integration/IntegrationModal.tsx index 232fb6983..af3d1cd8a 100644 --- a/src/components/Config/Integration/IntegrationModal.tsx +++ b/src/components/Config/Integration/IntegrationModal.tsx @@ -8,16 +8,20 @@ import { Menu, Modal, PasswordInput, + Popover, SelectItem, Stack, Text, TextInput, + ThemeIcon, Title, + Tooltip, rem, useMantineTheme, } from '@mantine/core'; import { AccordionItem } from '@mantine/core/lib/Accordion/AccordionItem/AccordionItem'; import { UseFormReturnType, useForm } from '@mantine/form'; +import { modals } from '@mantine/modals'; import { notifications } from '@mantine/notifications'; import { IconCheck, @@ -25,15 +29,23 @@ import { IconCircleX, IconCircleXFilled, IconDeviceFloppy, + IconExternalLink, + IconKey, IconLock, + IconPassword, IconPlug, IconPlugConnected, IconPlus, + IconQuestionMark, + IconTestPipe, IconTrash, + IconUser, + IconX, } from '@tabler/icons-react'; import { useQueryClient } from '@tanstack/react-query'; import { getQueryKey } from '@trpc/react-query'; import { getCookie, setCookie } from 'cookies-next'; +import Link from 'next/link'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { integrationsList } from '~/components/Dashboard/Modals/EditAppModal/Tabs/IntegrationTab/Components/InputElements/IntegrationSelector'; @@ -109,15 +121,20 @@ export function IntegrationMenu({ integrationsModal }: { integrationsModal: any function IntegrationDisplay({ integration, + integrations, + setIntegrations, integrationIdx, form, }: { integration: AppIntegrationType; + integrations: IntegrationTypeMap; + setIntegrations: (integrations: IntegrationTypeMap) => void; integrationIdx: number; form: UseFormReturnType; }) { if (!integration.type) return null; - const { t } = useTranslation('settings/integrations'); + const { t } = useTranslation(['settings/integrations', 'common']); + const mutation = api.system.testIntegration.useMutation(); return ( @@ -126,17 +143,20 @@ function IntegrationDisplay({ + + + + + } {...form.getInputProps(`${integration.type}.${integrationIdx}.url`)} /> - {integration.properties.map((property, idx) => { - if (!property.value) return null; - if (property.type === 'private') - return ( - - ); - else if (property.type === 'public') - return ( - - ); - })} + + {integration.properties.map((property, idx) => { + if (!property.value) return null; + if (property.type === 'private') + return ( + : } + defaultValue={property.value} + key={property.field} + label={property.field} + {...form.getInputProps( + `${integration.type}.${integrationIdx}.properties.${idx}.value` + )} + /> + ); + else if (property.type === 'public') + return ( + : } + defaultValue={property.value} + key={property.field} + label={property.field} + {...form.getInputProps( + `${integration.type}.${integrationIdx}.properties.${idx}.value` + )} + /> + ); + })} + + + + + + + + + {t('common:delete')} + {t('deleteConfirmation', { name: integration.name })} + + + + + + + + ); } +export function SecretsInputs({ + integration, + integrationIdx, + form, +}: { + integration: AppIntegrationType; + integrationIdx: number; + form: UseFormReturnType; +}) { + const { t } = useTranslation('settings/integrations'); + return ( + + {integration.properties.map((property, idx) => { + if (!property.value) return null; + + switch (property.field) { + case 'apiKey': + return ( + + + + + + + + + ); + case 'username': + return ( + + + + + + + + + ); + case 'password': + return ( + + + + + + + + + ); + // Other case + default: + return ( + + + + + + + + + ); + } + })} + + ); +} + // export type IntegrationType = // | 'readarr' // | 'radarr' @@ -251,6 +424,8 @@ export function IntegrationsAccordion({ closeModal }: { closeModal: () => void } integrationIdx={integrationIdx} form={form} integration={integration} + integrations={integrations} + setIntegrations={setIntegrations} /> ); })} @@ -341,9 +516,8 @@ export function IntegrationModal({ opened={opened} closeOnClickOutside={false} closeOnEscape={false} - withCloseButton={false} onClose={() => closeModal()} - size={rem(1000)} + fullScreen > diff --git a/src/server/api/routers/system.ts b/src/server/api/routers/system.ts index a811c466f..04e7574f4 100644 --- a/src/server/api/routers/system.ts +++ b/src/server/api/routers/system.ts @@ -7,6 +7,7 @@ import { cookies } from 'next/headers'; import { env } from 'process'; import { z } from 'zod'; import { getConfig } from '~/tools/config/getConfig'; +import { AppIntegrationType } from '~/types/app'; import { createTRPCRouter, publicProcedure } from '../trpc'; @@ -58,4 +59,17 @@ export const systemRouter = createTRPCRouter({ } return config.integrations; }), + + testIntegration: publicProcedure + .input( + z.object({ + integration: z.any(), + }) + ) + .mutation(async ({ input }) => { + // Wait 500ms then return true to simulate a successful integration + //TODO: Add integration tests + await new Promise((resolve) => setTimeout(resolve, 500)); + return true; + }), });