feat: soft delete (#6576)

Implement soft delete on standards and custom objects.
This is a temporary solution, when we drop `pg_graphql` we should rely
on the `softDelete` functions of TypeORM.

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Jérémy M
2024-08-16 21:20:02 +02:00
committed by GitHub
parent 20d84755bb
commit db54469c8a
118 changed files with 1675 additions and 492 deletions

View File

@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
import rehypeStringify from 'rehype-stringify';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import { H1Title, IconSettings } from 'twenty-ui';
import { H1Title, IconRocket } from 'twenty-ui';
import { unified } from 'unified';
import { visit } from 'unist-util-visit';
@ -108,7 +108,7 @@ export const Releases = () => {
}, []);
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Releases">
<SubMenuTopBarContainer Icon={IconRocket} title="Releases">
<SettingsPageContainer>
<StyledH1Title title="Releases" />
<ScrollWrapper>

View File

@ -1,5 +1,4 @@
import styled from '@emotion/styled';
import { H1Title, H2Title, IconSettings } from 'twenty-ui';
import { H2Title, IconUserCircle } from 'twenty-ui';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { ChangePassword } from '@/settings/profile/components/ChangePassword';
@ -10,14 +9,9 @@ import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePic
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
const StyledH1Title = styled(H1Title)`
margin-bottom: 0;
`;
export const SettingsProfile = () => (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer Icon={IconUserCircle} title="Profile">
<SettingsPageContainer>
<StyledH1Title title="Profile" />
<Section>
<H2Title title="Picture" />
<ProfilePictureUploader />

View File

@ -1,5 +1,4 @@
import styled from '@emotion/styled';
import { H1Title, H2Title, IconSettings } from 'twenty-ui';
import { H2Title, IconSettings } from 'twenty-ui';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { DeleteWorkspace } from '@/settings/profile/components/DeleteWorkspace';
@ -9,14 +8,9 @@ import { WorkspaceLogoUploader } from '@/settings/workspace/components/Workspace
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
const StyledH1Title = styled(H1Title)`
margin-bottom: 0;
`;
export const SettingsWorkspace = () => (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer Icon={IconSettings} title="General">
<SettingsPageContainer>
<StyledH1Title title="General" />
<Section>
<H2Title title="Picture" />
<WorkspaceLogoUploader />

View File

@ -1,7 +1,7 @@
import styled from '@emotion/styled';
import { useState } from 'react';
import { useRecoilValue } from 'recoil';
import { H1Title, H2Title, IconSettings, IconTrash } from 'twenty-ui';
import { H2Title, IconTrash, IconUsers } from 'twenty-ui';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
@ -18,10 +18,6 @@ import { WorkspaceInviteLink } from '@/workspace/components/WorkspaceInviteLink'
import { WorkspaceInviteTeam } from '@/workspace/components/WorkspaceInviteTeam';
import { WorkspaceMemberCard } from '@/workspace/components/WorkspaceMemberCard';
const StyledH1Title = styled(H1Title)`
margin-bottom: 0;
`;
const StyledButtonContainer = styled.div`
align-items: center;
display: flex;
@ -50,9 +46,8 @@ export const SettingsWorkspaceMembers = () => {
};
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer Icon={IconUsers} title="Members">
<SettingsPageContainer>
<StyledH1Title title="Members" />
<Section>
<H2Title
title="Invite by email"

View File

@ -1,5 +1,5 @@
import { useRecoilValue } from 'recoil';
import { H2Title, IconSettings } from 'twenty-ui';
import { H2Title, IconAt } from 'twenty-ui';
import { ConnectedAccount } from '@/accounts/types/ConnectedAccount';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
@ -14,7 +14,6 @@ import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
export const SettingsAccounts = () => {
@ -37,10 +36,8 @@ export const SettingsAccounts = () => {
const isBlocklistEnabled = useIsFeatureEnabled('IS_BLOCKLIST_ENABLED');
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer Icon={IconAt} title="Account">
<SettingsPageContainer>
<Breadcrumb links={[{ children: 'Accounts' }]} />
{loading ? (
<SettingsAccountLoader />
) : (

View File

@ -1,5 +1,3 @@
import { IconSettings } from 'twenty-ui';
import { SettingsAccountsCalendarChannelsContainer } from '@/settings/accounts/components/SettingsAccountsCalendarChannelsContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
@ -7,11 +5,13 @@ import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { IconCalendarEvent } from 'twenty-ui';
export const SettingsAccountsCalendars = () => {
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<SubMenuTopBarContainer
Icon={IconCalendarEvent}
title={
<Breadcrumb
links={[
{
@ -21,6 +21,9 @@ export const SettingsAccountsCalendars = () => {
{ children: 'Calendars' },
]}
/>
}
>
<SettingsPageContainer>
<Section>
<SettingsAccountsCalendarChannelsContainer />
</Section>

View File

@ -1,20 +1,23 @@
import { IconSettings } from 'twenty-ui';
import { SettingsAccountsMessageChannelsContainer } from '@/settings/accounts/components/SettingsAccountsMessageChannelsContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { IconMail } from 'twenty-ui';
export const SettingsAccountsEmails = () => (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<SubMenuTopBarContainer
Icon={IconMail}
title={
<Breadcrumb
links={[
{ children: 'Accounts', href: '/settings/accounts' },
{ children: 'Emails' },
]}
/>
}
>
<SettingsPageContainer>
<Section>
<SettingsAccountsMessageChannelsContainer />
</Section>

View File

@ -1,20 +1,23 @@
import { IconSettings } from 'twenty-ui';
import { SettingsNewAccountSection } from '@/settings/accounts/components/SettingsNewAccountSection';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { IconAt } from 'twenty-ui';
export const SettingsNewAccount = () => {
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<SubMenuTopBarContainer
Icon={IconAt}
title={
<Breadcrumb
links={[
{ children: 'Accounts', href: '/settings/accounts' },
{ children: `New` },
]}
/>
}
>
<SettingsPageContainer>
<SettingsNewAccountSection />
</SettingsPageContainer>
</SubMenuTopBarContainer>

View File

@ -16,12 +16,13 @@ const REVERT_PUBLIC_KEY = 'pk_live_a87fee8c-28c7-494f-99a3-996ff89f9918';
export const SettingsCRMMigration = () => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconSettings}
title={<Breadcrumb links={[{ children: 'Migrate' }]} />}
actionButton={<SettingsReadDocumentationButton />}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb links={[{ children: 'Migrate' }]} />
<SettingsReadDocumentationButton />
</SettingsHeaderContainer>
<SettingsHeaderContainer></SettingsHeaderContainer>
<Section>
<RevertConnect
config={{

View File

@ -1,7 +1,7 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { H2Title, IconSettings } from 'twenty-ui';
import { H2Title, IconHierarchy2 } from 'twenty-ui';
import { z } from 'zod';
import { useCreateOneObjectMetadataItem } from '@/object-metadata/hooks/useCreateOneObjectMetadataItem';
@ -70,25 +70,30 @@ export const SettingsNewObject = () => {
return (
// eslint-disable-next-line react/jsx-props-no-spreading
<FormProvider {...formConfig}>
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title={
<Breadcrumb
links={[
{
children: 'Objects',
href: settingsObjectsPagePath,
},
{ children: 'New' },
]}
/>
}
actionButton={
<SaveAndCancelButtons
isSaveDisabled={!canSave}
isCancelDisabled={isSubmitting}
onCancel={() => navigate(settingsObjectsPagePath)}
onSave={formConfig.handleSubmit(handleSave)}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{
children: 'Objects',
href: settingsObjectsPagePath,
},
{ children: 'New' },
]}
/>
<SaveAndCancelButtons
isSaveDisabled={!canSave}
isCancelDisabled={isSubmitting}
onCancel={() => navigate(settingsObjectsPagePath)}
onSave={formConfig.handleSubmit(handleSave)}
/>
</SettingsHeaderContainer>
<SettingsHeaderContainer></SettingsHeaderContainer>
<Section>
<H2Title
title="About"

View File

@ -1,12 +1,7 @@
import styled from '@emotion/styled';
import { useNavigate } from 'react-router-dom';
import { H2Title, IconPlus, IconSettings } from 'twenty-ui';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getDisabledFieldMetadataItems } from '@/object-metadata/utils/getDisabledFieldMetadataItems';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsObjectSummaryCard } from '@/settings/data-model/object-details/components/SettingsObjectSummaryCard';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
@ -15,7 +10,10 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink';
import styled from '@emotion/styled';
import { isNonEmptyArray } from '@sniptt/guards';
import { useNavigate } from 'react-router-dom';
import { H2Title, IconHierarchy2, IconPlus } from 'twenty-ui';
import { SettingsObjectFieldTable } from '~/pages/settings/data-model/SettingsObjectFieldTable';
const StyledDiv = styled.div`
@ -49,14 +47,18 @@ export const SettingsObjectDetailPageContent = ({
const shouldDisplayAddFieldButton = !objectMetadataItem.isRemote;
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title={
<Breadcrumb
links={[
{ children: 'Objects', href: '/settings/objects' },
{ children: objectMetadataItem.labelPlural },
]}
/>
}
>
<SettingsPageContainer>
<Section>
<H2Title title="About" description="Manage your object" />
<SettingsObjectSummaryCard

View File

@ -5,12 +5,13 @@ import pick from 'lodash.pick';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import { H2Title, IconArchive, IconSettings } from 'twenty-ui';
import { H2Title, IconArchive, IconHierarchy2 } from 'twenty-ui';
import { z } from 'zod';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
@ -30,7 +31,6 @@ import { Button } from '@/ui/input/button/components/Button';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
const objectEditFormSchema = z
.object({})
@ -108,22 +108,26 @@ export const SettingsObjectEdit = () => {
return (
<RecordFieldValueSelectorContextProvider>
<FormProvider {...formConfig}>
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title={
<Breadcrumb
links={[
{
children: 'Objects',
href: settingsObjectsPagePath,
},
{
children: activeObjectMetadataItem.labelPlural,
href: `${settingsObjectsPagePath}/${objectSlug}`,
},
{ children: 'Edit' },
]}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{
children: 'Objects',
href: settingsObjectsPagePath,
},
{
children: activeObjectMetadataItem.labelPlural,
href: `${settingsObjectsPagePath}/${objectSlug}`,
},
{ children: 'Edit' },
]}
/>
{activeObjectMetadataItem.isCustom && (
<SaveAndCancelButtons
isSaveDisabled={!canSave}

View File

@ -6,7 +6,7 @@ import pick from 'lodash.pick';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import { H2Title, IconArchive, IconSettings } from 'twenty-ui';
import { H2Title, IconArchive, IconHierarchy2 } from 'twenty-ui';
import { z } from 'zod';
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
@ -172,19 +172,23 @@ export const SettingsObjectFieldEdit = () => {
<RecordFieldValueSelectorContextProvider>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<FormProvider {...formConfig}>
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title={
<Breadcrumb
links={[
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectSlug}`,
},
{ children: activeMetadataField.label },
]}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectSlug}`,
},
{ children: activeMetadataField.label },
]}
/>
{shouldDisplaySaveAndCancel && (
<SaveAndCancelButtons
isSaveDisabled={!canSave}

View File

@ -5,7 +5,6 @@ import { H2Title, IconPlus, IconSettings } from 'twenty-ui';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
@ -85,27 +84,31 @@ export const SettingsObjectNewFieldStep1 = () => {
if (!activeObjectMetadataItem) return null;
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectSlug}`,
},
{ children: 'New Field' },
]}
<SubMenuTopBarContainer
Icon={IconSettings}
title={
<Breadcrumb
links={[
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectSlug}`,
},
{ children: 'New Field' },
]}
/>
}
actionButton={
!activeObjectMetadataItem.isRemote && (
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => navigate(`/settings/objects/${objectSlug}`)}
onSave={handleSave}
/>
{!activeObjectMetadataItem.isRemote && (
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => navigate(`/settings/objects/${objectSlug}`)}
onSave={handleSave}
/>
)}
</SettingsHeaderContainer>
)
}
>
<SettingsPageContainer>
<StyledSection>
<H2Title
title="Check deactivated fields"

View File

@ -1,12 +1,25 @@
import { ReactFlowProvider } from 'reactflow';
import { IconSettings } from 'twenty-ui';
import { SettingsDataModelOverview } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverview';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { IconHierarchy2 } from 'twenty-ui';
export const SettingsObjectOverview = () => {
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title={
<Breadcrumb
links={[
{ children: 'Data model', href: '/settings/objects' },
{
children: 'Overview',
},
]}
/>
}
>
<ReactFlowProvider>
<SettingsDataModelOverview />
</ReactFlowProvider>

View File

@ -1,19 +1,12 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import {
H1Title,
H2Title,
IconChevronRight,
IconPlus,
IconSettings,
} from 'twenty-ui';
import { H2Title, IconChevronRight, IconHierarchy2, IconPlus } from 'twenty-ui';
import { useDeleteOneObjectMetadataItem } from '@/object-metadata/hooks/useDeleteOneObjectMetadataItem';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
import { useCombinedGetTotalCount } from '@/object-record/multiple-objects/hooks/useCombinedGetTotalCount';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import {
SettingsObjectMetadataItemTableRow,
@ -42,10 +35,6 @@ const StyledIconChevronRight = styled(IconChevronRight)`
color: ${({ theme }) => theme.font.color.tertiary};
`;
const StyledH1Title = styled(H1Title)`
margin-bottom: 0;
`;
export const SettingsObjects = () => {
const theme = useTheme();
@ -115,19 +104,21 @@ export const SettingsObjects = () => {
);
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title="Data model"
actionButton={
<UndecoratedLink to={getSettingsPagePath(SettingsPath.NewObject)}>
<Button
Icon={IconPlus}
title="Add object"
accent="blue"
size="small"
/>
</UndecoratedLink>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<StyledH1Title title="Objects" />
<UndecoratedLink to={getSettingsPagePath(SettingsPath.NewObject)}>
<Button
Icon={IconPlus}
title="Add object"
accent="blue"
size="small"
/>
</UndecoratedLink>
</SettingsHeaderContainer>
<>
<SettingsObjectCoverImage />
<Section>

View File

@ -1,7 +1,6 @@
import styled from '@emotion/styled';
import { H2Title, IconPlus, IconSettings } from 'twenty-ui';
import { H2Title, IconCode, IconPlus } from 'twenty-ui';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsApiKeysTable } from '@/settings/developers/components/SettingsApiKeysTable';
import { SettingsReadDocumentationButton } from '@/settings/developers/components/SettingsReadDocumentationButton';
@ -9,7 +8,6 @@ import { SettingsWebhooksTable } from '@/settings/developers/components/Settings
import { Button } from '@/ui/input/button/components/Button';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
const StyledButtonContainer = styled.div`
display: flex;
@ -19,12 +17,12 @@ const StyledButtonContainer = styled.div`
export const SettingsDevelopers = () => {
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconCode}
title="Developers"
actionButton={<SettingsReadDocumentationButton />}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb links={[{ children: 'Developers' }]} />
<SettingsReadDocumentationButton />
</SettingsHeaderContainer>
<Section>
<H2Title
title="API keys"

View File

@ -4,16 +4,16 @@ import { DateTime } from 'luxon';
import { useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useRecoilState } from 'recoil';
import { H2Title, IconRepeat, IconSettings, IconTrash } from 'twenty-ui';
import { H2Title, IconCode, IconRepeat, IconTrash } from 'twenty-ui';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { ApiKeyInput } from '@/settings/developers/components/ApiKeyInput';
import { ApiKeyNameInput } from '@/settings/developers/components/ApiKeyNameInput';
import { apiKeyTokenState } from '@/settings/developers/states/generatedApiKeyTokenState';
import { ApiKey } from '@/settings/developers/types/api-key/ApiKey';
import { computeNewExpirationDate } from '@/settings/developers/utils/compute-new-expiration-date';
import { formatExpiration } from '@/settings/developers/utils/format-expiration';
@ -24,7 +24,6 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useGenerateApiKeyTokenMutation } from '~/generated/graphql';
import { apiKeyTokenState } from '@/settings/developers/states/generatedApiKeyTokenState';
const StyledInfo = styled.span`
color: ${({ theme }) => theme.font.color.light};
@ -121,16 +120,18 @@ export const SettingsDevelopersApiKeyDetail = () => {
return (
<>
{apiKeyData?.name && (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconCode}
title={
<Breadcrumb
links={[
{ children: 'Developers', href: '/settings/developers' },
{ children: `${apiKeyName} API Key` },
]}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Developers', href: '/settings/developers' },
{ children: `${apiKeyName} API Key` },
]}
/>
</SettingsHeaderContainer>
<Section>
{apiKeyToken ? (
<>

View File

@ -1,25 +1,24 @@
import { DateTime } from 'luxon';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { H2Title, IconSettings } from 'twenty-ui';
import { H2Title, IconCode } from 'twenty-ui';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { EXPIRATION_DATES } from '@/settings/developers/constants/ExpirationDates';
import { apiKeyTokenState } from '@/settings/developers/states/generatedApiKeyTokenState';
import { ApiKey } from '@/settings/developers/types/api-key/ApiKey';
import { Select } from '@/ui/input/components/Select';
import { TextInput } from '@/ui/input/components/TextInput';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useSetRecoilState } from 'recoil';
import { Key } from 'ts-key-enum';
import { useGenerateApiKeyTokenMutation } from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
import { Key } from 'ts-key-enum';
import { apiKeyTokenState } from '@/settings/developers/states/generatedApiKeyTokenState';
import { useSetRecoilState } from 'recoil';
export const SettingsDevelopersApiKeysNew = () => {
const [generateOneApiKeyToken] = useGenerateApiKeyTokenMutation();
@ -64,23 +63,27 @@ export const SettingsDevelopersApiKeysNew = () => {
};
const canSave = !!formValues.name && createOneApiKey;
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconCode}
title={
<Breadcrumb
links={[
{ children: 'Developers', href: '/settings/developers' },
{ children: 'New API Key' },
]}
/>
}
actionButton={
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/developers');
}}
onSave={handleSave}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Developers', href: '/settings/developers' },
{ children: 'New API Key' },
]}
/>
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/developers');
}}
onSave={handleSave}
/>
</SettingsHeaderContainer>
<Section>
<H2Title title="Name" description="Name of your API key" />
<TextInput

View File

@ -1,7 +1,7 @@
import styled from '@emotion/styled';
import { useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { H2Title, IconSettings, IconTrash } from 'twenty-ui';
import { H2Title, IconCode, IconTrash } from 'twenty-ui';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
@ -9,7 +9,6 @@ import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { Webhook } from '@/settings/developers/types/webhook/Webhook';
import { Button } from '@/ui/input/button/components/Button';
@ -88,23 +87,27 @@ export const SettingsDevelopersWebhooksDetail = () => {
return (
<>
{webhookData?.targetUrl && (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconCode}
title={
<Breadcrumb
links={[
{ children: 'Developers', href: '/settings/developers' },
{ children: 'Webhook' },
]}
/>
}
actionButton={
<SaveAndCancelButtons
isSaveDisabled={!isDirty}
onCancel={() => {
navigate('/settings/developers');
}}
onSave={handleSave}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Developers', href: '/settings/developers' },
{ children: 'Webhook' },
]}
/>
<SaveAndCancelButtons
isSaveDisabled={!isDirty}
onCancel={() => {
navigate('/settings/developers');
}}
onSave={handleSave}
/>
</SettingsHeaderContainer>
<Section>
<H2Title
title="Endpoint URL"

View File

@ -1,11 +1,10 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { H2Title, IconSettings } from 'twenty-ui';
import { H2Title, IconCode } from 'twenty-ui';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { Webhook } from '@/settings/developers/types/webhook/Webhook';
import { TextInput } from '@/ui/input/components/TextInput';
@ -35,23 +34,27 @@ export const SettingsDevelopersWebhooksNew = () => {
};
const canSave = !!formValues.targetUrl && createOneWebhook;
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconCode}
title={
<Breadcrumb
links={[
{ children: 'Developers', href: '/settings/developers' },
{ children: 'New webhook' },
]}
/>
}
actionButton={
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/developers');
}}
onSave={handleSave}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Developers', href: '/settings/developers' },
{ children: 'New webhook' },
]}
/>
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/developers');
}}
onSave={handleSave}
/>
</SettingsHeaderContainer>
<Section>
<H2Title
title="Endpoint URL"

View File

@ -42,8 +42,9 @@ export const SettingsIntegrationDatabase = () => {
if (!isIntegrationAvailable) return null;
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<SubMenuTopBarContainer
Icon={IconSettings}
title={
<Breadcrumb
links={[
{
@ -53,6 +54,9 @@ export const SettingsIntegrationDatabase = () => {
{ children: integration.text },
]}
/>
}
>
<SettingsPageContainer>
<SettingsIntegrationPreview
integrationLogoUrl={integration.from.image}
/>

View File

@ -3,10 +3,21 @@ import { IconSettings } from 'twenty-ui';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsIntegrationEditDatabaseConnectionContainer } from '@/settings/integrations/database-connection/components/SettingsIntegrationEditDatabaseConnectionContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
export const SettingsIntegrationEditDatabaseConnection = () => {
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconSettings}
title={
<Breadcrumb
links={[
// TODO
{ children: 'Edit connection' },
]}
/>
}
>
<SettingsPageContainer>
<SettingsIntegrationEditDatabaseConnectionContainer />
</SettingsPageContainer>

View File

@ -8,7 +8,6 @@ import { z } from 'zod';
import { useCreateOneDatabaseConnection } from '@/databases/hooks/useCreateOneDatabaseConnection';
import { getForeignDataWrapperType } from '@/databases/utils/getForeignDataWrapperType';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import {
SettingsIntegrationDatabaseConnectionForm,
@ -132,34 +131,38 @@ export const SettingsIntegrationNewDatabaseConnection = () => {
};
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconSettings}
title={
<Breadcrumb
links={[
{
children: 'Integrations',
href: settingsIntegrationsPagePath,
},
{
children: integration.text,
href: `${settingsIntegrationsPagePath}/${databaseKey}`,
},
{ children: 'New' },
]}
/>
}
actionButton={
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() =>
navigate(`${settingsIntegrationsPagePath}/${databaseKey}`)
}
onSave={handleSave}
/>
}
>
<SettingsPageContainer>
<FormProvider
// eslint-disable-next-line react/jsx-props-no-spreading
{...formConfig}
>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{
children: 'Integrations',
href: settingsIntegrationsPagePath,
},
{
children: integration.text,
href: `${settingsIntegrationsPagePath}/${databaseKey}`,
},
{ children: 'New' },
]}
/>
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() =>
navigate(`${settingsIntegrationsPagePath}/${databaseKey}`)
}
onSave={handleSave}
/>
</SettingsHeaderContainer>
<Section>
<H2Title
title="Connect a new database"

View File

@ -1,18 +1,15 @@
import { IconSettings } from 'twenty-ui';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsIntegrationGroup } from '@/settings/integrations/components/SettingsIntegrationGroup';
import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { IconApps } from 'twenty-ui';
export const SettingsIntegrations = () => {
const integrationCategories = useSettingsIntegrationCategories();
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer Icon={IconApps} title="Integrations">
<SettingsPageContainer>
<Breadcrumb links={[{ children: 'Integrations' }]} />
{integrationCategories.map((group) => (
<SettingsIntegrationGroup key={group.key} integrationGroup={group} />
))}

View File

@ -1,5 +1,4 @@
import styled from '@emotion/styled';
import { H1Title, H2Title, IconSettings } from 'twenty-ui';
import { H2Title, IconColorSwatch } from 'twenty-ui';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { ColorSchemePicker } from '@/ui/input/color-scheme/components/ColorSchemePicker';
@ -8,17 +7,12 @@ import { Section } from '@/ui/layout/section/components/Section';
import { useColorScheme } from '@/ui/theme/hooks/useColorScheme';
import { DateTimeSettings } from '~/pages/settings/profile/appearance/components/DateTimeSettings';
const StyledH1Title = styled(H1Title)`
margin-bottom: 0;
`;
export const SettingsAppearance = () => {
const { colorScheme, setColorScheme } = useColorScheme();
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer Icon={IconColorSwatch} title="Appearance">
<SettingsPageContainer>
<StyledH1Title title="Appearance" />
<Section>
<H2Title title="Theme" />
<ColorSchemePicker value={colorScheme} onChange={setColorScheme} />

View File

@ -1,7 +1,7 @@
import { useResetRecoilState } from 'recoil';
import { settingsServerlessFunctionCodeEditorOutputParamsState } from '@/settings/serverless-functions/states/settingsServerlessFunctionCodeEditorOutputParamsState';
import { settingsServerlessFunctionInputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionInputState';
import { settingsServerlessFunctionOutputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionOutputState';
import { settingsServerlessFunctionCodeEditorOutputParamsState } from '@/settings/serverless-functions/states/settingsServerlessFunctionCodeEditorOutputParamsState';
import { useResetRecoilState } from 'recoil';
export const ResetServerlessFunctionStatesEffect = () => {
const resetSettingsServerlessFunctionInput = useResetRecoilState(

View File

@ -1,25 +1,24 @@
import { useParams } from 'react-router-dom';
import { IconCode, IconSettings, IconTestPipe } from 'twenty-ui';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsServerlessFunctionCodeEditorTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionCodeEditorTab';
import { SettingsServerlessFunctionSettingsTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionSettingsTab';
import { SettingsServerlessFunctionTestTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTab';
import { SettingsServerlessFunctionTestTabEffect } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTabEffect';
import { useExecuteOneServerlessFunction } from '@/settings/serverless-functions/hooks/useExecuteOneServerlessFunction';
import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
import { useUpdateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useUpdateOneServerlessFunction';
import { settingsServerlessFunctionInputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionInputState';
import { settingsServerlessFunctionOutputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionOutputState';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { TabList } from '@/ui/layout/tab/components/TabList';
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useParams } from 'react-router-dom';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { SettingsServerlessFunctionCodeEditorTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionCodeEditorTab';
import { SettingsServerlessFunctionSettingsTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionSettingsTab';
import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
import { SettingsServerlessFunctionTestTab } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTab';
import { useExecuteOneServerlessFunction } from '@/settings/serverless-functions/hooks/useExecuteOneServerlessFunction';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { useUpdateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useUpdateOneServerlessFunction';
import { IconCode, IconFunction, IconSettings, IconTestPipe } from 'twenty-ui';
import { useDebouncedCallback } from 'use-debounce';
import { SettingsServerlessFunctionTestTabEffect } from '@/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTabEffect';
import { settingsServerlessFunctionOutputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionOutputState';
import { settingsServerlessFunctionInputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionInputState';
const TAB_LIST_COMPONENT_ID = 'serverless-function-detail';
@ -145,16 +144,18 @@ export const SettingsServerlessFunctionDetail = () => {
return (
formValues.name && (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconFunction}
title={
<Breadcrumb
links={[
{ children: 'Functions', href: '/settings/functions' },
{ children: `${formValues.name}` },
]}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Functions', href: '/settings/functions' },
{ children: `${formValues.name}` },
]}
/>
</SettingsHeaderContainer>
<Section>
<TabList tabListId={TAB_LIST_COMPONENT_ID} tabs={tabs} />
</Section>

View File

@ -1,31 +1,36 @@
import { IconPlus, IconSettings } from 'twenty-ui';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsServerlessFunctionsTable } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsTable';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { Button } from '@/ui/input/button/components/Button';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink';
import { IconFunction, IconPlus } from 'twenty-ui';
export const SettingsServerlessFunctions = () => {
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconFunction}
title="Functions"
actionButton={
<UndecoratedLink
to={getSettingsPagePath(SettingsPath.NewServerlessFunction)}
>
<Button
Icon={IconPlus}
title="New Function"
accent="blue"
size="small"
/>
</UndecoratedLink>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb links={[{ children: 'Functions' }]} />
<UndecoratedLink
to={getSettingsPagePath(SettingsPath.NewServerlessFunction)}
>
<Button
Icon={IconPlus}
title="New Function"
accent="blue"
size="small"
/>
</UndecoratedLink>
</SettingsHeaderContainer>
<Section>
<SettingsServerlessFunctionsTable />

View File

@ -1,19 +1,18 @@
import { IconSettings } from 'twenty-ui';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useNavigate } from 'react-router-dom';
import { useCreateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useCreateOneServerlessFunction';
import { DEFAULT_CODE } from '@/ui/input/code-editor/components/CodeEditor';
import { ServerlessFunctionNewFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
import { SettingsServerlessFunctionNewForm } from '@/settings/serverless-functions/components/SettingsServerlessFunctionNewForm';
import { isDefined } from '~/utils/isDefined';
import { useState } from 'react';
import { useCreateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useCreateOneServerlessFunction';
import { ServerlessFunctionNewFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { DEFAULT_CODE } from '@/ui/input/code-editor/components/CodeEditor';
import { useState } from 'react';
import { IconFunction } from 'twenty-ui';
import { isDefined } from '~/utils/isDefined';
export const SettingsServerlessFunctionsNew = () => {
const navigate = useNavigate();
@ -54,23 +53,27 @@ export const SettingsServerlessFunctionsNew = () => {
const canSave = !!formValues.name && createOneServerlessFunction;
return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SubMenuTopBarContainer
Icon={IconFunction}
title={
<Breadcrumb
links={[
{ children: 'Functions', href: '/settings/functions' },
{ children: 'New' },
]}
/>
}
actionButton={
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/functions');
}}
onSave={handleSave}
/>
}
>
<SettingsPageContainer>
<SettingsHeaderContainer>
<Breadcrumb
links={[
{ children: 'Functions', href: '/settings/functions' },
{ children: 'New' },
]}
/>
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/functions');
}}
onSave={handleSave}
/>
</SettingsHeaderContainer>
<SettingsServerlessFunctionNewForm
formValues={formValues}
onChange={onChange}