feat: add Tables settings to Settings/Integrations/Database/Connectio… (#4851)

…n page

Closes #4560
This commit is contained in:
Thaïs 2024-04-05 18:12:54 +02:00 committed by GitHub
parent f4017119ab
commit bbdb926687
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 112 additions and 31 deletions

View File

@ -42,7 +42,7 @@ type SettingsListCardProps<ListItem extends { id: string }> = {
hasFooter?: boolean;
isLoading?: boolean;
onRowClick?: (item: ListItem) => void;
RowIcon: IconComponent;
RowIcon?: IconComponent;
RowRightComponent: ComponentType<{ item: ListItem }>;
footerButtonLabel?: string;
onFooterButtonClick?: () => void;

View File

@ -14,16 +14,17 @@ const StyledRow = styled(CardContent)`
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(3)};
min-height: ${({ theme }) => theme.spacing(6)};
`;
const StyledAccountHandle = styled.span`
const StyledLabel = styled.span`
flex: 1 0 auto;
`;
type SettingsListItemCardContentProps = {
label: string;
divider?: boolean;
LeftIcon: IconComponent;
LeftIcon?: IconComponent;
onClick?: () => void;
rightComponent: ReactNode;
};
@ -39,8 +40,8 @@ export const SettingsListItemCardContent = ({
return (
<StyledRow onClick={onClick} divider={divider}>
<LeftIcon size={theme.icon.size.md} />
<StyledAccountHandle>{label}</StyledAccountHandle>
{!!LeftIcon && <LeftIcon size={theme.icon.size.md} />}
<StyledLabel>{label}</StyledLabel>
{rightComponent}
</StyledRow>
);

View File

@ -0,0 +1,50 @@
import { Controller, useFormContext } from 'react-hook-form';
import styled from '@emotion/styled';
import { z } from 'zod';
import { SettingsListCard } from '@/settings/components/SettingsListCard';
import { Toggle } from '@/ui/input/components/Toggle';
export const settingsIntegrationsDatabaseTablesSchema = z.object({
syncedTablesById: z.record(z.boolean()),
});
export type SettingsIntegrationsDatabaseTablesFormValues = z.infer<
typeof settingsIntegrationsDatabaseTablesSchema
>;
type SettingsIntegrationDatabaseTablesListCardProps = {
tables: { id: string; name: string; isSynced?: boolean }[];
};
const StyledRowRightContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
`;
export const SettingsIntegrationDatabaseTablesListCard = ({
tables,
}: SettingsIntegrationDatabaseTablesListCardProps) => {
const { control } =
useFormContext<SettingsIntegrationsDatabaseTablesFormValues>();
return (
<SettingsListCard
items={tables}
RowRightComponent={({ item: table }) => (
<StyledRowRightContainer>
<Controller
name={`syncedTablesById.${table.id}`}
control={control}
defaultValue={!!table.isSynced}
render={({ field: { onChange, value } }) => (
<Toggle value={value} onChange={onChange} />
)}
/>
</StyledRowRightContainer>
)}
getItemLabel={(table) => table.name}
/>
);
};

View File

@ -1,8 +1,15 @@
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import { zodResolver } from '@hookform/resolvers/zod';
import { IconSettings } from 'twenty-ui';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import {
SettingsIntegrationDatabaseTablesListCard,
SettingsIntegrationsDatabaseTablesFormValues,
settingsIntegrationsDatabaseTablesSchema,
} from '@/settings/integrations/components/SettingsIntegrationDatabaseTablesListCard';
import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { AppPath } from '@/types/AppPath';
@ -47,37 +54,54 @@ export const SettingsIntegrationDatabaseConnection = () => {
}
}, [integration, databaseKey, navigate, isIntegrationAvailable, connection]);
const formConfig = useForm<SettingsIntegrationsDatabaseTablesFormValues>({
mode: 'onTouched',
resolver: zodResolver(settingsIntegrationsDatabaseTablesSchema),
});
if (!isIntegrationAvailable || !connection) return null;
const settingsIntegrationsPagePath = getSettingsPagePath(
SettingsPath.Integrations,
);
const tables = mockedRemoteObjectIntegrations[0].connections[0].tables;
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<Breadcrumb
links={[
{
children: 'Integrations',
href: settingsIntegrationsPagePath,
},
{
children: integration.text,
href: `${settingsIntegrationsPagePath}/${databaseKey}`,
},
{ children: connection.name },
]}
/>
<Section>
<H2Title title="About" description="About this remote object" />
<SettingsIntegrationDatabaseConnectionSummaryCard
databaseLogoUrl={integration.from.image}
connectionName={connection.name}
connectedTablesNb={connection.tables.length}
// eslint-disable-next-line react/jsx-props-no-spreading
<FormProvider {...formConfig}>
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<Breadcrumb
links={[
{
children: 'Integrations',
href: settingsIntegrationsPagePath,
},
{
children: integration.text,
href: `${settingsIntegrationsPagePath}/${databaseKey}`,
},
{ children: connection.name },
]}
/>
</Section>
</SettingsPageContainer>
</SubMenuTopBarContainer>
<Section>
<H2Title title="About" description="About this remote object" />
<SettingsIntegrationDatabaseConnectionSummaryCard
databaseLogoUrl={integration.from.image}
connectionName={connection.name}
connectedTablesNb={tables.length}
/>
</Section>
<Section>
<H2Title
title="Tables"
description="Select the tables that should be tracked"
/>
<SettingsIntegrationDatabaseTablesListCard tables={tables} />
</Section>
</SettingsPageContainer>
</SubMenuTopBarContainer>
</FormProvider>
);
};

View File

@ -7,13 +7,19 @@ export const mockedRemoteObjectIntegrations = [
id: '67cbfd35-8dd4-4591-b9d4-c1906281a5da',
key: 'twenty_postgres',
name: 'Twenty_postgres',
tables: [{ name: '1' }],
tables: [
{ id: 'invoices', name: 'Invoices' },
{ id: 'quotes', name: 'Quotes', isSynced: true },
{ id: 'customers', name: 'Customers', isSynced: false },
{ id: 'subscriptions', name: 'Subscriptions', isSynced: true },
{ id: 'payments', name: 'Payments' },
],
},
{
id: '3740cd85-7a1e-45b5-8b0d-47e1921d01f3',
key: 'image_postgres',
name: 'Image_postgres',
tables: [{ name: '2' }, { name: '3' }],
tables: [],
},
],
},