diff --git a/packages/twenty-front/src/modules/types/SettingsPath.ts b/packages/twenty-front/src/modules/types/SettingsPath.ts
index 656f57847..d0f453757 100644
--- a/packages/twenty-front/src/modules/types/SettingsPath.ts
+++ b/packages/twenty-front/src/modules/types/SettingsPath.ts
@@ -1,6 +1,6 @@
export enum SettingsPath {
ProfilePage = 'profile',
- Appearance = 'profile/appearance',
+ Appearance = 'appearance',
Accounts = 'accounts',
NewAccount = 'accounts/new',
AccountsCalendars = 'accounts/calendars',
diff --git a/packages/twenty-front/src/modules/views/components/ViewBar.tsx b/packages/twenty-front/src/modules/views/components/ViewBar.tsx
index ca9903c46..1fa164e72 100644
--- a/packages/twenty-front/src/modules/views/components/ViewBar.tsx
+++ b/packages/twenty-front/src/modules/views/components/ViewBar.tsx
@@ -5,14 +5,17 @@ import { ObjectFilterDropdownButton } from '@/object-record/object-filter-dropdo
import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
import { ObjectSortDropdownButton } from '@/object-record/object-sort-dropdown/components/ObjectSortDropdownButton';
import { TopBar } from '@/ui/layout/top-bar/TopBar';
+import { PageTitle } from '@/ui/utilities/page-title/PageTitle';
import { QueryParamsFiltersEffect } from '@/views/components/QueryParamsFiltersEffect';
import { QueryParamsViewIdEffect } from '@/views/components/QueryParamsViewIdEffect';
import { ViewBarEffect } from '@/views/components/ViewBarEffect';
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
+import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewScope } from '@/views/scopes/ViewScope';
import { GraphQLView } from '@/views/types/GraphQLView';
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
+import { capitalize } from '~/utils/string/capitalize';
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
@@ -34,6 +37,9 @@ export const ViewBar = ({
}: ViewBarProps) => {
const { objectNamePlural } = useParams();
+ const { currentViewWithCombinedFiltersAndSorts: currentView } =
+ useGetCurrentView(viewBarId);
+
const filterDropdownId = 'view-filter';
const sortDropdownId = 'view-sort';
@@ -41,6 +47,10 @@ export const ViewBar = ({
return;
}
+ const pageTitle = currentView?.name
+ ? `${currentView?.name} - ${capitalize(objectNamePlural)}`
+ : capitalize(objectNamePlural);
+
return (
+
{
return (
<>
+
diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
index dbd2aacba..51ee50fce 100644
--- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
+++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
@@ -9,7 +9,9 @@ import { useSelectedTableCellEditMode } from '@/object-record/record-table/recor
import { PageBody } from '@/ui/layout/page/PageBody';
import { PageContainer } from '@/ui/layout/page/PageContainer';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
+import { PageTitle } from '@/ui/utilities/page-title/PageTitle';
import { RecordIndexPageHeader } from '~/pages/object-record/RecordIndexPageHeader';
+import { capitalize } from '~/utils/string/capitalize';
const StyledIndexContainer = styled.div`
display: flex;
@@ -40,6 +42,7 @@ export const RecordIndexPage = () => {
return (
+
diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx
index 52c1d9f68..0a9dde69d 100644
--- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx
+++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx
@@ -18,6 +18,7 @@ import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMor
import { PageTitle } from '@/ui/utilities/page-title/PageTitle';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
+import { capitalize } from '~/utils/string/capitalize';
export const RecordShowPage = () => {
const { objectNameSingular, objectRecordId } = useParams<{
@@ -80,13 +81,20 @@ export const RecordShowPage = () => {
const labelIdentifierFieldValue =
record?.[labelIdentifierFieldMetadataItem?.name ?? ''];
+
const pageName =
labelIdentifierFieldMetadataItem?.type === FieldMetadataType.FullName
? [
labelIdentifierFieldValue?.firstName,
labelIdentifierFieldValue?.lastName,
].join(' ')
- : `${labelIdentifierFieldValue}`;
+ : isDefined(labelIdentifierFieldValue)
+ ? `${labelIdentifierFieldValue}`
+ : '';
+
+ const pageTitle = pageName.trim()
+ ? `${pageName} - ${capitalize(objectNameSingular)}`
+ : capitalize(objectNameSingular);
// Temporarily since we don't have relations for remote objects yet
if (objectMetadataItem.isRemote) {
@@ -95,7 +103,7 @@ export const RecordShowPage = () => {
return (
-
+
{
it('should return the correct title for a given path', () => {
@@ -13,14 +13,39 @@ describe('title-utils', () => {
expect(getPageTitleFromPath('/objects/opportunities')).toBe(
'Opportunities',
);
- expect(getPageTitleFromPath('/settings/profile')).toBe('Profile');
- expect(getPageTitleFromPath('/settings/profile/appearance')).toBe(
- 'Appearance',
+ expect(getPageTitleFromPath('/settings/objects/opportunities')).toBe(
+ SettingsPageTitles.Objects,
+ );
+ expect(getPageTitleFromPath('/settings/profile')).toBe(
+ SettingsPageTitles.Profile,
+ );
+ expect(getPageTitleFromPath('/settings/appearance')).toBe(
+ SettingsPageTitles.Appearance,
+ );
+ expect(getPageTitleFromPath('/settings/accounts')).toBe(
+ SettingsPageTitles.Accounts,
+ );
+ expect(getPageTitleFromPath('/settings/accounts/new')).toBe(
+ SettingsPageTitles.Accounts,
+ );
+ expect(getPageTitleFromPath('/settings/accounts/calendars')).toBe(
+ SettingsPageTitles.Accounts,
+ );
+ expect(
+ getPageTitleFromPath('/settings/accounts/calendars/:accountUuid'),
+ ).toBe(SettingsPageTitles.Accounts);
+ expect(getPageTitleFromPath('/settings/accounts/emails')).toBe(
+ SettingsPageTitles.Accounts,
+ );
+ expect(getPageTitleFromPath('/settings/accounts/emails/:accountUuid')).toBe(
+ SettingsPageTitles.Accounts,
);
expect(getPageTitleFromPath('/settings/workspace-members')).toBe(
- 'Workspace Members',
+ SettingsPageTitles.Members,
+ );
+ expect(getPageTitleFromPath('/settings/workspace')).toBe(
+ SettingsPageTitles.General,
);
- expect(getPageTitleFromPath('/settings/workspace')).toBe('Workspace');
expect(getPageTitleFromPath('/')).toBe('Twenty');
expect(getPageTitleFromPath('/random')).toBe('Twenty');
});
diff --git a/packages/twenty-front/src/utils/title-utils.ts b/packages/twenty-front/src/utils/title-utils.ts
index 8723e9aa5..9d604c5ee 100644
--- a/packages/twenty-front/src/utils/title-utils.ts
+++ b/packages/twenty-front/src/utils/title-utils.ts
@@ -2,8 +2,41 @@ import { AppBasePath } from '@/types/AppBasePath';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
+export enum SettingsPageTitles {
+ Accounts = 'Account - Settings',
+ Appearance = 'Appearance - Settings',
+ Profile = 'Profile - Settings',
+ Objects = 'Data model - Settings',
+ Members = 'Members - Settings',
+ Developers = 'Developers - Settings',
+ Integration = 'Integrations - Settings',
+ General = 'General - Settings',
+ Default = 'Settings',
+}
+
+enum SettingsPathPrefixes {
+ Accounts = `${AppBasePath.Settings}/${SettingsPath.Accounts}`,
+ Appearance = `${AppBasePath.Settings}/${SettingsPath.Appearance}`,
+ Profile = `${AppBasePath.Settings}/${SettingsPath.ProfilePage}`,
+ Objects = `${AppBasePath.Settings}/${SettingsPath.Objects}`,
+ Members = `${AppBasePath.Settings}/${SettingsPath.WorkspaceMembersPage}`,
+ Developers = `${AppBasePath.Settings}/${SettingsPath.Developers}`,
+ Integration = `${AppBasePath.Settings}/${SettingsPath.Integrations}`,
+ General = `${AppBasePath.Settings}/${SettingsPath.Workspace}`,
+}
+
+const getPathnameOrPrefix = (pathname: string) => {
+ for (const prefix of Object.values(SettingsPathPrefixes)) {
+ if (pathname.startsWith(prefix)) {
+ return prefix;
+ }
+ }
+ return pathname;
+};
+
export const getPageTitleFromPath = (pathname: string): string => {
- switch (pathname) {
+ const pathnameOrPrefix = getPathnameOrPrefix(pathname);
+ switch (pathnameOrPrefix) {
case AppPath.Verify:
return 'Verify';
case AppPath.SignInUp:
@@ -18,14 +51,22 @@ export const getPageTitleFromPath = (pathname: string): string => {
return 'Tasks';
case AppPath.OpportunitiesPage:
return 'Opportunities';
- case `${AppBasePath.Settings}/${SettingsPath.ProfilePage}`:
- return 'Profile';
- case `${AppBasePath.Settings}/${SettingsPath.Appearance}`:
- return 'Appearance';
- case `${AppBasePath.Settings}/${SettingsPath.WorkspaceMembersPage}`:
- return 'Workspace Members';
- case `${AppBasePath.Settings}/${SettingsPath.Workspace}`:
- return 'Workspace';
+ case SettingsPathPrefixes.Appearance:
+ return SettingsPageTitles.Appearance;
+ case SettingsPathPrefixes.Accounts:
+ return SettingsPageTitles.Accounts;
+ case SettingsPathPrefixes.Profile:
+ return SettingsPageTitles.Profile;
+ case SettingsPathPrefixes.Members:
+ return SettingsPageTitles.Members;
+ case SettingsPathPrefixes.Objects:
+ return SettingsPageTitles.Objects;
+ case SettingsPathPrefixes.Developers:
+ return SettingsPageTitles.Developers;
+ case SettingsPathPrefixes.Integration:
+ return SettingsPageTitles.Integration;
+ case SettingsPathPrefixes.General:
+ return SettingsPageTitles.General;
default:
return 'Twenty';
}