mirror of
https://github.com/ajnart/homarr.git
synced 2026-01-27 17:59:16 +01:00
WIP on integrations panel
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -11,7 +11,7 @@
|
||||
"layout.manage.navigation.**",
|
||||
],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
"source.organizeImports": "explicit"
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"explorer.fileNesting.patterns": {
|
||||
|
||||
134
drizzle/0001_volatile_the_enforcers.sql
Normal file
134
drizzle/0001_volatile_the_enforcers.sql
Normal file
@@ -0,0 +1,134 @@
|
||||
CREATE TABLE `app_status_code` (
|
||||
`app_id` text NOT NULL,
|
||||
`code` integer NOT NULL,
|
||||
PRIMARY KEY(`app_id`, `code`),
|
||||
FOREIGN KEY (`app_id`) REFERENCES `app`(`id`) ON UPDATE no action ON DELETE cascade,
|
||||
FOREIGN KEY (`code`) REFERENCES `status_code`(`code`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `app` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`name` text NOT NULL,
|
||||
`description` text,
|
||||
`internal_url` text NOT NULL,
|
||||
`external_url` text,
|
||||
`icon_url` text NOT NULL,
|
||||
`open_in_new_tab` integer DEFAULT false NOT NULL,
|
||||
`is_ping_enabled` integer DEFAULT false NOT NULL,
|
||||
`font_size` integer DEFAULT 16 NOT NULL,
|
||||
`name_position` text DEFAULT 'top' NOT NULL,
|
||||
`name_style` text DEFAULT 'normal' NOT NULL,
|
||||
`name_line_clamp` integer DEFAULT 1 NOT NULL,
|
||||
`item_id` text NOT NULL,
|
||||
FOREIGN KEY (`item_id`) REFERENCES `item`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `board_integration` (
|
||||
`board_id` text NOT NULL,
|
||||
`integration_id` text NOT NULL,
|
||||
PRIMARY KEY(`board_id`, `integration_id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `board` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`name` text NOT NULL,
|
||||
`is_ping_enabled` integer DEFAULT false NOT NULL,
|
||||
`allow_guests` integer DEFAULT false NOT NULL,
|
||||
`page_title` text,
|
||||
`meta_title` text,
|
||||
`logo_image_url` text,
|
||||
`favicon_image_url` text,
|
||||
`background_image_url` text,
|
||||
`background_image_attachment` text DEFAULT 'fixed' NOT NULL,
|
||||
`background_image_repeat` text DEFAULT 'no-repeat' NOT NULL,
|
||||
`background_image_size` text DEFAULT 'cover' NOT NULL,
|
||||
`primary_color` text DEFAULT 'red' NOT NULL,
|
||||
`secondary_color` text DEFAULT 'orange' NOT NULL,
|
||||
`primary_shade` integer DEFAULT 6 NOT NULL,
|
||||
`app_opacity` integer DEFAULT 100 NOT NULL,
|
||||
`custom_css` text,
|
||||
`user_id` text NOT NULL,
|
||||
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `integration_secret` (
|
||||
`key` text NOT NULL,
|
||||
`value` text,
|
||||
`integration_id` text NOT NULL,
|
||||
PRIMARY KEY(`integration_id`, `key`),
|
||||
FOREIGN KEY (`integration_id`) REFERENCES `integration`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `integration` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`type` text NOT NULL,
|
||||
`name` text NOT NULL,
|
||||
`url` text NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `item` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`kind` text NOT NULL,
|
||||
`board_id` text NOT NULL,
|
||||
FOREIGN KEY (`board_id`) REFERENCES `board`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `layout_item` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`section_id` text NOT NULL,
|
||||
`item_id` text NOT NULL,
|
||||
`x` integer NOT NULL,
|
||||
`y` integer NOT NULL,
|
||||
`width` integer NOT NULL,
|
||||
`height` integer NOT NULL,
|
||||
FOREIGN KEY (`section_id`) REFERENCES `section`(`id`) ON UPDATE no action ON DELETE cascade,
|
||||
FOREIGN KEY (`item_id`) REFERENCES `item`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `layout` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`name` text NOT NULL,
|
||||
`kind` text NOT NULL,
|
||||
`show_right_sidebar` integer DEFAULT false NOT NULL,
|
||||
`show_left_sidebar` integer DEFAULT false NOT NULL,
|
||||
`column_count` integer DEFAULT 10 NOT NULL,
|
||||
`board_id` text NOT NULL,
|
||||
FOREIGN KEY (`board_id`) REFERENCES `board`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `section` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`kind` text NOT NULL,
|
||||
`position` integer,
|
||||
`name` text,
|
||||
`layout_id` text NOT NULL,
|
||||
FOREIGN KEY (`layout_id`) REFERENCES `layout`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `status_code` (
|
||||
`code` integer PRIMARY KEY NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `widget_integration` (
|
||||
`widget_id` text NOT NULL,
|
||||
`integration_id` text NOT NULL,
|
||||
PRIMARY KEY(`integration_id`, `widget_id`),
|
||||
FOREIGN KEY (`widget_id`) REFERENCES `widget`(`id`) ON UPDATE no action ON DELETE cascade,
|
||||
FOREIGN KEY (`integration_id`) REFERENCES `integration`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `widget_option` (
|
||||
`path` text NOT NULL,
|
||||
`value` text,
|
||||
`type` text NOT NULL,
|
||||
`widget_id` text NOT NULL,
|
||||
PRIMARY KEY(`path`, `widget_id`),
|
||||
FOREIGN KEY (`widget_id`) REFERENCES `widget`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `widget` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`sort` text NOT NULL,
|
||||
`item_id` text NOT NULL,
|
||||
FOREIGN KEY (`item_id`) REFERENCES `item`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
1358
drizzle/meta/0001_snapshot.json
Normal file
1358
drizzle/meta/0001_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,13 @@
|
||||
"when": 1695874816934,
|
||||
"tag": "0000_supreme_the_captain",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "5",
|
||||
"when": 1701527428740,
|
||||
"tag": "0001_volatile_the_enforcers",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -24,7 +24,8 @@
|
||||
"test:coverage": "SKIP_ENV_VALIDATION=1 vitest run --coverage",
|
||||
"docker:build": "turbo build && docker build . -t homarr:local-dev",
|
||||
"docker:start": "docker run -p 7575:7575 --name homarr-development homarr:local-dev",
|
||||
"db:migrate": "dotenv ts-node drizzle/migrate/migrate.ts ./drizzle"
|
||||
"db:migrate": "dotenv ts-node drizzle/migrate/migrate.ts ./drizzle",
|
||||
"db:create": "dotenv drizzle-kit push:sqlite"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/drizzle-adapter": "^0.3.2",
|
||||
@@ -92,6 +93,7 @@
|
||||
"html-entities": "^2.3.3",
|
||||
"i18next": "^22.5.1",
|
||||
"immer": "^10.0.2",
|
||||
"nanoid": "^5.0.4",
|
||||
"next": "13.4.12",
|
||||
"next-auth": "^4.23.0",
|
||||
"next-i18next": "^14.0.0",
|
||||
@@ -234,4 +236,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
"contribute": "Contribute"
|
||||
}
|
||||
},
|
||||
"integrations": {
|
||||
"title": "Integrations"
|
||||
},
|
||||
"tools": {
|
||||
"title": "Tools",
|
||||
"items": {
|
||||
|
||||
@@ -8,10 +8,8 @@ import {
|
||||
Indicator,
|
||||
NavLink,
|
||||
Navbar,
|
||||
Paper,
|
||||
Text,
|
||||
ThemeIcon,
|
||||
useMantineTheme,
|
||||
ThemeIcon
|
||||
} from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import {
|
||||
@@ -21,7 +19,6 @@ import {
|
||||
IconBrandGithub,
|
||||
IconGitFork,
|
||||
IconHome,
|
||||
IconInfoCircle,
|
||||
IconInfoSmall,
|
||||
IconLayoutDashboard,
|
||||
IconMailForward,
|
||||
@@ -29,7 +26,7 @@ import {
|
||||
IconTool,
|
||||
IconUser,
|
||||
IconUsers,
|
||||
TablerIconsProps,
|
||||
TablerIconsProps
|
||||
} from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useSession } from 'next-auth/react';
|
||||
@@ -42,6 +39,7 @@ import { useScreenLargerThan } from '~/hooks/useScreenLargerThan';
|
||||
import { usePackageAttributesStore } from '~/tools/client/zustands/usePackageAttributesStore';
|
||||
import { ConditionalWrapper } from '~/utils/security';
|
||||
|
||||
import { IconPlugConnected } from '@tabler/icons-react';
|
||||
import { REPO_URL } from '../../../../data/constants';
|
||||
import { type navigation } from '../../../../public/locales/en/layout/manage.json';
|
||||
import { MainHeader } from '../header/Header';
|
||||
@@ -96,6 +94,11 @@ export const ManageLayout = ({ children }: ManageLayoutProps) => {
|
||||
},
|
||||
},
|
||||
},
|
||||
integrations: {
|
||||
icon: IconPlugConnected,
|
||||
onlyAdmin: true,
|
||||
href: '/manage/integrations',
|
||||
},
|
||||
tools: {
|
||||
icon: IconTool,
|
||||
onlyAdmin: true,
|
||||
|
||||
@@ -1,98 +1,42 @@
|
||||
import { Button, Group, Stack, TextInput, useMantineTheme } from '@mantine/core';
|
||||
import { UseFormReturnType, useForm } from '@mantine/form';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { QueryKey, useQueryClient } from '@tanstack/react-query';
|
||||
import { getQueryKey } from '@trpc/react-query';
|
||||
import { getCookie } from 'cookies-next';
|
||||
import { produce } from 'immer';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { IntegrationTab } from '~/components/Dashboard/Modals/EditAppModal/Tabs/IntegrationTab/IntegrationTab';
|
||||
import { AppType } from '~/types/app';
|
||||
import { IntegrationTypeMap } from '~/types/config';
|
||||
import { api } from '~/utils/api';
|
||||
import { IntegrationType } from '~/server/db/items';
|
||||
import { AppIntegrationType } from '~/types/app';
|
||||
|
||||
const defaultAppValues: AppType = {
|
||||
id: uuidv4(),
|
||||
name: 'Your app',
|
||||
url: 'https://homarr.dev',
|
||||
appearance: {
|
||||
iconUrl: '/imgs/logo/logo.png',
|
||||
appNameStatus: 'normal',
|
||||
positionAppName: '-moz-initial',
|
||||
lineClampAppName: 2
|
||||
},
|
||||
network: {
|
||||
enabledStatusChecker: true,
|
||||
statusCodes: ['200', '301', '302', '304', '307', '308'],
|
||||
okStatus: [200, 301, 302, 304, 307, 308],
|
||||
},
|
||||
behaviour: {
|
||||
isOpeningNewTab: true,
|
||||
externalUrl: '',
|
||||
},
|
||||
|
||||
area: {
|
||||
type: 'wrapper',
|
||||
properties: {
|
||||
id: 'default',
|
||||
},
|
||||
},
|
||||
shape: {},
|
||||
integration: {
|
||||
id: uuidv4(),
|
||||
url: '',
|
||||
type: undefined,
|
||||
properties: [],
|
||||
name: 'New integration',
|
||||
},
|
||||
};
|
||||
|
||||
export function AddIntegrationPanel({
|
||||
globalForm,
|
||||
queryKey,
|
||||
integrations,
|
||||
setIntegrations,
|
||||
}: {
|
||||
globalForm: UseFormReturnType<any>;
|
||||
queryKey: QueryKey;
|
||||
integrations: IntegrationTypeMap | undefined;
|
||||
setIntegrations: React.Dispatch<React.SetStateAction<IntegrationTypeMap | undefined>>;
|
||||
}) {
|
||||
export function AddIntegrationPanel({}) {
|
||||
const { t } = useTranslation(['board/integrations', 'common']);
|
||||
const queryClient = useQueryClient();
|
||||
const { primaryColor } = useMantineTheme();
|
||||
|
||||
const form = useForm<AppType>({
|
||||
initialValues: defaultAppValues,
|
||||
const form = useForm<IntegrationType>({
|
||||
initialValues: 'jellyfin',
|
||||
});
|
||||
|
||||
if (!integrations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={form.onSubmit(({ integration }) => {
|
||||
if (!integration.type || !integrations) return null;
|
||||
const newIntegrations = produce(integrations, (draft) => {
|
||||
integration.id = uuidv4();
|
||||
// console.log(integration.type);
|
||||
if (!integration.type) return;
|
||||
// If integration type is not in integrations, add it
|
||||
if (!draft[integration.type]) {
|
||||
draft[integration.type] = [];
|
||||
}
|
||||
draft[integration.type].push(integration);
|
||||
});
|
||||
// queryClient.setQueryData(queryKey, newIntegrations);
|
||||
form.reset();
|
||||
setIntegrations(newIntegrations);
|
||||
notifications.show({
|
||||
title: t('integration.Added'),
|
||||
message: t('integration.AddedDescription', { name: integration.name }),
|
||||
color: 'green',
|
||||
});
|
||||
onSubmit={form.onSubmit((input) => {
|
||||
console.log(input);
|
||||
// if (!integration.type || !integrations) return null;
|
||||
// const newIntegrations = produce(integrations, (draft) => {
|
||||
// integration.id = uuidv4();
|
||||
// // console.log(integration.type);
|
||||
// if (!integration.type) return;
|
||||
// // If integration type is not in integrations, add it
|
||||
// if (!draft[integration.type]) {
|
||||
// draft[integration.type] = [];
|
||||
// }
|
||||
// draft[integration.type].push(integration);
|
||||
// });
|
||||
// // queryClient.setQueryData(queryKey, newIntegrations);
|
||||
// form.reset();
|
||||
// setIntegrations(newIntegrations);
|
||||
// notifications.show({
|
||||
// title: t('integration.Added'),
|
||||
// message: t('integration.AddedDescription', { name: integration.name }),
|
||||
// color: 'green',
|
||||
// });
|
||||
})}
|
||||
>
|
||||
<Stack>
|
||||
|
||||
@@ -1,64 +1,20 @@
|
||||
import {
|
||||
ActionIcon,
|
||||
Autocomplete,
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Flex,
|
||||
Group,
|
||||
Pagination,
|
||||
Table,
|
||||
Text,
|
||||
Title,
|
||||
Tooltip,
|
||||
useMantineTheme,
|
||||
} from '@mantine/core';
|
||||
import { Text, Title } from '@mantine/core';
|
||||
import { useDebouncedValue } from '@mantine/hooks';
|
||||
import { IconPlus, IconTrash, IconUserDown, IconUserUp } from '@tabler/icons-react';
|
||||
import { GetServerSideProps } from 'next';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import Head from 'next/head';
|
||||
import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import { openRoleChangeModal } from '~/components/Manage/User/change-user-role.modal';
|
||||
import { openDeleteUserModal } from '~/components/Manage/User/delete-user.modal';
|
||||
import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
|
||||
import { getServerAuthSession } from '~/server/auth';
|
||||
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
|
||||
import { manageNamespaces } from '~/tools/server/translation-namespaces';
|
||||
import { api } from '~/utils/api';
|
||||
|
||||
import { AddIntegrationPanel } from './AddIntegrationPanel';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { IntegrationTypeMap } from '~/types/config';
|
||||
import { useConfigContext } from '~/config/provider';
|
||||
import { useForm } from '@mantine/form';
|
||||
|
||||
const ManageUsersPage = () => {
|
||||
const [activePage, setActivePage] = useState(0);
|
||||
const [nonDebouncedSearch, setNonDebouncedSearch] = useState<string | undefined>('');
|
||||
const [debouncedSearch] = useDebouncedValue<string | undefined>(nonDebouncedSearch, 200);
|
||||
const { t } = useTranslation('manage/integrations');
|
||||
const queryClient = useQueryClient();
|
||||
const { primaryColor } = useMantineTheme();
|
||||
const integrationsQuery: IntegrationTypeMap | undefined = queryClient.getQueryData(queryKey);
|
||||
const mutation = api.config.save.useMutation();
|
||||
const { config, name } = useConfigContext();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { data: sessionData } = useSession();
|
||||
const [integrations, setIntegrations] = useState<IntegrationTypeMap | undefined>(
|
||||
integrationsQuery
|
||||
);
|
||||
|
||||
if (!integrations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const form = useForm({
|
||||
initialValues: integrationsQuery,
|
||||
});
|
||||
|
||||
const metaTitle = `${t('metaTitle')} • Homarr`;
|
||||
|
||||
@@ -70,12 +26,6 @@ const ManageUsersPage = () => {
|
||||
|
||||
<Title mb="md">{t('pageTitle')}</Title>
|
||||
<Text mb="xl">{t('text')}</Text>
|
||||
<AddIntegrationPanel
|
||||
globalForm={form}
|
||||
queryKey={queryKey}
|
||||
integrations={integrations}
|
||||
setIntegrations={setIntegrations}
|
||||
/>
|
||||
</ManageLayout>
|
||||
);
|
||||
};
|
||||
@@ -85,15 +35,20 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
||||
|
||||
if (!session?.user.isAdmin) {
|
||||
return {
|
||||
notFound: true,
|
||||
redirect: {
|
||||
destination: '/401',
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const caller = integrationsRouter
|
||||
|
||||
const translations = await getServerSideTranslations(
|
||||
manageNamespaces,
|
||||
[...manageNamespaces, 'manage/integrations'],
|
||||
ctx.locale,
|
||||
undefined,
|
||||
undefined
|
||||
ctx.req,
|
||||
ctx.res,
|
||||
);
|
||||
return {
|
||||
props: {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { dnsHoleRouter } from './routers/dns-hole/router';
|
||||
import { dockerRouter } from './routers/docker/router';
|
||||
import { downloadRouter } from './routers/download';
|
||||
import { iconRouter } from './routers/icon';
|
||||
import { integrationRouter } from './routers/integration';
|
||||
import { integrationsRouter } from './routers/integration';
|
||||
import { inviteRouter } from './routers/invite/invite-router';
|
||||
import { layoutsRouter } from './routers/layout/layout.router';
|
||||
import { mediaRequestsRouter } from './routers/media-request';
|
||||
@@ -50,7 +50,7 @@ export const rootRouter = createTRPCRouter({
|
||||
password: passwordRouter,
|
||||
notebook: notebookRouter,
|
||||
layouts: layoutsRouter,
|
||||
integration: integrationRouter,
|
||||
integration: integrationsRouter,
|
||||
});
|
||||
|
||||
// export type definition of API
|
||||
|
||||
@@ -1,13 +1,59 @@
|
||||
import { inArray } from 'drizzle-orm';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { z } from 'zod';
|
||||
import { db } from '~/server/db';
|
||||
import { integrations } from '~/server/db/schema';
|
||||
import { integrationSecrets, integrations } from '~/server/db/schema';
|
||||
|
||||
import { adminProcedure, createTRPCRouter } from '../trpc';
|
||||
|
||||
export const integrationRouter = createTRPCRouter({
|
||||
export const integrationsRouter = createTRPCRouter({
|
||||
allMedia: adminProcedure.query(async () => {
|
||||
return await db.query.integrations.findMany({
|
||||
where: inArray(integrations.type, ['jellyseerr', 'overseerr']),
|
||||
});
|
||||
}),
|
||||
|
||||
findAll: adminProcedure.query(async () => {
|
||||
return await db.query.integrations.findMany({
|
||||
with: {
|
||||
secrets: true,
|
||||
},
|
||||
});
|
||||
}),
|
||||
|
||||
addOne: adminProcedure
|
||||
.input(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
type: z.any(),
|
||||
url: z.string().url(),
|
||||
secrets: z.array(
|
||||
z.object({
|
||||
key: z.string(),
|
||||
value: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ input }) => {
|
||||
const newId = nanoid(8);
|
||||
const integration = await db
|
||||
.insert(integrations)
|
||||
.values({
|
||||
id: newId,
|
||||
name: input.name,
|
||||
type: input.type,
|
||||
url: input.url,
|
||||
})
|
||||
.execute();
|
||||
|
||||
const secrets = await db.insert(integrationSecrets).values(
|
||||
{
|
||||
integrationId: newId,
|
||||
key: 'apiKey',
|
||||
value: 'test'
|
||||
}
|
||||
);
|
||||
return { integration, secrets };
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { MantineColor } from '@mantine/core';
|
||||
import { relations, type InferSelectModel } from 'drizzle-orm';
|
||||
import { type InferSelectModel, relations } from 'drizzle-orm';
|
||||
import { index, int, integer, primaryKey, sqliteTable, text } from 'drizzle-orm/sqlite-core';
|
||||
import { type AdapterAccount } from 'next-auth/adapters';
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ export type IntegrationType =
|
||||
| 'adGuardHome';
|
||||
|
||||
export type AppIntegrationType = {
|
||||
type: IntegrationType | null;
|
||||
type: IntegrationType;
|
||||
properties: AppIntegrationPropertyType[];
|
||||
};
|
||||
|
||||
@@ -69,8 +69,7 @@ export type ConfigAppIntegrationType = Omit<AppIntegrationType, 'properties'> &
|
||||
export type AppIntegrationPropertyType = {
|
||||
type: AppIntegrationPropertyAccessabilityType;
|
||||
field: IntegrationField;
|
||||
value?: string | null;
|
||||
isDefined: boolean;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type AppIntegrationPropertyAccessabilityType = 'private' | 'public';
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@@ -7192,6 +7192,7 @@ __metadata:
|
||||
html-entities: ^2.3.3
|
||||
i18next: ^22.5.1
|
||||
immer: ^10.0.2
|
||||
nanoid: ^5.0.4
|
||||
next: 13.4.12
|
||||
next-auth: ^4.23.0
|
||||
next-i18next: ^14.0.0
|
||||
@@ -8929,6 +8930,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"nanoid@npm:^5.0.4":
|
||||
version: 5.0.4
|
||||
resolution: "nanoid@npm:5.0.4"
|
||||
bin:
|
||||
nanoid: bin/nanoid.js
|
||||
checksum: cf09cca3774f3147100948f7478f75f4c9ee97a4af65c328dd9abbd83b12f8bb35cf9f89a21c330f3b759d667a4cd0140ed84aa5fdd522c61e0d341aeaa7fb6f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"napi-build-utils@npm:^1.0.1":
|
||||
version: 1.0.2
|
||||
resolution: "napi-build-utils@npm:1.0.2"
|
||||
|
||||
Reference in New Issue
Block a user