Sync table from frontend (#4894)

This PR:
- separates the existing updateSyncStatus endpoint into 2 endpoints
- creates mutations and hooks that will call those endpoints
- trigger the hook on toggle
- removes form logic and add a separated component for toggling

---------

Co-authored-by: Thomas Trompette <thomast@twenty.com>
This commit is contained in:
Thomas Trompette
2024-04-11 11:51:49 +02:00
committed by GitHub
parent bea6d4173c
commit aecf8783a0
20 changed files with 372 additions and 149 deletions

View File

@ -1,10 +1,13 @@
import { Controller, useFormContext } from 'react-hook-form';
import { useCallback, useState } from 'react';
import styled from '@emotion/styled';
import { z } from 'zod';
import { useSyncRemoteTable } from '@/databases/hooks/useSyncRemoteTable';
import { useUnsyncRemoteTable } from '@/databases/hooks/useUnsyncRemoteTable';
import { SettingsListCard } from '@/settings/components/SettingsListCard';
import { Toggle } from '@/ui/input/components/Toggle';
import { SettingsIntegrationRemoteTableSyncStatusToggle } from '@/settings/integrations/components/SettingsIntegrationRemoteTableSyncStatusToggle';
import { RemoteTable, RemoteTableStatus } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
export const settingsIntegrationsDatabaseTablesSchema = z.object({
syncedTablesByName: z.record(z.boolean()),
@ -15,6 +18,7 @@ export type SettingsIntegrationsDatabaseTablesFormValues = z.infer<
>;
type SettingsIntegrationDatabaseTablesListCardProps = {
connectionId: string;
tables: RemoteTable[];
};
@ -25,27 +29,63 @@ const StyledRowRightContainer = styled.div`
`;
export const SettingsIntegrationDatabaseTablesListCard = ({
connectionId,
tables,
}: SettingsIntegrationDatabaseTablesListCardProps) => {
const { control } =
useFormContext<SettingsIntegrationsDatabaseTablesFormValues>();
const { syncRemoteTable } = useSyncRemoteTable();
const { unsyncRemoteTable } = useUnsyncRemoteTable();
// We need to use a state because the table status update re-render the whole list of toggles
const [items] = useState(
tables.map((table) => ({
id: table.name,
...table,
})),
);
const onSyncUpdate = useCallback(
async (isSynced: boolean, tableName: string) => {
const table = items.find((table) => table.name === tableName);
if (!isDefined(table)) return;
if (isSynced) {
await syncRemoteTable({
remoteServerId: connectionId,
name: tableName,
schema: table.schema,
});
} else {
await unsyncRemoteTable({
remoteServerId: connectionId,
name: tableName,
schema: table.schema,
});
}
},
[connectionId, syncRemoteTable, items, unsyncRemoteTable],
);
const rowRightComponent = useCallback(
({
item,
}: {
item: { id: string; name: string; status: RemoteTableStatus };
}) => (
<StyledRowRightContainer>
<SettingsIntegrationRemoteTableSyncStatusToggle
table={item}
onSyncUpdate={onSyncUpdate}
/>
</StyledRowRightContainer>
),
[onSyncUpdate],
);
return (
<SettingsListCard
items={tables.map((table) => ({ id: table.name, ...table }))}
RowRightComponent={({ item: table }) => (
<StyledRowRightContainer>
<Controller
name={`syncedTablesByName.${table.name}`}
control={control}
defaultValue={table.status === RemoteTableStatus.Synced}
render={({ field: { onChange, value } }) => (
<Toggle value={value} onChange={onChange} />
)}
/>
</StyledRowRightContainer>
)}
getItemLabel={(table) => table.name}
items={items}
RowRightComponent={rowRightComponent}
getItemLabel={(table) => table.id}
/>
);
};

View File

@ -0,0 +1,29 @@
import { useState } from 'react';
import { Toggle } from '@/ui/input/components/Toggle';
import { RemoteTableStatus } from '~/generated-metadata/graphql';
export const SettingsIntegrationRemoteTableSyncStatusToggle = ({
table,
onSyncUpdate,
}: {
table: { id: string; name: string; status: RemoteTableStatus };
onSyncUpdate: (value: boolean, tableName: string) => Promise<void>;
}) => {
const [isToggleLoading, setIsToggleLoading] = useState(false);
const onChange = async (newValue: boolean) => {
if (isToggleLoading) return;
setIsToggleLoading(true);
await onSyncUpdate(newValue, table.name);
setIsToggleLoading(false);
};
return (
<Toggle
value={table.status === RemoteTableStatus.Synced}
disabled={isToggleLoading}
onChange={onChange}
/>
);
};