New useNavigateApp (#9729)

Todo : 
- replace all instances of useNavigate(
- remove getSettingsPagePath
- add eslint rule to enfore usage of useNavigateApp instead of
useNavigate
This commit is contained in:
Félix Malfait
2025-01-18 13:58:12 +01:00
committed by GitHub
parent 8572471973
commit 152902d1be
115 changed files with 975 additions and 679 deletions

View File

@ -1,12 +1,13 @@
import { AppPath } from '@/types/AppPath';
import styled from '@emotion/styled';
import { useEffect, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useSearchParams } from 'react-router-dom';
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
import { MainButton, UndecoratedLink } from 'twenty-ui';
import { useAuthorizeAppMutation } from '~/generated/graphql';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { isDefined } from '~/utils/isDefined';
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
type App = { id: string; name: string; logo: string };
@ -54,7 +55,7 @@ const StyledButtonContainer = styled.div`
width: 100%;
`;
export const Authorize = () => {
const navigate = useNavigate();
const navigate = useNavigateApp();
const [searchParam] = useSearchParams();
const { redirect } = useRedirect();
//TODO: Replace with db call for registered third party apps

View File

@ -3,6 +3,7 @@ import { Logo } from '@/auth/components/Logo';
import { Title } from '@/auth/components/Title';
import { useAuth } from '@/auth/hooks/useAuth';
import { useIsLogged } from '@/auth/hooks/useIsLogged';
import { workspacePublicDataState } from '@/auth/states/workspacePublicDataState';
import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex';
import { useReadCaptchaToken } from '@/captcha/hooks/useReadCaptchaToken';
import { AppPath } from '@/types/AppPath';
@ -18,16 +19,16 @@ import { motion } from 'framer-motion';
import { useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { useNavigate, useParams } from 'react-router-dom';
import { useSetRecoilState, useRecoilValue } from 'recoil';
import { useParams } from 'react-router-dom';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { AnimatedEaseIn, MainButton } from 'twenty-ui';
import { z } from 'zod';
import {
useUpdatePasswordViaResetTokenMutation,
useValidatePasswordResetTokenQuery,
} from '~/generated/graphql';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { logError } from '~/utils/logError';
import { workspacePublicDataState } from '@/auth/states/workspacePublicDataState';
const validationSchema = z
.object({
@ -74,7 +75,7 @@ export const PasswordReset = () => {
const workspacePublicData = useRecoilValue(workspacePublicDataState);
const navigate = useNavigate();
const navigate = useNavigateApp();
const [email, setEmail] = useState('');
const [isTokenValid, setIsTokenValid] = useState(false);

View File

@ -12,15 +12,14 @@ import {
import { SubTitle } from '@/auth/components/SubTitle';
import { Title } from '@/auth/components/Title';
import { currentUserState } from '@/auth/states/currentUserState';
import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
import { AppPath } from '@/types/AppPath';
import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus';
import {
OnboardingStatus,
useGetCurrentUserLazyQuery,
} from '~/generated/graphql';
import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus';
import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
import { AppPath } from '@/types/AppPath';
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { useNavigateApp } from '~/hooks/useNavigateApp';
const StyledCheckContainer = styled.div`
align-items: center;
@ -41,7 +40,7 @@ const StyledButtonContainer = styled.div`
export const PaymentSuccess = () => {
const theme = useTheme();
const navigate = useNavigate();
const navigate = useNavigateApp();
const subscriptionStatus = useSubscriptionStatus();
const onboardingStatus = useOnboardingStatus();
const [getCurrentUser] = useGetCurrentUserLazyQuery();

View File

@ -8,10 +8,10 @@ import { unified } from 'unified';
import { visit } from 'unist-util-visit';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
type ReleaseNote = {
slug: string;
@ -112,7 +112,7 @@ export const Releases = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: <Trans>Releases</Trans> },
]}

View File

@ -14,7 +14,6 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage';
import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
@ -28,6 +27,7 @@ import {
useUpdateBillingSubscriptionMutation,
} from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
type SwitchInfo = {
newInterval: SubscriptionInterval;
@ -130,7 +130,7 @@ export const SettingsBilling = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: <Trans>Billing</Trans> },
]}

View File

@ -7,9 +7,9 @@ import { DeleteAccount } from '@/settings/profile/components/DeleteAccount';
import { EmailField } from '@/settings/profile/components/EmailField';
import { NameFields } from '@/settings/profile/components/NameFields';
import { ProfilePictureUploader } from '@/settings/profile/components/ProfilePictureUploader';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsProfile = () => {
const { t } = useLingui();
@ -20,7 +20,7 @@ export const SettingsProfile = () => {
links={[
{
children: <Trans>User</Trans>,
href: getSettingsPagePath(SettingsPath.ProfilePage),
href: getSettingsPath(SettingsPath.ProfilePage),
},
{ children: <Trans>Profile</Trans> },
]}

View File

@ -12,12 +12,12 @@ import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWork
import { SettingsCard } from '@/settings/components/SettingsCard';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { DeleteWorkspace } from '@/settings/profile/components/DeleteWorkspace';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { NameField } from '@/settings/workspace/components/NameField';
import { ToggleImpersonate } from '@/settings/workspace/components/ToggleImpersonate';
import { WorkspaceLogoUploader } from '@/settings/workspace/components/WorkspaceLogoUploader';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import packageJson from '../../../package.json';
export const SettingsWorkspace = () => {
@ -30,7 +30,7 @@ export const SettingsWorkspace = () => {
links={[
{
children: t`Workspace`,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: t`General` },
]}
@ -51,7 +51,7 @@ export const SettingsWorkspace = () => {
title={t`Domain`}
description={t`Edit your subdomain name or set a custom domain.`}
/>
<UndecoratedLink to={getSettingsPagePath(SettingsPath.Domain)}>
<UndecoratedLink to={getSettingsPath(SettingsPath.Domain)}>
<SettingsCard
title={t`Customize Domain`}
Icon={<IconWorld />}

View File

@ -23,7 +23,6 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
@ -37,6 +36,7 @@ import { WorkspaceInviteTeam } from '@/workspace/components/WorkspaceInviteTeam'
import { formatDistanceToNow } from 'date-fns';
import { useGetWorkspaceInvitationsQuery } from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { TableCell } from '../../modules/ui/layout/table/components/TableCell';
import { TableRow } from '../../modules/ui/layout/table/components/TableRow';
import { useDeleteWorkspaceInvitation } from '../../modules/workspace-invitation/hooks/useDeleteWorkspaceInvitation';
@ -144,7 +144,7 @@ export const SettingsWorkspaceMembers = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: <Trans>Members</Trans> },
]}

View File

@ -1,7 +1,6 @@
import { Meta, StoryObj } from '@storybook/react';
import { within } from '@storybook/test';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import {
PageDecorator,
@ -10,13 +9,14 @@ import {
import { graphqlMocks } from '~/testing/graphqlMocks';
import { sleep } from '~/utils/sleep';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { SettingsBilling } from '../SettingsBilling';
const meta: Meta<PageDecoratorArgs> = {
title: 'Pages/Settings/SettingsBilling',
component: SettingsBilling,
decorators: [PageDecorator],
args: { routePath: getSettingsPagePath(SettingsPath.Billing) },
args: { routePath: getSettingsPath(SettingsPath.Billing) },
parameters: {
msw: graphqlMocks,
},

View File

@ -12,9 +12,9 @@ import { SettingsAccountsBlocklistSection } from '@/settings/accounts/components
import { SettingsAccountsConnectedAccountsListCard } from '@/settings/accounts/components/SettingsAccountsConnectedAccountsListCard';
import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/SettingsAccountsSettingsSection';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsAccounts = () => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
@ -39,7 +39,7 @@ export const SettingsAccounts = () => {
links={[
{
children: 'User',
href: getSettingsPagePath(SettingsPath.ProfilePage),
href: getSettingsPath(SettingsPath.ProfilePage),
},
{ children: 'Account' },
]}

View File

@ -1,10 +1,10 @@
import { SettingsAccountsCalendarChannelsContainer } from '@/settings/accounts/components/SettingsAccountsCalendarChannelsContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { Trans, useLingui } from '@lingui/react/macro';
import { Section } from 'twenty-ui';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsAccountsCalendars = () => {
const { t } = useLingui();
@ -15,11 +15,11 @@ export const SettingsAccountsCalendars = () => {
links={[
{
children: <Trans>User</Trans>,
href: getSettingsPagePath(SettingsPath.ProfilePage),
href: getSettingsPath(SettingsPath.ProfilePage),
},
{
children: <Trans>Accounts</Trans>,
href: getSettingsPagePath(SettingsPath.Accounts),
href: getSettingsPath(SettingsPath.Accounts),
},
{ children: <Trans>Calendars</Trans> },
]}

View File

@ -1,9 +1,9 @@
import { SettingsAccountsMessageChannelsContainer } from '@/settings/accounts/components/SettingsAccountsMessageChannelsContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { Section } from 'twenty-ui';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsAccountsEmails = () => (
<SubMenuTopBarContainer
@ -11,11 +11,11 @@ export const SettingsAccountsEmails = () => (
links={[
{
children: 'User',
href: getSettingsPagePath(SettingsPath.ProfilePage),
href: getSettingsPath(SettingsPath.ProfilePage),
},
{
children: 'Accounts',
href: getSettingsPagePath(SettingsPath.Accounts),
href: getSettingsPath(SettingsPath.Accounts),
},
{ children: 'Emails' },
]}

View File

@ -1,8 +1,8 @@
import { SettingsNewAccountSection } from '@/settings/accounts/components/SettingsNewAccountSection';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsNewAccount = () => {
return (
@ -11,11 +11,11 @@ export const SettingsNewAccount = () => {
links={[
{
children: 'User',
href: getSettingsPagePath(SettingsPath.ProfilePage),
href: getSettingsPath(SettingsPath.ProfilePage),
},
{
children: 'Accounts',
href: getSettingsPagePath(SettingsPath.Accounts),
href: getSettingsPath(SettingsPath.Accounts),
},
{ children: `New` },
]}

View File

@ -1,8 +1,8 @@
import { SettingsAdminContent } from '@/settings/admin-panel/components/SettingsAdminContent';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { SettingsAdminContent } from '@/settings/admin-panel/components/SettingsAdminContent';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsAdmin = () => {
return (
@ -11,7 +11,7 @@ export const SettingsAdmin = () => {
links={[
{
children: 'Other',
href: getSettingsPagePath(SettingsPath.AdminPanel),
href: getSettingsPath(SettingsPath.AdminPanel),
},
{ children: 'Server Admin Panel' },
]}

View File

@ -1,45 +0,0 @@
// @ts-expect-error external library has a typing issue
import { RevertConnect } from '@revertdotdev/revert-react';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsReadDocumentationButton } from '@/settings/developers/components/SettingsReadDocumentationButton';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { Trans, useLingui } from '@lingui/react/macro';
import { useRecoilValue } from 'recoil';
import { Section } from 'twenty-ui';
const REVERT_PUBLIC_KEY = 'pk_live_a87fee8c-28c7-494f-99a3-996ff89f9918';
export const SettingsCRMMigration = () => {
const { t } = useLingui();
const currentWorkspace = useRecoilValue(currentWorkspaceState);
return (
<SubMenuTopBarContainer
title={t`Migrate`}
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
},
{ children: <Trans>Migrate</Trans> },
]}
actionButton={<SettingsReadDocumentationButton />}
>
<SettingsPageContainer>
<SettingsHeaderContainer></SettingsHeaderContainer>
<Section>
<RevertConnect
config={{
revertToken: REVERT_PUBLIC_KEY,
tenantId: currentWorkspace?.id,
}}
/>
</Section>
</SettingsPageContainer>
</SubMenuTopBarContainer>
);
};

View File

@ -1,7 +1,6 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { Trans, useLingui } from '@lingui/react/macro';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { H2Title, Section } from 'twenty-ui';
import { z } from 'zod';
@ -13,18 +12,19 @@ import {
settingsDataModelObjectAboutFormSchema,
} from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectAboutForm';
import { settingsCreateObjectInputSchema } from '@/settings/data-model/validation-schemas/settingsCreateObjectInputSchema';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
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/components/SubMenuTopBarContainer';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const newObjectFormSchema = settingsDataModelObjectAboutFormSchema;
type SettingsDataModelNewObjectFormValues = z.infer<typeof newObjectFormSchema>;
export const SettingsNewObject = () => {
const navigate = useNavigate();
const navigate = useNavigateSettings();
const { t } = useLingui();
const { enqueueSnackBar } = useSnackBar();
@ -47,7 +47,7 @@ export const SettingsNewObject = () => {
variant: SnackBarVariant.Success,
});
navigate(getSettingsPagePath(SettingsPath.Objects));
navigate(SettingsPath.Objects);
} catch (error) {
if (error instanceof z.ZodError) {
enqueueSnackBar(t`Invalid object data`, {
@ -68,11 +68,11 @@ export const SettingsNewObject = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: <Trans>Objects</Trans>,
href: getSettingsPagePath(SettingsPath.Objects),
href: getSettingsPath(SettingsPath.Objects),
},
{ children: <Trans>New</Trans> },
]}
@ -89,9 +89,7 @@ export const SettingsNewObject = () => {
<SettingsDataModelObjectAboutForm />
</Section>
<SaveAndCancelButtons
onCancel={() =>
navigate(getSettingsPagePath(SettingsPath.Objects))
}
onCancel={() => navigate(SettingsPath.Objects)}
/>
</form>
</FormProvider>

View File

@ -1,5 +1,5 @@
import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
@ -8,7 +8,6 @@ import { ObjectIndexes } from '@/settings/data-model/object-details/components/t
import { ObjectSettings } from '@/settings/data-model/object-details/components/tabs/ObjectSettings';
import { SettingsDataModelObjectTypeTag } from '@/settings/data-model/objects/components/SettingsDataModelObjectTypeTag';
import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
@ -31,8 +30,10 @@ import {
isDefined,
} from 'twenty-ui';
import { FeatureFlagKey } from '~/generated/graphql';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { SETTINGS_OBJECT_DETAIL_TABS } from '~/pages/settings/data-model/constants/SettingsObjectDetailTabs';
import { updatedObjectNamePluralState } from '~/pages/settings/data-model/states/updatedObjectNamePluralState';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledContentContainer = styled.div`
flex: 1;
@ -51,7 +52,7 @@ const StyledTitleContainer = styled.div`
`;
export const SettingsObjectDetailPage = () => {
const navigate = useNavigate();
const navigateApp = useNavigateApp();
const { objectNamePlural = '' } = useParams();
const { findActiveObjectMetadataItemByNamePlural } =
@ -76,10 +77,10 @@ export const SettingsObjectDetailPage = () => {
useEffect(() => {
if (objectNamePlural === updatedObjectNamePlural)
setUpdatedObjectNamePlural('');
if (!isDefined(objectMetadataItem)) navigate(AppPath.NotFound);
if (!isDefined(objectMetadataItem)) navigateApp(AppPath.NotFound);
}, [
objectMetadataItem,
navigate,
navigateApp,
objectNamePlural,
updatedObjectNamePlural,
setUpdatedObjectNamePlural,
@ -142,9 +143,9 @@ export const SettingsObjectDetailPage = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: 'Objects', href: '/settings/objects' },
{ children: 'Objects', href: getSettingsPath(SettingsPath.Objects) },
{
children: objectMetadataItem.labelPlural,
},

View File

@ -3,7 +3,7 @@ import omit from 'lodash.omit';
import pick from 'lodash.pick';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import {
Button,
H2Title,
@ -28,14 +28,16 @@ import { SettingsDataModelFieldIconLabelForm } from '@/settings/data-model/field
import { SettingsDataModelFieldSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard';
import { settingsFieldFormSchema } from '@/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema';
import { SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
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/components/SubMenuTopBarContainer';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { isDefined } from '~/utils/isDefined';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
//TODO: fix this type
type SettingsDataModelFieldEditFormValues = z.infer<
@ -44,7 +46,9 @@ type SettingsDataModelFieldEditFormValues = z.infer<
any;
export const SettingsObjectFieldEdit = () => {
const navigate = useNavigate();
const navigateSettings = useNavigateSettings();
const navigateApp = useNavigateApp();
const { enqueueSnackBar } = useSnackBar();
const { objectNamePlural = '', fieldName = '' } = useParams();
@ -78,9 +82,9 @@ export const SettingsObjectFieldEdit = () => {
useEffect(() => {
if (!objectMetadataItem || !fieldMetadataItem) {
navigate(AppPath.NotFound);
navigateApp(AppPath.NotFound);
}
}, [navigate, objectMetadataItem, fieldMetadataItem]);
}, [navigateApp, objectMetadataItem, fieldMetadataItem]);
const { isDirty, isValid, isSubmitting } = formConfig.formState;
const canSave = isDirty && isValid && !isSubmitting;
@ -127,7 +131,9 @@ export const SettingsObjectFieldEdit = () => {
Object.keys(otherDirtyFields),
);
navigate(`/settings/objects/${objectNamePlural}`);
navigateSettings(SettingsPath.ObjectDetail, {
objectNamePlural,
});
await updateOneFieldMetadataItem({
objectMetadataId: objectMetadataItem.id,
@ -144,12 +150,16 @@ export const SettingsObjectFieldEdit = () => {
const handleDeactivate = async () => {
await deactivateMetadataField(fieldMetadataItem.id, objectMetadataItem.id);
navigate(`/settings/objects/${objectNamePlural}`);
navigateSettings(SettingsPath.ObjectDetail, {
objectNamePlural,
});
};
const handleActivate = async () => {
await activateMetadataField(fieldMetadataItem.id, objectMetadataItem.id);
navigate(`/settings/objects/${objectNamePlural}`);
navigateSettings(SettingsPath.ObjectDetail, {
objectNamePlural,
});
};
return (
@ -161,15 +171,17 @@ export const SettingsObjectFieldEdit = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Objects',
href: '/settings/objects',
href: getSettingsPath(SettingsPath.Objects),
},
{
children: objectMetadataItem.labelPlural,
href: `/settings/objects/${objectNamePlural}`,
href: getSettingsPath(SettingsPath.ObjectDetail, {
objectNamePlural,
}),
},
{
children: fieldMetadataItem.label,
@ -179,7 +191,11 @@ export const SettingsObjectFieldEdit = () => {
<SaveAndCancelButtons
isSaveDisabled={!canSave}
isCancelDisabled={isSubmitting}
onCancel={() => navigate(`/settings/objects/${objectNamePlural}`)}
onCancel={() =>
navigateSettings(SettingsPath.ObjectDetail, {
objectNamePlural,
})
}
onSave={formConfig.handleSubmit(handleSave)}
/>
}

View File

@ -14,6 +14,7 @@ import { SettingsDataModelFieldSettingsFormCard } from '@/settings/data-model/fi
import { settingsFieldFormSchema } from '@/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema';
import { SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
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/components/SubMenuTopBarContainer';
@ -24,13 +25,16 @@ import { zodResolver } from '@hookform/resolvers/zod';
import pick from 'lodash.pick';
import { useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { useParams, useSearchParams } from 'react-router-dom';
import { H2Title, Section } from 'twenty-ui';
import { z } from 'zod';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { DEFAULT_ICONS_BY_FIELD_TYPE } from '~/pages/settings/data-model/constants/DefaultIconsByFieldType';
import { computeMetadataNameFromLabel } from '~/pages/settings/data-model/utils/compute-metadata-name-from-label.utils';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
type SettingsDataModelNewFieldFormValues = z.infer<
ReturnType<typeof settingsFieldFormSchema>
@ -40,7 +44,9 @@ type SettingsDataModelNewFieldFormValues = z.infer<
const DEFAULT_ICON_FOR_NEW_FIELD = 'IconUsers';
export const SettingsObjectNewFieldConfigure = () => {
const navigate = useNavigate();
const navigateApp = useNavigateApp();
const navigate = useNavigateSettings();
const { objectNamePlural = '' } = useParams();
const [searchParams] = useSearchParams();
const fieldType =
@ -115,9 +121,9 @@ export const SettingsObjectNewFieldConfigure = () => {
useEffect(() => {
if (!activeObjectMetadataItem) {
navigate(AppPath.NotFound);
navigateApp(AppPath.NotFound);
}
}, [activeObjectMetadataItem, navigate]);
}, [activeObjectMetadataItem, navigateApp]);
if (!activeObjectMetadataItem) return null;
@ -163,7 +169,9 @@ export const SettingsObjectNewFieldConfigure = () => {
});
}
navigate(`/settings/objects/${objectNamePlural}`);
navigate(SettingsPath.ObjectDetail, {
objectNamePlural,
});
// TODO: fix optimistic update logic
// Forcing a refetch for now but it's not ideal
@ -190,7 +198,9 @@ export const SettingsObjectNewFieldConfigure = () => {
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectNamePlural}`,
href: getSettingsPath(SettingsPath.ObjectDetail, {
objectNamePlural,
}),
},
{ children: <SettingsDataModelNewFieldBreadcrumbDropDown /> },
@ -201,7 +211,13 @@ export const SettingsObjectNewFieldConfigure = () => {
isCancelDisabled={isSubmitting}
onCancel={() =>
navigate(
`/settings/objects/${objectNamePlural}/new-field/select?fieldType=${fieldType}`,
SettingsPath.ObjectNewFieldSelect,
{
objectNamePlural,
},
{
fieldType,
},
)
}
onSave={formConfig.handleSubmit(handleSave)}

View File

@ -6,14 +6,17 @@ import { SETTINGS_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/Set
import { SettingsObjectNewFieldSelector } from '@/settings/data-model/fields/forms/components/SettingsObjectNewFieldSelector';
import { SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { zodResolver } from '@hookform/resolvers/zod';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { isDefined } from 'twenty-ui';
import { z } from 'zod';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const settingsDataModelFieldTypeFormSchema = z.object({
type: z.enum(
@ -29,7 +32,7 @@ export type SettingsDataModelFieldTypeFormValues = z.infer<
>;
export const SettingsObjectNewFieldSelect = () => {
const navigate = useNavigate();
const navigate = useNavigateApp();
const { objectNamePlural = '' } = useParams();
const { findActiveObjectMetadataItemByNamePlural } =
useFilteredObjectMetadataItems();
@ -69,7 +72,9 @@ export const SettingsObjectNewFieldSelect = () => {
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectNamePlural}`,
href: getSettingsPath(SettingsPath.ObjectDetail, {
objectNamePlural,
}),
},
{ children: <SettingsDataModelNewFieldBreadcrumbDropDown /> },
]}

View File

@ -1,9 +1,9 @@
import { ReactFlowProvider } from '@xyflow/react';
import { SettingsDataModelOverview } from '@/settings/data-model/graph-overview/components/SettingsDataModelOverview';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsObjectOverview = () => {
return (
@ -11,7 +11,7 @@ export const SettingsObjectOverview = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: 'Objects', href: '/settings/objects' },
{

View File

@ -10,7 +10,6 @@ import {
import { SettingsObjectCoverImage } from '@/settings/data-model/objects/components/SettingsObjectCoverImage';
import { SettingsObjectInactiveMenuDropDown } from '@/settings/data-model/objects/components/SettingsObjectInactiveMenuDropDown';
import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { TextInput } from '@/ui/input/components/TextInput';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
@ -35,6 +34,7 @@ import {
} from 'twenty-ui';
import { GET_SETTINGS_OBJECT_TABLE_METADATA } from '~/pages/settings/data-model/constants/SettingsObjectTableMetadata';
import { SettingsObjectTableItem } from '~/pages/settings/data-model/types/SettingsObjectTableItem';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledIconChevronRight = styled(IconChevronRight)`
color: ${({ theme }) => theme.font.color.tertiary};
@ -143,7 +143,7 @@ export const SettingsObjects = () => {
<SubMenuTopBarContainer
title={t`Data model`}
actionButton={
<UndecoratedLink to={getSettingsPagePath(SettingsPath.NewObject)}>
<UndecoratedLink to={getSettingsPath(SettingsPath.NewObject)}>
<Button
Icon={IconPlus}
title={t`Add object`}
@ -155,7 +155,7 @@ export const SettingsObjects = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: <Trans>Objects</Trans> },
]}
@ -205,9 +205,10 @@ export const SettingsObjects = () => {
stroke={theme.icon.stroke.sm}
/>
}
link={`/settings/objects/${
objectSettingsItem.objectMetadataItem.namePlural
}`}
link={getSettingsPath(SettingsPath.ObjectDetail, {
objectNamePlural:
objectSettingsItem.objectMetadataItem.namePlural,
})}
/>
),
)}

View File

@ -2,13 +2,13 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain
import { SettingsApiKeysTable } from '@/settings/developers/components/SettingsApiKeysTable';
import { SettingsReadDocumentationButton } from '@/settings/developers/components/SettingsReadDocumentationButton';
import { SettingsWebhooksTable } from '@/settings/developers/components/SettingsWebhooksTable';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import styled from '@emotion/styled';
import { Trans, useLingui } from '@lingui/react/macro';
import { Button, H2Title, IconPlus, MOBILE_VIEWPORT, Section } from 'twenty-ui';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledButtonContainer = styled.div`
display: flex;
@ -37,7 +37,7 @@ export const SettingsDevelopers = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: <Trans>Developers</Trans> },
]}
@ -56,7 +56,7 @@ export const SettingsDevelopers = () => {
title={t`Create API key`}
size="small"
variant="secondary"
to={'/settings/developers/api-keys/new'}
to={getSettingsPath(SettingsPath.DevelopersNewApiKey)}
/>
</StyledButtonContainer>
</Section>
@ -72,7 +72,7 @@ export const SettingsDevelopers = () => {
title={t`Create Webhook`}
size="small"
variant="secondary"
to={'/settings/developers/webhooks/new'}
to={getSettingsPath(SettingsPath.DevelopersNewWebhook)}
/>
</StyledButtonContainer>
</Section>

View File

@ -1,3 +1,4 @@
import { SettingsPath } from '@/types/SettingsPath';
import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/test';
@ -7,12 +8,13 @@ import {
PageDecoratorArgs,
} from '~/testing/decorators/PageDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const meta: Meta<PageDecoratorArgs> = {
title: 'Pages/Settings/Developers/ApiKeys/SettingsDevelopersApiKeysNew',
component: SettingsDevelopersApiKeysNew,
decorators: [PageDecorator],
args: { routePath: '/settings/developers/api-keys/new' },
args: { routePath: getSettingsPath(SettingsPath.DevelopersNewApiKey) },
parameters: {
msw: graphqlMocks,
},

View File

@ -2,7 +2,7 @@ import styled from '@emotion/styled';
import { isNonEmptyString } from '@sniptt/guards';
import { DateTime } from 'luxon';
import { useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { useRecoilState } from 'recoil';
import { Button, H2Title, IconRepeat, IconTrash, Section } from 'twenty-ui';
@ -17,7 +17,6 @@ import { apiKeyTokenState } from '@/settings/developers/states/generatedApiKeyTo
import { ApiKey } from '@/settings/developers/types/api-key/ApiKey';
import { computeNewExpirationDate } from '@/settings/developers/utils/computeNewExpirationDate';
import { formatExpiration } from '@/settings/developers/utils/formatExpiration';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
@ -25,6 +24,8 @@ import { TextInput } from '@/ui/input/components/TextInput';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { useGenerateApiKeyTokenMutation } from '~/generated/graphql';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledInfo = styled.span`
color: ${({ theme }) => theme.font.color.light};
@ -47,7 +48,7 @@ export const SettingsDevelopersApiKeyDetail = () => {
const [isDeleteApiKeyModalOpen, setIsDeleteApiKeyModalOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const navigate = useNavigateSettings();
const { apiKeyId = '' } = useParams();
const [apiKeyToken, setApiKeyToken] = useRecoilState(apiKeyTokenState);
@ -68,7 +69,6 @@ export const SettingsDevelopersApiKeyDetail = () => {
setApiKeyName(record.name);
},
});
const developerPath = getSettingsPagePath(SettingsPath.Developers);
const deleteIntegration = async (redirect = true) => {
setIsLoading(true);
@ -79,7 +79,7 @@ export const SettingsDevelopersApiKeyDetail = () => {
updateOneRecordInput: { revokedAt: DateTime.now().toString() },
});
if (redirect) {
navigate(developerPath);
navigate(SettingsPath.Developers);
}
} catch (err) {
enqueueSnackBar(`Error deleting api key: ${err}`, {
@ -114,6 +114,7 @@ export const SettingsDevelopersApiKeyDetail = () => {
token: tokenData.data?.generateApiKeyToken.token,
};
};
const regenerateApiKey = async () => {
setIsLoading(true);
try {
@ -127,7 +128,9 @@ export const SettingsDevelopersApiKeyDetail = () => {
if (isNonEmptyString(apiKey?.token)) {
setApiKeyToken(apiKey.token);
navigate(`/settings/developers/api-keys/${apiKey.id}`);
navigate(SettingsPath.DevelopersApiKeyDetail, {
apiKeyId: apiKey.id,
});
}
}
} catch (err) {
@ -147,9 +150,12 @@ export const SettingsDevelopersApiKeyDetail = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Developers',
href: getSettingsPath(SettingsPath.Developers),
},
{ children: 'Developers', href: developerPath },
{ children: `${apiKeyName} API Key` },
]}
>

View File

@ -1,6 +1,5 @@
import { DateTime } from 'luxon';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { H2Title, Section } from 'twenty-ui';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
@ -10,7 +9,6 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain
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 { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { Select } from '@/ui/input/components/Select';
import { TextInput } from '@/ui/input/components/TextInput';
@ -18,11 +16,13 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBa
import { useSetRecoilState } from 'recoil';
import { Key } from 'ts-key-enum';
import { useGenerateApiKeyTokenMutation } from '~/generated/graphql';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { isDefined } from '~/utils/isDefined';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsDevelopersApiKeysNew = () => {
const [generateOneApiKeyToken] = useGenerateApiKeyTokenMutation();
const navigate = useNavigate();
const navigateSettings = useNavigateSettings();
const setApiKeyToken = useSetRecoilState(apiKeyTokenState);
const [formValues, setFormValues] = useState<{
name: string;
@ -58,7 +58,9 @@ export const SettingsDevelopersApiKeysNew = () => {
});
if (isDefined(tokenData.data?.generateApiKeyToken)) {
setApiKeyToken(tokenData.data.generateApiKeyToken.token);
navigate(`/settings/developers/api-keys/${newApiKey.id}`);
navigateSettings(SettingsPath.DevelopersApiKeyDetail, {
apiKeyId: newApiKey.id,
});
}
};
const canSave = !!formValues.name && createOneApiKey;
@ -68,11 +70,11 @@ export const SettingsDevelopersApiKeysNew = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Developers',
href: getSettingsPagePath(SettingsPath.Developers),
href: getSettingsPath(SettingsPath.Developers),
},
{ children: 'New Key' },
]}
@ -80,7 +82,7 @@ export const SettingsDevelopersApiKeysNew = () => {
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/developers');
navigateSettings(SettingsPath.Developers);
}}
onSave={handleSave}
/>

View File

@ -1,7 +1,7 @@
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import styled from '@emotion/styled';
import { useMemo, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import {
Button,
H2Title,
@ -28,7 +28,6 @@ import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { Webhook } from '@/settings/developers/types/webhook/Webhook';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { Select, SelectOption } from '@/ui/input/components/Select';
import { TextArea } from '@/ui/input/components/TextArea';
@ -38,8 +37,10 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBa
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useRecoilValue } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { WEBHOOK_EMPTY_OPERATION } from '~/pages/settings/developers/webhooks/constants/WebhookEmptyOperation';
import { WebhookOperationType } from '~/pages/settings/developers/webhooks/types/WebhookOperationsType';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const OBJECT_DROPDOWN_WIDTH = 340;
const ACTION_DROPDOWN_WIDTH = 140;
@ -66,7 +67,7 @@ export const SettingsDevelopersWebhooksDetail = () => {
const { objectMetadataItems } = useObjectMetadataItems();
const isAnalyticsEnabled = useRecoilValue(isAnalyticsEnabledState);
const isMobile = useIsMobile();
const navigate = useNavigate();
const navigate = useNavigateSettings();
const { webhookId = '' } = useParams();
const [isDeleteWebhookModalOpen, setIsDeleteWebhookModalOpen] =
@ -108,11 +109,9 @@ export const SettingsDevelopersWebhooksDetail = () => {
objectNameSingular: CoreObjectNameSingular.Webhook,
});
const developerPath = getSettingsPagePath(SettingsPath.Developers);
const deleteWebhook = () => {
deleteOneWebhook(webhookId);
navigate(developerPath);
navigate(SettingsPath.Developers);
};
const isAnalyticsV2Enabled = useIsFeatureEnabled(
@ -163,7 +162,7 @@ export const SettingsDevelopersWebhooksDetail = () => {
secret: secret,
},
});
navigate(developerPath);
navigate(SettingsPath.Developers);
};
const addEmptyOperationIfNecessary = (
@ -210,16 +209,19 @@ export const SettingsDevelopersWebhooksDetail = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Developers',
href: getSettingsPath(SettingsPath.Developers),
},
{ children: 'Developers', href: developerPath },
{ children: 'Webhook' },
]}
actionButton={
<SaveAndCancelButtons
isSaveDisabled={!isDirty}
onCancel={() => {
navigate(developerPath);
navigate(SettingsPath.Developers);
}}
onSave={handleSave}
/>

View File

@ -1,5 +1,4 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { H2Title, isDefined, Section } from 'twenty-ui';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
@ -7,14 +6,16 @@ import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { Webhook } from '@/settings/developers/types/webhook/Webhook';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { TextInput } from '@/ui/input/components/TextInput';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { isValidUrl } from '~/utils/url/isValidUrl';
export const SettingsDevelopersWebhooksNew = () => {
const navigate = useNavigate();
const navigate = useNavigateSettings();
const [formValues, setFormValues] = useState<{
targetUrl: string;
operations: string[];
@ -40,7 +41,9 @@ export const SettingsDevelopersWebhooksNew = () => {
if (!newWebhook) {
return;
}
navigate(`/settings/developers/webhooks/${newWebhook.id}`);
navigate(SettingsPath.DevelopersNewWebhookDetail, {
webhookId: newWebhook.id,
});
};
const canSave =
@ -67,11 +70,11 @@ export const SettingsDevelopersWebhooksNew = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Developers',
href: getSettingsPagePath(SettingsPath.Developers),
href: getSettingsPath(SettingsPath.Developers),
},
{ children: 'New Webhook' },
]}
@ -79,7 +82,7 @@ export const SettingsDevelopersWebhooksNew = () => {
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate(getSettingsPagePath(SettingsPath.Developers));
navigate(SettingsPath.Developers);
}}
onSave={handleSave}
/>

View File

@ -1,5 +1,5 @@
import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { H2Title, Section } from 'twenty-ui';
import { useGetDatabaseConnections } from '@/databases/hooks/useGetDatabaseConnections';
@ -8,14 +8,15 @@ import { SettingsIntegrationPreview } from '@/settings/integrations/components/S
import { SettingsIntegrationDatabaseConnectionsListCard } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionsListCard';
import { useIsSettingsIntegrationEnabled } from '@/settings/integrations/hooks/useIsSettingsIntegrationEnabled';
import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsIntegrationDatabase = () => {
const { databaseKey = '' } = useParams();
const navigate = useNavigate();
const navigateApp = useNavigateApp();
const [integrationCategoryAll] = useSettingsIntegrationCategories();
const integration = integrationCategoryAll.integrations.find(
@ -28,9 +29,9 @@ export const SettingsIntegrationDatabase = () => {
useEffect(() => {
if (!isIntegrationAvailable) {
navigate(AppPath.NotFound);
navigateApp(AppPath.NotFound);
}
}, [integration, databaseKey, navigate, isIntegrationAvailable]);
}, [integration, databaseKey, navigateApp, isIntegrationAvailable]);
const { connections } = useGetDatabaseConnections({
databaseKey,
@ -45,11 +46,11 @@ export const SettingsIntegrationDatabase = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Integrations',
href: getSettingsPagePath(SettingsPath.Integrations),
href: getSettingsPath(SettingsPath.Integrations),
},
{ children: integration.text },
]}

View File

@ -1,8 +1,8 @@
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsIntegrationEditDatabaseConnectionContainer } from '@/settings/integrations/database-connection/components/SettingsIntegrationEditDatabaseConnectionContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsIntegrationEditDatabaseConnection = () => {
return (
@ -11,11 +11,11 @@ export const SettingsIntegrationEditDatabaseConnection = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Integrations',
href: getSettingsPagePath(SettingsPath.Integrations),
href: getSettingsPath(SettingsPath.Integrations),
},
{ children: 'Edit connection' },
]}

View File

@ -1,7 +1,7 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { z } from 'zod';
import { useCreateOneDatabaseConnection } from '@/databases/hooks/useCreateOneDatabaseConnection';
@ -15,7 +15,6 @@ import {
} from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm';
import { useIsSettingsIntegrationEnabled } from '@/settings/integrations/hooks/useIsSettingsIntegrationEnabled';
import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
@ -23,6 +22,9 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { H2Title, Section } from 'twenty-ui';
import { CreateRemoteServerInput } from '~/generated-metadata/graphql';
import { useNavigateApp } from '~/hooks/useNavigateApp';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const createRemoteServerInputPostgresSchema =
settingsIntegrationPostgreSQLConnectionFormSchema.transform<CreateRemoteServerInput>(
@ -67,7 +69,8 @@ type SettingsIntegrationNewConnectionFormValues =
export const SettingsIntegrationNewDatabaseConnection = () => {
const { databaseKey = '' } = useParams();
const navigate = useNavigate();
const navigate = useNavigateSettings();
const navigateApp = useNavigateApp();
const [integrationCategoryAll] = useSettingsIntegrationCategories();
const integration = integrationCategoryAll.integrations.find(
@ -83,9 +86,9 @@ export const SettingsIntegrationNewDatabaseConnection = () => {
useEffect(() => {
if (!isIntegrationAvailable) {
navigate(AppPath.NotFound);
navigateApp(AppPath.NotFound);
}
}, [integration, databaseKey, navigate, isIntegrationAvailable]);
}, [integration, databaseKey, navigateApp, isIntegrationAvailable]);
const newConnectionSchema =
databaseKey === 'postgresql'
@ -99,7 +102,7 @@ export const SettingsIntegrationNewDatabaseConnection = () => {
if (!isIntegrationAvailable) return null;
const settingsIntegrationsPagePath = getSettingsPagePath(
const settingsIntegrationsPagePath = getSettingsPath(
SettingsPath.Integrations,
);
@ -118,9 +121,14 @@ export const SettingsIntegrationNewDatabaseConnection = () => {
const connectionId = createdConnection.data?.createOneRemoteServer.id;
navigate(
`${settingsIntegrationsPagePath}/${databaseKey}/${connectionId}`,
);
if (!connectionId) {
throw new Error('Failed to create connection');
}
navigate(SettingsPath.IntegrationDatabaseConnection, {
databaseKey,
connectionId,
});
} catch (error) {
enqueueSnackBar((error as Error).message, {
variant: SnackBarVariant.Error,
@ -134,7 +142,7 @@ export const SettingsIntegrationNewDatabaseConnection = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Integrations',
@ -150,7 +158,9 @@ export const SettingsIntegrationNewDatabaseConnection = () => {
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() =>
navigate(`${settingsIntegrationsPagePath}/${databaseKey}`)
navigate(SettingsPath.IntegrationDatabase, {
databaseKey,
})
}
onSave={handleSave}
/>

View File

@ -1,8 +1,8 @@
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsIntegrationDatabaseConnectionShowContainer } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionShowContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsIntegrationShowDatabaseConnection = () => {
return (
@ -11,11 +11,11 @@ export const SettingsIntegrationShowDatabaseConnection = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Integrations',
href: getSettingsPagePath(SettingsPath.Integrations),
href: getSettingsPath(SettingsPath.Integrations),
},
{ children: 'Database Connection' },
]}

View File

@ -1,10 +1,10 @@
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsIntegrationGroup } from '@/settings/integrations/components/SettingsIntegrationGroup';
import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { Trans, useLingui } from '@lingui/react/macro';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsIntegrations = () => {
const { t } = useLingui();
@ -16,7 +16,7 @@ export const SettingsIntegrations = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: <Trans>Integrations</Trans> },
]}

View File

@ -2,7 +2,6 @@ import { expect } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { within } from '@storybook/test';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SettingsIntegrationDatabase } from '~/pages/settings/integrations/SettingsIntegrationDatabase';
import {
@ -10,6 +9,7 @@ import {
PageDecoratorArgs,
} from '~/testing/decorators/PageDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { sleep } from '~/utils/sleep';
const meta: Meta<PageDecoratorArgs> = {
@ -17,7 +17,7 @@ const meta: Meta<PageDecoratorArgs> = {
component: SettingsIntegrationDatabase,
decorators: [PageDecorator],
args: {
routePath: getSettingsPagePath(SettingsPath.IntegrationDatabase),
routePath: getSettingsPath(SettingsPath.IntegrationDatabase),
routeParams: { ':databaseKey': 'postgresql' },
},
parameters: {

View File

@ -1,7 +1,6 @@
import { Meta, StoryObj } from '@storybook/react';
import { within } from '@storybook/test';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SettingsIntegrationShowDatabaseConnection } from '~/pages/settings/integrations/SettingsIntegrationShowDatabaseConnection';
import {
@ -9,6 +8,7 @@ import {
PageDecoratorArgs,
} from '~/testing/decorators/PageDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { sleep } from '~/utils/sleep';
const meta: Meta<PageDecoratorArgs> = {
@ -17,7 +17,7 @@ const meta: Meta<PageDecoratorArgs> = {
component: SettingsIntegrationShowDatabaseConnection,
decorators: [PageDecorator],
args: {
routePath: getSettingsPagePath(SettingsPath.IntegrationDatabaseConnection),
routePath: getSettingsPath(SettingsPath.IntegrationDatabaseConnection),
routeParams: {
':databaseKey': 'postgresql',
':connectionId': '67cbfd35-8dd4-4591-b9d4-c1906281a5da',

View File

@ -1,7 +1,6 @@
import { Meta, StoryObj } from '@storybook/react';
import { within } from '@storybook/test';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SettingsIntegrations } from '~/pages/settings/integrations/SettingsIntegrations';
import {
@ -9,13 +8,14 @@ import {
PageDecoratorArgs,
} from '~/testing/decorators/PageDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { sleep } from '~/utils/sleep';
const meta: Meta<PageDecoratorArgs> = {
title: 'Pages/Settings/Integrations/SettingsIntegrations',
component: SettingsIntegrations,
decorators: [PageDecorator],
args: { routePath: getSettingsPagePath(SettingsPath.Integrations) },
args: { routePath: getSettingsPath(SettingsPath.Integrations) },
parameters: {
msw: graphqlMocks,
},

View File

@ -1,7 +1,6 @@
import { ColorSchemePicker, H2Title, Section } from 'twenty-ui';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { useColorScheme } from '@/ui/theme/hooks/useColorScheme';
@ -11,6 +10,7 @@ import { Trans, useLingui } from '@lingui/react/macro';
import { FeatureFlagKey } from '~/generated/graphql';
import { DateTimeSettings } from '~/pages/settings/profile/appearance/components/DateTimeSettings';
import { LocalePicker } from '~/pages/settings/profile/appearance/components/LocalePicker';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsExperience = () => {
const { colorScheme, setColorScheme } = useColorScheme();
@ -27,7 +27,7 @@ export const SettingsExperience = () => {
links={[
{
children: <Trans>User</Trans>,
href: getSettingsPagePath(SettingsPath.ProfilePage),
href: getSettingsPath(SettingsPath.ProfilePage),
},
{ children: <Trans>Experience</Trans> },
]}

View File

@ -6,9 +6,9 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain
import { SettingsReadDocumentationButton } from '@/settings/developers/components/SettingsReadDocumentationButton';
import { SettingsSSOIdentitiesProvidersListCard } from '@/settings/security/components/SettingsSSOIdentitiesProvidersListCard';
import { SettingsSecurityOptionsList } from '@/settings/security/components/SettingsSecurityOptionsList';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const StyledContainer = styled.div`
width: 100%;
@ -35,7 +35,7 @@ export const SettingsSecurity = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: <Trans>Security</Trans> },
]}

View File

@ -6,7 +6,6 @@ import { useCreateSSOIdentityProvider } from '@/settings/security/hooks/useCreat
import { SettingSecurityNewSSOIdentityFormValues } from '@/settings/security/types/SSOIdentityProvider';
import { sSOIdentityProviderDefaultValues } from '@/settings/security/utils/sSOIdentityProviderDefaultValues';
import { SSOIdentitiesProvidersParamsSchema } from '@/settings/security/validation-schemas/SSOIdentityProviderSchema';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
@ -14,10 +13,11 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBa
import { zodResolver } from '@hookform/resolvers/zod';
import pick from 'lodash.pick';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsSecuritySSOIdentifyProvider = () => {
const navigate = useNavigate();
const navigate = useNavigateSettings();
const { enqueueSnackBar } = useSnackBar();
const { createSSOIdentityProvider } = useCreateSSOIdentityProvider();
@ -44,7 +44,7 @@ export const SettingsSecuritySSOIdentifyProvider = () => {
),
);
navigate(getSettingsPagePath(SettingsPath.Security));
navigate(SettingsPath.Security);
} catch (error) {
enqueueSnackBar((error as Error).message, {
variant: SnackBarVariant.Error,
@ -58,18 +58,18 @@ export const SettingsSecuritySSOIdentifyProvider = () => {
actionButton={
<SaveAndCancelButtons
isSaveDisabled={!formConfig.formState.isValid}
onCancel={() => navigate(getSettingsPagePath(SettingsPath.Security))}
onCancel={() => navigate(SettingsPath.Security)}
onSave={handleSave}
/>
}
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Security',
href: getSettingsPagePath(SettingsPath.Security),
href: getSettingsPath(SettingsPath.Security),
},
{ children: 'New' },
]}

View File

@ -9,7 +9,6 @@ import { useGetOneServerlessFunctionSourceCode } from '@/settings/serverless-fun
import { usePublishOneServerlessFunction } from '@/settings/serverless-functions/hooks/usePublishOneServerlessFunction';
import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
import { useUpdateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useUpdateOneServerlessFunction';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
@ -25,6 +24,7 @@ import { useDebouncedCallback } from 'use-debounce';
import { FeatureFlagKey } from '~/generated/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { isDefined } from '~/utils/isDefined';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
const TAB_LIST_COMPONENT_ID = 'serverless-function-detail';
@ -198,11 +198,11 @@ export const SettingsServerlessFunctionDetail = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Functions',
href: getSettingsPagePath(SettingsPath.ServerlessFunctions),
href: getSettingsPath(SettingsPath.ServerlessFunctions),
},
{ children: `${formValues.name}` },
]}

View File

@ -1,8 +1,8 @@
import { SettingsServerlessFunctionsTable } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsTable';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { Button, IconPlus, Section, UndecoratedLink } from 'twenty-ui';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsServerlessFunctions = () => {
return (
@ -10,7 +10,7 @@ export const SettingsServerlessFunctions = () => {
title="Functions"
actionButton={
<UndecoratedLink
to={getSettingsPagePath(SettingsPath.NewServerlessFunction)}
to={getSettingsPath(SettingsPath.NewServerlessFunction)}
>
<Button
Icon={IconPlus}
@ -23,7 +23,7 @@ export const SettingsServerlessFunctions = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Functions',

View File

@ -1,22 +1,22 @@
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { useNavigate } from 'react-router-dom';
import { SettingsServerlessFunctionNewForm } from '@/settings/serverless-functions/components/SettingsServerlessFunctionNewForm';
import { useCreateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useCreateOneServerlessFunction';
import { ServerlessFunctionNewFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useState } from 'react';
import { Key } from 'ts-key-enum';
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { isDefined } from '~/utils/isDefined';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
export const SettingsServerlessFunctionsNew = () => {
const navigate = useNavigate();
const navigate = useNavigateSettings();
const [formValues, setFormValues] = useState<ServerlessFunctionNewFormValues>(
{
name: '',
@ -34,11 +34,9 @@ export const SettingsServerlessFunctionsNew = () => {
if (!isDefined(newServerlessFunction?.data)) {
return;
}
navigate(
getSettingsPagePath(SettingsPath.ServerlessFunctions, {
id: newServerlessFunction.data.createOneServerlessFunction.id,
}),
);
navigate(SettingsPath.ServerlessFunctions, {
id: newServerlessFunction.data.createOneServerlessFunction.id,
});
};
const onChange = (key: string) => {
@ -69,7 +67,7 @@ export const SettingsServerlessFunctionsNew = () => {
useScopedHotkeys(
[Key.Escape],
() => {
navigate(getSettingsPagePath(SettingsPath.ServerlessFunctions));
navigate(SettingsPath.ServerlessFunctions);
},
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionNew,
);
@ -80,11 +78,11 @@ export const SettingsServerlessFunctionsNew = () => {
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: 'Functions',
href: getSettingsPagePath(SettingsPath.ServerlessFunctions),
href: getSettingsPath(SettingsPath.ServerlessFunctions),
},
{ children: 'New' },
]}
@ -92,7 +90,7 @@ export const SettingsServerlessFunctionsNew = () => {
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => {
navigate('/settings/functions');
navigate(SettingsPath.ServerlessFunctions);
}}
onSave={handleSave}
/>

View File

@ -3,7 +3,6 @@ import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirect
import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
@ -13,12 +12,13 @@ import styled from '@emotion/styled';
import { zodResolver } from '@hookform/resolvers/zod';
import { Trans, useLingui } from '@lingui/react/macro';
import { Controller, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { useRecoilState, useRecoilValue } from 'recoil';
import { H2Title, Section } from 'twenty-ui';
import { z } from 'zod';
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { isDefined } from '~/utils/isDefined';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
type Form = {
subdomain: string;
@ -38,7 +38,7 @@ const StyledDomain = styled.h2`
`;
export const SettingsDomain = () => {
const navigate = useNavigate();
const navigate = useNavigateSettings();
const { t } = useLingui();
const validationSchema = z
@ -126,11 +126,11 @@ export const SettingsDomain = () => {
links={[
{
children: <Trans>Workspace</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: <Trans>General</Trans>,
href: getSettingsPagePath(SettingsPath.Workspace),
href: getSettingsPath(SettingsPath.Workspace),
},
{ children: <Trans>Domain</Trans> },
]}
@ -139,7 +139,7 @@ export const SettingsDomain = () => {
isSaveDisabled={
!isValid || subdomainValue === currentWorkspace?.subdomain
}
onCancel={() => navigate(getSettingsPagePath(SettingsPath.Workspace))}
onCancel={() => navigate(SettingsPath.Workspace)}
onSave={handleSave}
/>
}