Skip to content

Commit 50b6863

Browse files
authored
feat: create Integrations/IntegrationDetail page (twentyhq#4574)
* feat: create Integrations/IntegrationDetail page Closes twentyhq#4546 * docs: add Settings/Integrations/Integration Detail page stories * docs: add Settings/Billing page stories * refactor: move some Settings components to @/settings * refactor: move some Settings integrations components to @/settings/integrations
1 parent cc8a652 commit 50b6863

31 files changed

+335
-174
lines changed
Loading
Loading

packages/twenty-front/src/App.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { SettingsDevelopersApiKeysNew } from '~/pages/settings/developers/api-ke
3838
import { SettingsDevelopers } from '~/pages/settings/developers/SettingsDevelopers';
3939
import { SettingsDevelopersWebhooksDetail } from '~/pages/settings/developers/webhooks/SettingsDevelopersWebhookDetail';
4040
import { SettingsDevelopersWebhooksNew } from '~/pages/settings/developers/webhooks/SettingsDevelopersWebhooksNew';
41+
import { SettingsIntegrationDetail } from '~/pages/settings/integrations/SettingsIntegrationDetail';
4142
import { SettingsIntegrations } from '~/pages/settings/integrations/SettingsIntegrations';
4243
import { SettingsAppearance } from '~/pages/settings/SettingsAppearance';
4344
import { SettingsBilling } from '~/pages/settings/SettingsBilling.tsx';
@@ -170,6 +171,10 @@ export const App = () => {
170171
path={SettingsPath.Integrations}
171172
element={<SettingsIntegrations />}
172173
/>
174+
<Route
175+
path={SettingsPath.IntegrationDetail}
176+
element={<SettingsIntegrationDetail />}
177+
/>
173178
<Route
174179
path={SettingsPath.ObjectNewFieldStep1}
175180
element={<SettingsObjectNewFieldStep1 />}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { useNavigate } from 'react-router-dom';
2+
import styled from '@emotion/styled';
3+
4+
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
5+
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
6+
import { SettingsApiKeysFieldItemTableRow } from '@/settings/developers/components/SettingsApiKeysFieldItemTableRow';
7+
import { ApiFieldItem } from '@/settings/developers/types/api-key/ApiFieldItem';
8+
import { ApiKey } from '@/settings/developers/types/api-key/ApiKey';
9+
import { formatExpirations } from '@/settings/developers/utils/format-expiration';
10+
import { Table } from '@/spreadsheet-import/components/Table';
11+
import { TableBody } from '@/ui/layout/table/components/TableBody';
12+
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
13+
import { TableRow } from '@/ui/layout/table/components/TableRow';
14+
15+
const StyledTableBody = styled(TableBody)`
16+
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
17+
`;
18+
19+
const StyledTableRow = styled(TableRow)`
20+
grid-template-columns: 312px 132px 68px;
21+
`;
22+
23+
export const SettingsApiKeysTable = () => {
24+
const navigate = useNavigate();
25+
26+
const { records: apiKeys } = useFindManyRecords<ApiKey>({
27+
objectNameSingular: CoreObjectNameSingular.ApiKey,
28+
filter: { revokedAt: { is: 'NULL' } },
29+
});
30+
31+
return (
32+
<Table>
33+
<StyledTableRow>
34+
<TableHeader>Name</TableHeader>
35+
<TableHeader>Expiration</TableHeader>
36+
<TableHeader></TableHeader>
37+
</StyledTableRow>
38+
{!!apiKeys.length && (
39+
<StyledTableBody>
40+
{formatExpirations(apiKeys).map((fieldItem) => (
41+
<SettingsApiKeysFieldItemTableRow
42+
key={fieldItem.id}
43+
fieldItem={fieldItem as ApiFieldItem}
44+
onClick={() => {
45+
navigate(`/settings/developers/api-keys/${fieldItem.id}`);
46+
}}
47+
/>
48+
))}
49+
</StyledTableBody>
50+
)}
51+
</Table>
52+
);
53+
};

packages/twenty-front/src/pages/settings/developers/components/ReadDocumentationButton.tsx renamed to packages/twenty-front/src/modules/settings/developers/components/SettingsReadDocumentationButton.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { IconBook2 } from '@/ui/display/icon';
22
import { Button } from '@/ui/input/button/components/Button';
33

4-
export const ReadDocumentationButton = () => {
4+
export const SettingsReadDocumentationButton = () => {
55
return (
66
<Button
77
title="Read documentation"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { useNavigate } from 'react-router-dom';
2+
import styled from '@emotion/styled';
3+
4+
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
5+
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
6+
import { SettingsDevelopersWebhookTableRow } from '@/settings/developers/components/SettingsDevelopersWebhookTableRow';
7+
import { WebhookFieldItem } from '@/settings/developers/types/webhook/WebhookFieldItem';
8+
import { Table } from '@/ui/layout/table/components/Table';
9+
import { TableBody } from '@/ui/layout/table/components/TableBody';
10+
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
11+
import { TableRow } from '@/ui/layout/table/components/TableRow';
12+
13+
const StyledTableBody = styled(TableBody)`
14+
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
15+
`;
16+
17+
const StyledTableRow = styled(TableRow)`
18+
grid-template-columns: 444px 68px;
19+
`;
20+
21+
export const SettingsWebhooksTable = () => {
22+
const navigate = useNavigate();
23+
24+
const { records: webhooks } = useFindManyRecords<WebhookFieldItem>({
25+
objectNameSingular: CoreObjectNameSingular.Webhook,
26+
});
27+
28+
return (
29+
<Table>
30+
<StyledTableRow>
31+
<TableHeader>Url</TableHeader>
32+
<TableHeader></TableHeader>
33+
</StyledTableRow>
34+
{!!webhooks.length && (
35+
<StyledTableBody>
36+
{webhooks.map((webhookFieldItem) => (
37+
<SettingsDevelopersWebhookTableRow
38+
key={webhookFieldItem.id}
39+
fieldItem={webhookFieldItem}
40+
onClick={() => {
41+
navigate(
42+
`/settings/developers/webhooks/${webhookFieldItem.id}`,
43+
);
44+
}}
45+
/>
46+
))}
47+
</StyledTableBody>
48+
)}
49+
</Table>
50+
);
51+
};

packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationGroup.tsx renamed to packages/twenty-front/src/modules/settings/integrations/components/SettingsIntegrationGroup.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import styled from '@emotion/styled';
22

3+
import { SettingsIntegrationComponent } from '@/settings/integrations/components/SettingsIntegrationComponent';
34
import { H2Title } from '@/ui/display/typography/components/H2Title';
45
import { Section } from '@/ui/layout/section/components/Section';
5-
import { SettingsIntegrationComponent } from '~/pages/settings/integrations/SettingsIntegrationComponent';
66
import { SettingsIntegrationCategory } from '~/pages/settings/integrations/types/SettingsIntegrationCategory';
77

88
interface SettingsIntegrationGroupProps {

packages/twenty-front/src/modules/types/SettingsPath.ts

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export enum SettingsPath {
2121
DevelopersNewApiKey = 'api-keys/new',
2222
DevelopersApiKeyDetail = 'api-keys/:apiKeyId',
2323
Integrations = 'integrations',
24+
IntegrationDetail = 'integrations/:integrationKey',
2425
DevelopersNewWebhook = 'webhooks/new',
2526
DevelopersNewWebhookDetail = 'webhooks/:webhookId',
2627
}

packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ export type FeatureFlagKey =
22
| 'IS_BLOCKLIST_ENABLED'
33
| 'IS_CALENDAR_ENABLED'
44
| 'IS_QUICK_ACTIONS_ENABLED'
5-
| 'IS_EVENT_OBJECT_ENABLED';
5+
| 'IS_EVENT_OBJECT_ENABLED'
6+
| 'IS_AIRTABLE_INTEGRATION_ENABLED'
7+
| 'IS_POSTGRESQL_INTEGRATION_ENABLED';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Meta, StoryObj } from '@storybook/react';
2+
3+
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
4+
import { SettingsPath } from '@/types/SettingsPath';
5+
import {
6+
PageDecorator,
7+
PageDecoratorArgs,
8+
} from '~/testing/decorators/PageDecorator';
9+
import { graphqlMocks } from '~/testing/graphqlMocks';
10+
11+
import { SettingsBilling } from '../SettingsBilling';
12+
13+
const meta: Meta<PageDecoratorArgs> = {
14+
title: 'Pages/Settings/SettingsBilling',
15+
component: SettingsBilling,
16+
decorators: [PageDecorator],
17+
args: { routePath: getSettingsPagePath(SettingsPath.Billing) },
18+
parameters: {
19+
msw: graphqlMocks,
20+
},
21+
};
22+
23+
export default meta;
24+
25+
export type Story = StoryObj<typeof SettingsBilling>;
26+
27+
export const Default: Story = {};

packages/twenty-front/src/pages/settings/accounts/SettingsAccounts.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useRecoilValue } from 'recoil';
33
import { ConnectedAccount } from '@/accounts/types/ConnectedAccount';
44
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
55
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
6+
import { SettingsAccountLoader } from '@/settings/accounts/components/SettingsAccountLoader';
67
import { SettingsAccountsConnectedAccountsSection } from '@/settings/accounts/components/SettingsAccountsConnectedAccountsSection';
78
import { SettingsAccountsEmailsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistSection';
89
import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/SettingsAccountsSettingsSection';
@@ -11,7 +12,6 @@ import { IconSettings } from '@/ui/display/icon';
1112
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
1213
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
1314
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
14-
import { SettingsAccountLoader } from '~/pages/settings/accounts/SettingsAccountLoader';
1515

1616
export const SettingsAccounts = () => {
1717
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);

packages/twenty-front/src/pages/settings/developers/SettingsDevelopers.tsx

+54-7
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,70 @@
1+
import { useNavigate } from 'react-router-dom';
2+
import styled from '@emotion/styled';
3+
14
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
25
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
3-
import { IconSettings } from '@/ui/display/icon';
6+
import { SettingsApiKeysTable } from '@/settings/developers/components/SettingsApiKeysTable';
7+
import { SettingsReadDocumentationButton } from '@/settings/developers/components/SettingsReadDocumentationButton';
8+
import { SettingsWebhooksTable } from '@/settings/developers/components/SettingsWebhooksTable';
9+
import { IconPlus, IconSettings } from '@/ui/display/icon';
10+
import { H2Title } from '@/ui/display/typography/components/H2Title';
11+
import { Button } from '@/ui/input/button/components/Button';
412
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
13+
import { Section } from '@/ui/layout/section/components/Section';
514
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
6-
import { SettingsDevelopersApiKeys } from '~/pages/settings/developers/api-keys/SettingsDevelopersApiKeys';
7-
import { SettingsDevelopersWebhooks } from '~/pages/settings/developers/webhooks/SettingsDevelopersWebhooks';
815

9-
import { ReadDocumentationButton } from './components/ReadDocumentationButton';
16+
const StyledButtonContainer = styled.div`
17+
display: flex;
18+
justify-content: flex-end;
19+
padding-top: ${({ theme }) => theme.spacing(2)};
20+
`;
1021

1122
export const SettingsDevelopers = () => {
23+
const navigate = useNavigate();
24+
1225
return (
1326
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
1427
<SettingsPageContainer>
1528
<SettingsHeaderContainer>
1629
<Breadcrumb links={[{ children: 'Developers' }]} />
17-
<ReadDocumentationButton />
30+
<SettingsReadDocumentationButton />
1831
</SettingsHeaderContainer>
19-
<SettingsDevelopersApiKeys />
20-
<SettingsDevelopersWebhooks />
32+
<Section>
33+
<H2Title
34+
title="API keys"
35+
description="Active APIs keys created by you or your team."
36+
/>
37+
<SettingsApiKeysTable />
38+
<StyledButtonContainer>
39+
<Button
40+
Icon={IconPlus}
41+
title="Create API key"
42+
size="small"
43+
variant="secondary"
44+
onClick={() => {
45+
navigate('/settings/developers/api-keys/new');
46+
}}
47+
/>
48+
</StyledButtonContainer>
49+
</Section>
50+
<Section>
51+
<H2Title
52+
title="Webhooks"
53+
description="Establish Webhook endpoints for notifications on asynchronous events."
54+
/>
55+
<SettingsWebhooksTable />
56+
<StyledButtonContainer>
57+
<Button
58+
Icon={IconPlus}
59+
title="Create Webhook"
60+
size="small"
61+
variant="secondary"
62+
onClick={() => {
63+
navigate('/settings/developers/webhooks/new');
64+
}}
65+
/>
66+
</StyledButtonContainer>
67+
</Section>
2168
</SettingsPageContainer>
2269
</SubMenuTopBarContainer>
2370
);

packages/twenty-front/src/pages/settings/developers/__stories__/SettingsDevelopersWebhooksDetail.stories.tsx renamed to packages/twenty-front/src/pages/settings/developers/__stories__/webhooks/SettingsDevelopersWebhooksDetail.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
import { graphqlMocks } from '~/testing/graphqlMocks';
1111

1212
const meta: Meta<PageDecoratorArgs> = {
13-
title: 'Pages/Settings/Developers/SettingsDevelopersWebhooksDetail',
13+
title: 'Pages/Settings/Developers/Webhooks/SettingsDevelopersWebhooksDetail',
1414
component: SettingsDevelopersWebhooksDetail,
1515
decorators: [PageDecorator],
1616
args: {

packages/twenty-front/src/pages/settings/developers/__stories__/SettingsDevelopersWebhooksNew.stories.tsx renamed to packages/twenty-front/src/pages/settings/developers/__stories__/webhooks/SettingsDevelopersWebhooksNew.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
import { graphqlMocks } from '~/testing/graphqlMocks';
1010

1111
const meta: Meta<PageDecoratorArgs> = {
12-
title: 'Pages/Settings/Developers/SettingsDevelopersWebhooksNew',
12+
title: 'Pages/Settings/Developers/Webhooks/SettingsDevelopersWebhooksNew',
1313
component: SettingsDevelopersWebhooksNew,
1414
decorators: [PageDecorator],
1515
args: { routePath: '/settings/developers' },

packages/twenty-front/src/pages/settings/developers/api-keys/SettingsDevelopersApiKeys.tsx

-80
This file was deleted.

0 commit comments

Comments
 (0)