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:
+124
@@ -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;
|
||||
|
||||
+2
-3
@@ -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();
|
||||
|
||||
|
||||
+1
-2
@@ -66,8 +66,7 @@ export const SettingsApplicationDetailContentTab = ({
|
||||
description={t`Objects created by application`}
|
||||
/>
|
||||
<SettingsObjectTable
|
||||
activeObjects={applicationObjectMetadataItems}
|
||||
inactiveObjects={[]}
|
||||
objectMetadataItems={applicationObjectMetadataItems}
|
||||
withSearchBar={false}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
@@ -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 });
|
||||
|
||||
|
||||
@@ -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 && (
|
||||
<StyledSearchInput
|
||||
instanceId="settings-objects-search"
|
||||
LeftIcon={IconSearch}
|
||||
placeholder={t`Search for an object...`}
|
||||
value={searchTerm}
|
||||
onChange={setSearchTerm}
|
||||
/>
|
||||
<StyledSearchAndFilterContainer>
|
||||
<StyledSearchInput
|
||||
instanceId="settings-objects-search"
|
||||
LeftIcon={IconSearch}
|
||||
placeholder={t`Search for an object...`}
|
||||
value={searchTerm}
|
||||
onChange={setSearchTerm}
|
||||
/>
|
||||
<Dropdown
|
||||
dropdownId="settings-objects-filter-dropdown"
|
||||
dropdownPlacement="bottom-end"
|
||||
dropdownOffset={{ x: 0, y: 8 }}
|
||||
clickableComponent={
|
||||
<Button
|
||||
Icon={IconFilter}
|
||||
size="medium"
|
||||
variant="secondary"
|
||||
accent="default"
|
||||
ariaLabel={t`Filter`}
|
||||
/>
|
||||
}
|
||||
dropdownComponents={
|
||||
<DropdownContent>
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItemToggle
|
||||
LeftIcon={IconArchive}
|
||||
onToggleChange={() => setShowDeactivated(!showDeactivated)}
|
||||
toggled={showDeactivated}
|
||||
text={t`Deactivated`}
|
||||
toggleSize="small"
|
||||
/>
|
||||
{isAdvancedModeEnabled && (
|
||||
<MenuItemToggle
|
||||
LeftIcon={IconSettings}
|
||||
onToggleChange={() =>
|
||||
setShowSystemObjects(!showSystemObjects)
|
||||
}
|
||||
toggled={showSystemObjects}
|
||||
text={t`System objects`}
|
||||
toggleSize="small"
|
||||
/>
|
||||
)}
|
||||
</DropdownMenuItemsContainer>
|
||||
</DropdownContent>
|
||||
}
|
||||
/>
|
||||
</StyledSearchAndFilterContainer>
|
||||
)}
|
||||
|
||||
<Table>
|
||||
@@ -165,35 +200,21 @@ export const SettingsObjectTable = ({
|
||||
)}
|
||||
<TableHeader></TableHeader>
|
||||
</StyledObjectTableRow>
|
||||
{isNonEmptyArray(sortedActiveObjectSettingsItems) && (
|
||||
<TableSection title={t`Active`}>
|
||||
{filteredActiveObjectSettingsItems.map((objectSettingsItem) => (
|
||||
<SettingsObjectMetadataItemTableRow
|
||||
key={objectSettingsItem.objectMetadataItem.namePlural}
|
||||
objectMetadataItem={objectSettingsItem.objectMetadataItem}
|
||||
totalObjectCount={objectSettingsItem.totalObjectCount}
|
||||
action={
|
||||
{filteredObjectSettingsItems.map((objectSettingsItem) => {
|
||||
const isActive = objectSettingsItem.objectMetadataItem.isActive;
|
||||
|
||||
return (
|
||||
<SettingsObjectMetadataItemTableRow
|
||||
key={objectSettingsItem.objectMetadataItem.namePlural}
|
||||
objectMetadataItem={objectSettingsItem.objectMetadataItem}
|
||||
totalObjectCount={objectSettingsItem.totalObjectCount}
|
||||
action={
|
||||
isActive ? (
|
||||
<StyledIconChevronRight
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
}
|
||||
link={getSettingsPath(SettingsPath.ObjectDetail, {
|
||||
objectNamePlural:
|
||||
objectSettingsItem.objectMetadataItem.namePlural,
|
||||
})}
|
||||
/>
|
||||
))}
|
||||
</TableSection>
|
||||
)}
|
||||
{isNonEmptyArray(sortedInactiveObjectSettingsItems) && (
|
||||
<TableSection title={t`Inactive`}>
|
||||
{filteredInactiveObjectSettingsItems.map((objectSettingsItem) => (
|
||||
<SettingsObjectMetadataItemTableRow
|
||||
key={objectSettingsItem.objectMetadataItem.namePlural}
|
||||
objectMetadataItem={objectSettingsItem.objectMetadataItem}
|
||||
totalObjectCount={objectSettingsItem.totalObjectCount}
|
||||
action={
|
||||
) : (
|
||||
<SettingsObjectInactiveMenuDropDown
|
||||
isCustomObject={
|
||||
objectSettingsItem.objectMetadataItem.isCustom
|
||||
@@ -213,11 +234,19 @@ export const SettingsObjectTable = ({
|
||||
)
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</TableSection>
|
||||
)}
|
||||
)
|
||||
}
|
||||
link={
|
||||
isActive
|
||||
? getSettingsPath(SettingsPath.ObjectDetail, {
|
||||
objectNamePlural:
|
||||
objectSettingsItem.objectMetadataItem.namePlural,
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Table>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -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 (
|
||||
<SubMenuTopBarContainer
|
||||
@@ -47,10 +44,7 @@ export const SettingsObjects = () => {
|
||||
<Section>
|
||||
<H2Title title={t`Existing objects`} />
|
||||
|
||||
<SettingsObjectTable
|
||||
activeObjects={activeNonSystemObjectMetadataItems}
|
||||
inactiveObjects={inactiveNonSystemObjectMetadataItems}
|
||||
/>
|
||||
<SettingsObjectTable objectMetadataItems={objectMetadataItems} />
|
||||
</Section>
|
||||
</>
|
||||
</SettingsPageContainer>
|
||||
|
||||
+2
-2
@@ -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<SettingsDataModelNewFieldFormValues>({
|
||||
|
||||
+2
-2
@@ -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: {
|
||||
|
||||
+8
@@ -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();
|
||||
|
||||
+122
@@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
+55
@@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
+104
@@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
+132
@@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
+2
-1
@@ -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 {
|
||||
|
||||
+1
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user