diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkspaceMembersActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkspaceMembersActionsConfig.tsx
new file mode 100644
index 0000000000..b6476ec3c6
--- /dev/null
+++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkspaceMembersActionsConfig.tsx
@@ -0,0 +1,124 @@
+import { ActionLink } from '@/action-menu/actions/components/ActionLink';
+import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
+import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
+import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
+import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig';
+import { ActionScope } from '@/action-menu/actions/types/ActionScope';
+import { ActionType } from '@/action-menu/actions/types/ActionType';
+import { ActionViewType } from '@/action-menu/actions/types/ActionViewType';
+import { msg } from '@lingui/core/macro';
+import { AppPath, SettingsPath } from 'twenty-shared/types';
+import { IconSettings } from 'twenty-ui/display';
+
+export const WORKSPACE_MEMBERS_ACTIONS_CONFIG = inheritActionsFromDefaultConfig(
+ {
+ config: {
+ [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: {
+ type: ActionType.Navigation,
+ scope: ActionScope.Global,
+ key: NoSelectionRecordActionKeys.GO_TO_SETTINGS,
+ label: msg`Manage members in settings`,
+ shortLabel: msg`Manage in settings`,
+ position: 14,
+ Icon: IconSettings,
+ isPinned: true,
+ availableOn: [
+ ActionViewType.INDEX_PAGE_NO_SELECTION,
+ ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ActionViewType.INDEX_PAGE_BULK_SELECTION,
+ ActionViewType.SHOW_PAGE,
+ ],
+ shouldBeRegistered: () => true,
+ component: (
+
+ ),
+ hotKeys: ['G', 'S'],
+ },
+ },
+ actionKeys: [
+ SingleRecordActionKeys.ADD_TO_FAVORITES,
+ SingleRecordActionKeys.REMOVE_FROM_FAVORITES,
+ SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD,
+ SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD,
+ SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX,
+ SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW,
+ MultipleRecordsActionKeys.EXPORT,
+ NoSelectionRecordActionKeys.EXPORT_VIEW,
+ NoSelectionRecordActionKeys.SEE_DELETED_RECORDS,
+ NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS,
+ NoSelectionRecordActionKeys.GO_TO_WORKFLOWS,
+ NoSelectionRecordActionKeys.GO_TO_PEOPLE,
+ NoSelectionRecordActionKeys.GO_TO_COMPANIES,
+ NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES,
+ NoSelectionRecordActionKeys.GO_TO_DASHBOARDS,
+ NoSelectionRecordActionKeys.GO_TO_TASKS,
+ NoSelectionRecordActionKeys.GO_TO_NOTES,
+ ],
+ propertiesToOverwrite: {
+ [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
+ isPinned: false,
+ position: 0,
+ },
+ [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: {
+ isPinned: false,
+ position: 1,
+ },
+ [SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX]: {
+ position: 2,
+ label: msg`Export member`,
+ },
+ [SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW]: {
+ position: 2,
+ label: msg`Export member`,
+ },
+ [MultipleRecordsActionKeys.EXPORT]: {
+ position: 3,
+ label: msg`Export members`,
+ },
+ [NoSelectionRecordActionKeys.EXPORT_VIEW]: {
+ position: 4,
+ label: msg`Export view`,
+ },
+ [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: {
+ position: 5,
+ label: msg`See deleted members`,
+ },
+ [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: {
+ position: 6,
+ label: msg`Hide deleted members`,
+ },
+ [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
+ position: 7,
+ },
+ [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: {
+ position: 8,
+ },
+ [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: {
+ position: 9,
+ },
+ [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: {
+ position: 10,
+ },
+ [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: {
+ position: 11,
+ },
+ [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: {
+ position: 12,
+ },
+ [NoSelectionRecordActionKeys.GO_TO_DASHBOARDS]: {
+ position: 13,
+ },
+ [NoSelectionRecordActionKeys.GO_TO_TASKS]: {
+ position: 15,
+ },
+ [NoSelectionRecordActionKeys.GO_TO_NOTES]: {
+ position: 16,
+ },
+ },
+ },
+);
diff --git a/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts
index 31ea3ebe50..c5bed2d8e2 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts
+++ b/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts
@@ -4,6 +4,7 @@ import { RECORD_PAGE_LAYOUT_ACTIONS_CONFIG } from '@/action-menu/actions/record-
import { WORKFLOW_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowActionsConfig';
import { WORKFLOW_RUNS_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig';
import { WORKFLOW_VERSIONS_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig';
+import { WORKSPACE_MEMBERS_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkspaceMembersActionsConfig';
import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
@@ -33,6 +34,9 @@ export const getActionConfig = ({
case CoreObjectNameSingular.WorkflowRun: {
return WORKFLOW_RUNS_ACTIONS_CONFIG;
}
+ case CoreObjectNameSingular.WorkspaceMember: {
+ return WORKSPACE_MEMBERS_ACTIONS_CONFIG;
+ }
case CoreObjectNameSingular.Company: {
if (isRecordPageLayoutEnabled) {
return RECORD_PAGE_LAYOUT_ACTIONS_CONFIG;
diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerOpenedSection.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerOpenedSection.tsx
index 5538313763..aa94f97fcc 100644
--- a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerOpenedSection.tsx
+++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerOpenedSection.tsx
@@ -10,10 +10,9 @@ import { useLingui } from '@lingui/react/macro';
export const NavigationDrawerOpenedSection = () => {
const { t } = useLingui();
- const { activeNonSystemObjectMetadataItems } =
- useFilteredObjectMetadataItems();
+ const { activeObjectMetadataItems } = useFilteredObjectMetadataItems();
const filteredActiveNonSystemObjectMetadataItems =
- activeNonSystemObjectMetadataItems.filter((item) => !item.isRemote);
+ activeObjectMetadataItems.filter((item) => !item.isRemote);
const loading = useIsPrefetchLoading();
diff --git a/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationDetailContentTab.tsx b/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationDetailContentTab.tsx
index 0b581cd5d0..cfdb3d8d37 100644
--- a/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationDetailContentTab.tsx
+++ b/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationDetailContentTab.tsx
@@ -66,8 +66,7 @@ export const SettingsApplicationDetailContentTab = ({
description={t`Objects created by application`}
/>
diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx
index 820a8bb31e..bd686c4bc0 100644
--- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx
@@ -14,6 +14,7 @@ import styled from '@emotion/styled';
import { useRecoilState, useRecoilValue } from 'recoil';
import { AppPath, SettingsPath } from 'twenty-shared/types';
+import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
@@ -34,7 +35,6 @@ 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 { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
const StyledContentContainer = styled.div`
flex: 1;
@@ -57,15 +57,15 @@ export const SettingsObjectDetailPage = () => {
const { t } = useLingui();
const { objectNamePlural = '' } = useParams();
- const { findActiveObjectMetadataItemByNamePlural } =
+ const { findObjectMetadataItemByNamePlural } =
useFilteredObjectMetadataItems();
const [updatedObjectNamePlural, setUpdatedObjectNamePlural] = useRecoilState(
updatedObjectNamePluralState,
);
const objectMetadataItem =
- findActiveObjectMetadataItemByNamePlural(objectNamePlural) ??
- findActiveObjectMetadataItemByNamePlural(updatedObjectNamePlural);
+ findObjectMetadataItemByNamePlural(objectNamePlural) ??
+ findObjectMetadataItemByNamePlural(updatedObjectNamePlural);
const readonly = isObjectMetadataSettingsReadOnly({ objectMetadataItem });
diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx
index d8fc991b6f..5b103097ef 100644
--- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx
@@ -9,19 +9,30 @@ import {
import { SettingsObjectInactiveMenuDropDown } from '@/settings/data-model/objects/components/SettingsObjectInactiveMenuDropDown';
import { getItemTagInfo } from '@/settings/data-model/utils/getItemTagInfo';
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
+import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
+import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
+import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { SortableTableHeader } from '@/ui/layout/table/components/SortableTableHeader';
import { Table } from '@/ui/layout/table/components/Table';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
-import { TableSection } from '@/ui/layout/table/components/TableSection';
import { useSortedArray } from '@/ui/layout/table/hooks/useSortedArray';
+import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
-import { isNonEmptyArray } from '@sniptt/guards';
import { useMemo, useState } from 'react';
+import { useRecoilValue } from 'recoil';
import { SettingsPath } from 'twenty-shared/types';
import { getSettingsPath } from 'twenty-shared/utils';
-import { IconChevronRight, IconSearch } from 'twenty-ui/display';
+import {
+ IconArchive,
+ IconChevronRight,
+ IconFilter,
+ IconSearch,
+ IconSettings,
+} from 'twenty-ui/display';
+import { Button } from 'twenty-ui/input';
+import { MenuItemToggle } from 'twenty-ui/navigation';
import { GET_SETTINGS_OBJECT_TABLE_METADATA } from '~/pages/settings/data-model/constants/SettingsObjectTableMetadata';
import type { SettingsObjectTableItem } from '~/pages/settings/data-model/types/SettingsObjectTableItem';
import { normalizeSearchText } from '~/utils/normalizeSearchText';
@@ -30,25 +41,34 @@ const StyledIconChevronRight = styled(IconChevronRight)`
color: ${({ theme }) => theme.font.color.tertiary};
`;
-const StyledSearchInput = styled(SettingsTextInput)`
+const StyledSearchAndFilterContainer = styled.div`
+ display: flex;
+ gap: ${({ theme }) => theme.spacing(2)};
+ align-items: center;
padding-bottom: ${({ theme }) => theme.spacing(2)};
+`;
+
+const StyledSearchInput = styled(SettingsTextInput)`
+ flex: 1;
width: 100%;
`;
export const SettingsObjectTable = ({
- activeObjects,
- inactiveObjects,
+ objectMetadataItems,
withSearchBar = true,
}: {
- activeObjects: ObjectMetadataItem[];
- inactiveObjects: ObjectMetadataItem[];
+ objectMetadataItems: ObjectMetadataItem[];
withSearchBar?: boolean;
}) => {
const { t } = useLingui();
const theme = useTheme();
+ const isAdvancedModeEnabled = useRecoilValue(isAdvancedModeEnabledState);
+
const [searchTerm, setSearchTerm] = useState('');
+ const [showDeactivated, setShowDeactivated] = useState(false);
+ const [showSystemObjects, setShowSystemObjects] = useState(false);
const { deleteOneObjectMetadataItem } = useDeleteOneObjectMetadataItem();
@@ -56,13 +76,13 @@ export const SettingsObjectTable = ({
const { totalCountByObjectMetadataItemNamePlural } = useCombinedGetTotalCount(
{
- objectMetadataItems: [...activeObjects, ...inactiveObjects],
+ objectMetadataItems,
},
);
- const activeObjectSettingsArray = useMemo(
+ const allObjectSettingsArray = useMemo(
() =>
- activeObjects.map(
+ objectMetadataItems.map(
(objectMetadataItem) =>
({
objectMetadataItem,
@@ -77,76 +97,91 @@ export const SettingsObjectTable = ({
] ?? 0,
}) satisfies SettingsObjectTableItem,
),
- [activeObjects, totalCountByObjectMetadataItemNamePlural],
+ [objectMetadataItems, totalCountByObjectMetadataItemNamePlural],
);
- const inactiveObjectSettingsArray = useMemo(
- () =>
- inactiveObjects.map(
- (objectMetadataItem) =>
- ({
- objectMetadataItem,
- labelPlural: objectMetadataItem.labelPlural,
- objectTypeLabel: getItemTagInfo({
- isCustom: objectMetadataItem.isCustom,
- isRemote: objectMetadataItem.isRemote,
- }).labelText,
- fieldsCount: objectMetadataItem.fields.filter(
- (field) => !field.isSystem,
- ).length,
- totalObjectCount:
- totalCountByObjectMetadataItemNamePlural[
- objectMetadataItem.namePlural
- ] ?? 0,
- }) satisfies SettingsObjectTableItem,
- ),
- [inactiveObjects, totalCountByObjectMetadataItemNamePlural],
- );
-
- const sortedActiveObjectSettingsItems = useSortedArray(
- activeObjectSettingsArray,
+ const sortedObjectSettingsItems = useSortedArray(
+ allObjectSettingsArray,
GET_SETTINGS_OBJECT_TABLE_METADATA,
);
- const sortedInactiveObjectSettingsItems = useSortedArray(
- inactiveObjectSettingsArray,
- GET_SETTINGS_OBJECT_TABLE_METADATA,
- );
-
- const filteredActiveObjectSettingsItems = useMemo(
+ const filteredObjectSettingsItems = useMemo(
() =>
- sortedActiveObjectSettingsItems.filter((item) => {
+ sortedObjectSettingsItems.filter((item) => {
const searchNormalized = normalizeSearchText(searchTerm);
- return (
+ const matchesSearch =
normalizeSearchText(item.labelPlural).includes(searchNormalized) ||
- normalizeSearchText(item.objectTypeLabel).includes(searchNormalized)
- );
- }),
- [sortedActiveObjectSettingsItems, searchTerm],
- );
+ normalizeSearchText(item.objectTypeLabel).includes(searchNormalized);
- const filteredInactiveObjectSettingsItems = useMemo(
- () =>
- sortedInactiveObjectSettingsItems.filter((item) => {
- const searchNormalized = normalizeSearchText(searchTerm);
- return (
- normalizeSearchText(item.labelPlural).includes(searchNormalized) ||
- normalizeSearchText(item.objectTypeLabel).includes(searchNormalized)
- );
+ if (!matchesSearch) {
+ return false;
+ }
+
+ const isActive = item.objectMetadataItem.isActive;
+ if (!isActive && !showDeactivated) {
+ return false;
+ }
+
+ const isSystem = item.objectMetadataItem.isSystem;
+ if (isSystem && !showSystemObjects) {
+ return false;
+ }
+
+ return true;
}),
- [sortedInactiveObjectSettingsItems, searchTerm],
+ [sortedObjectSettingsItems, searchTerm, showDeactivated, showSystemObjects],
);
return (
<>
{withSearchBar && (
-
+
+
+
+ }
+ dropdownComponents={
+
+
+ setShowDeactivated(!showDeactivated)}
+ toggled={showDeactivated}
+ text={t`Deactivated`}
+ toggleSize="small"
+ />
+ {isAdvancedModeEnabled && (
+
+ setShowSystemObjects(!showSystemObjects)
+ }
+ toggled={showSystemObjects}
+ text={t`System objects`}
+ toggleSize="small"
+ />
+ )}
+
+
+ }
+ />
+
)}
@@ -165,35 +200,21 @@ export const SettingsObjectTable = ({
)}
- {isNonEmptyArray(sortedActiveObjectSettingsItems) && (
-
- {filteredActiveObjectSettingsItems.map((objectSettingsItem) => (
- {
+ const isActive = objectSettingsItem.objectMetadataItem.isActive;
+
+ return (
+
- }
- link={getSettingsPath(SettingsPath.ObjectDetail, {
- objectNamePlural:
- objectSettingsItem.objectMetadataItem.namePlural,
- })}
- />
- ))}
-
- )}
- {isNonEmptyArray(sortedInactiveObjectSettingsItems) && (
-
- {filteredInactiveObjectSettingsItems.map((objectSettingsItem) => (
-
- }
- />
- ))}
-
- )}
+ )
+ }
+ link={
+ isActive
+ ? getSettingsPath(SettingsPath.ObjectDetail, {
+ objectNamePlural:
+ objectSettingsItem.objectMetadataItem.namePlural,
+ })
+ : undefined
+ }
+ />
+ );
+ })}
>
);
diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx
index 72221fc245..85607d7728 100644
--- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjects.tsx
@@ -15,10 +15,7 @@ import { SettingsObjectTable } from '~/pages/settings/data-model/SettingsObjectT
export const SettingsObjects = () => {
const { t } = useLingui();
- const {
- activeNonSystemObjectMetadataItems,
- inactiveNonSystemObjectMetadataItems,
- } = useFilteredObjectMetadataItems();
+ const { objectMetadataItems } = useFilteredObjectMetadataItems();
return (
{
>
diff --git a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldConfigure.tsx b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldConfigure.tsx
index 0d165d45a3..581d726dbf 100644
--- a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldConfigure.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldConfigure.tsx
@@ -49,10 +49,10 @@ export const SettingsObjectNewFieldConfigure = () => {
FieldMetadataType.TEXT;
const { enqueueErrorSnackBar } = useSnackBar();
- const { findActiveObjectMetadataItemByNamePlural } =
+ const { findObjectMetadataItemByNamePlural } =
useFilteredObjectMetadataItems();
const activeObjectMetadataItem =
- findActiveObjectMetadataItemByNamePlural(objectNamePlural);
+ findObjectMetadataItemByNamePlural(objectNamePlural);
const { createMetadataField } = useFieldMetadataItem();
const formConfig = useForm({
diff --git a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx
index 4df58c1c13..107223d569 100644
--- a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx
+++ b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx
@@ -33,10 +33,10 @@ export type SettingsDataModelFieldTypeFormValues = z.infer<
export const SettingsObjectNewFieldSelect = () => {
const navigate = useNavigateApp();
const { objectNamePlural = '' } = useParams();
- const { findActiveObjectMetadataItemByNamePlural } =
+ const { findObjectMetadataItemByNamePlural } =
useFilteredObjectMetadataItems();
const activeObjectMetadataItem =
- findActiveObjectMetadataItemByNamePlural(objectNamePlural);
+ findObjectMetadataItemByNamePlural(objectNamePlural);
const formMethods = useForm({
resolver: zodResolver(settingsDataModelFieldTypeFormSchema),
defaultValues: {
diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts
index 1b3ada68c8..0da404bb20 100644
--- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts
@@ -16,8 +16,11 @@ import { type WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manage
import { shouldSeedWorkspaceFavorite } from 'src/engine/utils/should-seed-workspace-favorite';
import { prefillWorkspaceFavorites } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workspace-favorites';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
+import { calendarEventsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/calendar-events-all.view';
import { companiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view';
import { dashboardsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/dashboards-all.view';
+import { messageThreadsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/message-threads-all.view';
+import { messagesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/messages-all.view';
import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view';
import { opportunitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view';
import { opportunitiesByStageView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-by-stage.view';
@@ -28,6 +31,7 @@ import { tasksByStatusView } from 'src/engine/workspace-manager/standard-objects
import { workflowRunsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-runs-all.view';
import { workflowVersionsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-versions-all.view';
import { workflowsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view';
+import { workspaceMembersAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workspace-members-all.view';
type PrefillCoreViewsArgs = {
coreDataSource: DataSource;
@@ -56,6 +60,10 @@ export const prefillCoreViews = async ({
workflowVersionsAllView(objectMetadataItems, true),
workflowRunsAllView(objectMetadataItems, true),
dashboardsAllView(objectMetadataItems, true),
+ workspaceMembersAllView(objectMetadataItems, true),
+ messagesAllView(objectMetadataItems, true),
+ messageThreadsAllView(objectMetadataItems, true),
+ calendarEventsAllView(objectMetadataItems, true),
];
const queryRunner = coreDataSource.createQueryRunner();
diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/calendar-events-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/calendar-events-all.view.ts
new file mode 100644
index 0000000000..2ec1ee3507
--- /dev/null
+++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/calendar-events-all.view.ts
@@ -0,0 +1,122 @@
+import { msg } from '@lingui/core/macro';
+
+import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
+import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
+import {
+ BASE_OBJECT_STANDARD_FIELD_IDS,
+ CALENDAR_EVENT_STANDARD_FIELD_IDS,
+} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
+import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
+
+export const calendarEventsAllView = (
+ objectMetadataItems: ObjectMetadataEntity[],
+ useCoreNaming = false,
+) => {
+ const calendarEventObjectMetadata = objectMetadataItems.find(
+ (object) => object.standardId === STANDARD_OBJECT_IDS.calendarEvent,
+ );
+
+ if (!calendarEventObjectMetadata) {
+ throw new Error('CalendarEvent object metadata not found');
+ }
+
+ return {
+ name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Calendar Events',
+ objectMetadataId: calendarEventObjectMetadata.id ?? '',
+ type: 'calendar',
+ key: 'INDEX',
+ position: 0,
+ icon: 'IconCalendar',
+ kanbanFieldMetadataId: '',
+ calendarFieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === CALENDAR_EVENT_STANDARD_FIELD_IDS.startsAt,
+ )?.id ?? '',
+ calendarLayout: 'MONTH',
+ filters: [],
+ fields: [
+ {
+ fieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === CALENDAR_EVENT_STANDARD_FIELD_IDS.title,
+ )?.id ?? '',
+ position: 0,
+ isVisible: true,
+ size: DEFAULT_VIEW_FIELD_SIZE,
+ },
+ {
+ fieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === CALENDAR_EVENT_STANDARD_FIELD_IDS.startsAt,
+ )?.id ?? '',
+ position: 1,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === CALENDAR_EVENT_STANDARD_FIELD_IDS.endsAt,
+ )?.id ?? '',
+ position: 2,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === CALENDAR_EVENT_STANDARD_FIELD_IDS.isFullDay,
+ )?.id ?? '',
+ position: 3,
+ isVisible: true,
+ size: 100,
+ },
+ {
+ fieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === CALENDAR_EVENT_STANDARD_FIELD_IDS.location,
+ )?.id ?? '',
+ position: 4,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId ===
+ CALENDAR_EVENT_STANDARD_FIELD_IDS.conferenceLink,
+ )?.id ?? '',
+ position: 5,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === CALENDAR_EVENT_STANDARD_FIELD_IDS.isCanceled,
+ )?.id ?? '',
+ position: 6,
+ isVisible: true,
+ size: 100,
+ },
+ {
+ fieldMetadataId:
+ calendarEventObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
+ )?.id ?? '',
+ position: 7,
+ isVisible: true,
+ size: 150,
+ },
+ ],
+ };
+};
diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/message-threads-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/message-threads-all.view.ts
new file mode 100644
index 0000000000..fecd0ffe3d
--- /dev/null
+++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/message-threads-all.view.ts
@@ -0,0 +1,55 @@
+import { msg } from '@lingui/core/macro';
+
+import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
+import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
+import {
+ BASE_OBJECT_STANDARD_FIELD_IDS,
+ MESSAGE_THREAD_STANDARD_FIELD_IDS,
+} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
+import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
+
+export const messageThreadsAllView = (
+ objectMetadataItems: ObjectMetadataEntity[],
+ useCoreNaming = false,
+) => {
+ const messageThreadObjectMetadata = objectMetadataItems.find(
+ (object) => object.standardId === STANDARD_OBJECT_IDS.messageThread,
+ );
+
+ if (!messageThreadObjectMetadata) {
+ throw new Error('MessageThread object metadata not found');
+ }
+
+ return {
+ name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Message Threads',
+ objectMetadataId: messageThreadObjectMetadata.id ?? '',
+ type: 'table',
+ key: 'INDEX',
+ position: 0,
+ icon: 'IconList',
+ kanbanFieldMetadataId: '',
+ filters: [],
+ fields: [
+ {
+ fieldMetadataId:
+ messageThreadObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === MESSAGE_THREAD_STANDARD_FIELD_IDS.messages,
+ )?.id ?? '',
+ position: 0,
+ isVisible: true,
+ size: DEFAULT_VIEW_FIELD_SIZE,
+ },
+ {
+ fieldMetadataId:
+ messageThreadObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
+ )?.id ?? '',
+ position: 1,
+ isVisible: true,
+ size: 150,
+ },
+ ],
+ };
+};
diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/messages-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/messages-all.view.ts
new file mode 100644
index 0000000000..b06d925567
--- /dev/null
+++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/messages-all.view.ts
@@ -0,0 +1,104 @@
+import { msg } from '@lingui/core/macro';
+
+import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
+import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
+import {
+ BASE_OBJECT_STANDARD_FIELD_IDS,
+ MESSAGE_STANDARD_FIELD_IDS,
+} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
+import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
+
+export const messagesAllView = (
+ objectMetadataItems: ObjectMetadataEntity[],
+ useCoreNaming = false,
+) => {
+ const messageObjectMetadata = objectMetadataItems.find(
+ (object) => object.standardId === STANDARD_OBJECT_IDS.message,
+ );
+
+ if (!messageObjectMetadata) {
+ throw new Error('Message object metadata not found');
+ }
+
+ return {
+ name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Messages',
+ objectMetadataId: messageObjectMetadata.id ?? '',
+ type: 'table',
+ key: 'INDEX',
+ position: 0,
+ icon: 'IconList',
+ kanbanFieldMetadataId: '',
+ filters: [],
+ fields: [
+ {
+ fieldMetadataId:
+ messageObjectMetadata.fields.find(
+ (field) => field.standardId === MESSAGE_STANDARD_FIELD_IDS.subject,
+ )?.id ?? '',
+ position: 0,
+ isVisible: true,
+ size: DEFAULT_VIEW_FIELD_SIZE,
+ },
+ {
+ fieldMetadataId:
+ messageObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === MESSAGE_STANDARD_FIELD_IDS.messageThread,
+ )?.id ?? '',
+ position: 1,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ messageObjectMetadata.fields.find(
+ (field) =>
+ field.standardId ===
+ MESSAGE_STANDARD_FIELD_IDS.messageParticipants,
+ )?.id ?? '',
+ position: 2,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ messageObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === MESSAGE_STANDARD_FIELD_IDS.receivedAt,
+ )?.id ?? '',
+ position: 3,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ messageObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === MESSAGE_STANDARD_FIELD_IDS.headerMessageId,
+ )?.id ?? '',
+ position: 4,
+ isVisible: true,
+ size: 180,
+ },
+ {
+ fieldMetadataId:
+ messageObjectMetadata.fields.find(
+ (field) => field.standardId === MESSAGE_STANDARD_FIELD_IDS.text,
+ )?.id ?? '',
+ position: 5,
+ isVisible: true,
+ size: 200,
+ },
+ {
+ fieldMetadataId:
+ messageObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
+ )?.id ?? '',
+ position: 6,
+ isVisible: true,
+ size: 150,
+ },
+ ],
+ };
+};
diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workspace-members-all.view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workspace-members-all.view.ts
new file mode 100644
index 0000000000..685127e56b
--- /dev/null
+++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/views/workspace-members-all.view.ts
@@ -0,0 +1,132 @@
+import { msg } from '@lingui/core/macro';
+
+import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
+import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
+import {
+ BASE_OBJECT_STANDARD_FIELD_IDS,
+ WORKSPACE_MEMBER_STANDARD_FIELD_IDS,
+} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
+import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
+
+export const workspaceMembersAllView = (
+ objectMetadataItems: ObjectMetadataEntity[],
+ useCoreNaming = false,
+) => {
+ const workspaceMemberObjectMetadata = objectMetadataItems.find(
+ (object) => object.standardId === STANDARD_OBJECT_IDS.workspaceMember,
+ );
+
+ if (!workspaceMemberObjectMetadata) {
+ throw new Error('WorkspaceMember object metadata not found');
+ }
+
+ return {
+ name: useCoreNaming
+ ? msg`All {objectLabelPlural}`
+ : 'All Workspace Members',
+ objectMetadataId: workspaceMemberObjectMetadata.id ?? '',
+ type: 'table',
+ key: 'INDEX',
+ position: 0,
+ icon: 'IconList',
+ kanbanFieldMetadataId: '',
+ filters: [],
+ fields: [
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === WORKSPACE_MEMBER_STANDARD_FIELD_IDS.name,
+ )?.id ?? '',
+ position: 0,
+ isVisible: true,
+ size: DEFAULT_VIEW_FIELD_SIZE,
+ },
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId ===
+ WORKSPACE_MEMBER_STANDARD_FIELD_IDS.userEmail,
+ )?.id ?? '',
+ position: 1,
+ isVisible: true,
+ size: 180,
+ },
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId ===
+ WORKSPACE_MEMBER_STANDARD_FIELD_IDS.avatarUrl,
+ )?.id ?? '',
+ position: 2,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId ===
+ WORKSPACE_MEMBER_STANDARD_FIELD_IDS.colorScheme,
+ )?.id ?? '',
+ position: 3,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === WORKSPACE_MEMBER_STANDARD_FIELD_IDS.locale,
+ )?.id ?? '',
+ position: 4,
+ isVisible: true,
+ size: 120,
+ },
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === WORKSPACE_MEMBER_STANDARD_FIELD_IDS.timeZone,
+ )?.id ?? '',
+ position: 5,
+ isVisible: true,
+ size: 150,
+ },
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId ===
+ WORKSPACE_MEMBER_STANDARD_FIELD_IDS.dateFormat,
+ )?.id ?? '',
+ position: 6,
+ isVisible: true,
+ size: 120,
+ },
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId ===
+ WORKSPACE_MEMBER_STANDARD_FIELD_IDS.timeFormat,
+ )?.id ?? '',
+ position: 7,
+ isVisible: true,
+ size: 120,
+ },
+ {
+ fieldMetadataId:
+ workspaceMemberObjectMetadata.fields.find(
+ (field) =>
+ field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
+ )?.id ?? '',
+ position: 8,
+ isVisible: true,
+ size: 150,
+ },
+ ],
+ };
+};
diff --git a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-run.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-run.workspace-entity.ts
index fb53c70ae4..92a611d36d 100644
--- a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-run.workspace-entity.ts
+++ b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-run.workspace-entity.ts
@@ -2,9 +2,9 @@ import { registerEnumType } from '@nestjs/graphql';
import { msg } from '@lingui/core/macro';
import {
+ ActorMetadata,
FieldMetadataType,
RelationOnDeleteAction,
- ActorMetadata,
} from 'twenty-shared/types';
import { type WorkflowRunStepInfos } from 'twenty-shared/workflow';
@@ -92,6 +92,7 @@ export const SEARCH_FIELDS_FOR_WORKFLOW_RUNS: FieldTypeAndNameMetadata[] = [
labelIdentifierStandardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.name,
icon: STANDARD_OBJECT_ICONS.workflowRun,
})
+@WorkspaceIsSystem()
@WorkspaceIsNotAuditLogged()
@WorkspaceIsObjectUIReadOnly()
export class WorkflowRunWorkspaceEntity extends BaseWorkspaceEntity {
diff --git a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts
index ccf782b3ec..ce54c4b633 100644
--- a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts
+++ b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts
@@ -80,6 +80,7 @@ export const SEARCH_FIELDS_FOR_WORKFLOW_VERSIONS: FieldTypeAndNameMetadata[] = [
icon: STANDARD_OBJECT_ICONS.workflowVersion,
labelIdentifierStandardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.name,
})
+@WorkspaceIsSystem()
@WorkspaceIsObjectUIReadOnly()
export class WorkflowVersionWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({