feat: Add filter button to objects table and enable system objects access (#15856)

## Summary
This PR replaces the Active/Inactive accordion sections with a modern
filter dropdown button and enables full access to system objects in
advanced mode.

## Changes

### UI Improvements
-  Replaced accordion sections with a filter button dropdown (matching
the design pattern from the Group filter)
-  Added 'Deactivated' toggle filter (hidden by default, uses
IconArchive)
-  Added 'System objects' toggle filter (only visible in advanced mode,
uses IconSettings)
-  Fixed search input width to properly fill available space
-  Proper button sizing and alignment

### System Objects Support
-  Made system objects visible when 'System objects' filter is toggled
on
-  System objects are now fully clickable and accessible
-  Updated object detail page to support system objects
-  Updated field creation/edit pages to support system objects
-  System objects can now have custom fields added

### Architecture
-  Implemented scalable filter architecture using a single filtered
list
-  Easy to add more filters in the future (e.g., show remote objects)
-  All filters work independently and can be combined

## Testing
- [x] Tested deactivated objects toggle
- [x] Tested system objects toggle (only shows in advanced mode)
- [x] Tested clicking on system objects
- [x] Tested adding custom fields to system objects
- [x] No linter errors

## Screenshots
See attached screenshots in the conversation for the new filter UI.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a filter dropdown to the Settings Objects table (incl.
deactivated/system toggles), enables system objects across
settings/field flows, seeds core views (workspace members, messages,
threads, calendar events), and adds actions for Workspace Members.
> 
> - **Settings UI**
> - **Objects Table**: Replaces Active/Inactive sections with a single
filterable list and dropdown (`Deactivated`, `System objects` in
advanced mode); updates props to `objectMetadataItems` and removes
accordion sections.
> - **Search/UX**: Search input fills available space; inactive rows
show activation/delete menu; active rows remain navigable.
> - **Pages Updated**: `SettingsObjects`,
`SettingsApplicationDetailContentTab` switch to new table API; object
detail and new-field flows use `findObjectMetadataItemByNamePlural`
(works with system objects).
> - **Action Menu**
> - **Workspace Members**: Adds `WORKSPACE_MEMBERS_ACTIONS_CONFIG` with
"Manage members in settings" action; wired into `getActionConfig` for
`WorkspaceMember`.
> - **Server (Core Views Seed)**
> - Adds default views: `workspaceMembersAllView`, `messagesAllView`,
`messageThreadsAllView`, `calendarEventsAllView`; included in
`prefillCoreViews`.
> - Marks workflow entities as system (`WorkflowRun`,
`WorkflowVersion`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6a2856df85104665bd986cc63f2d54f19bf668d0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This commit is contained in:
Félix Malfait
2025-11-17 19:10:19 +01:00
committed by GitHub
parent 60ed9b53f4
commit 0fa2a4524a
16 changed files with 690 additions and 118 deletions
@@ -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: (
<ActionLink
to={AppPath.SettingsCatchAll}
params={{
'*': SettingsPath.WorkspaceMembersPage,
}}
/>
),
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,
},
},
},
);
@@ -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;
@@ -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();