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:
@ -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>
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
@ -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)}
|
||||
/>
|
||||
}
|
||||
|
||||
@ -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)}
|
||||
|
||||
@ -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 /> },
|
||||
]}
|
||||
|
||||
@ -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' },
|
||||
{
|
||||
|
||||
@ -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,
|
||||
})}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user