Add system view fallback (#18536)
## Context The goal is to add a "See records" button in all objects that would redirect to that view (this will be done in a later PR). See screenshot below. <img width="665" height="312" alt="Screenshot 2026-03-10 at 15 54 36" src="https://github.com/user-attachments/assets/6e23a75b-cff0-4d93-bce8-b5481b05c6f6" /> ## Implementation - If a view does not exist on an object, there is a **temporary** fallback where the frontend creates the missing view as a custom view when going over the object index page - System objects are now surfaced but we don't want their records to be editable, they will be readonly (mostly, all fields will be non-editable except for their custom fields). - We can't create a new record of a system object, some actions are also hidden. - The backend now rejects if you are trying to delete the last view of an object
This commit is contained in:
+15
-3
@@ -14,11 +14,13 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { coreViewsFromObjectMetadataItemFamilySelector } from '@/views/states/selectors/coreViewsFromObjectMetadataItemFamilySelector';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { ViewType, viewTypeIconMapping } from '@/views/types/ViewType';
|
||||
import { useDestroyViewFromCurrentState } from '@/views/view-picker/hooks/useDestroyViewFromCurrentState';
|
||||
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilySelectorValue';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
@@ -64,7 +66,13 @@ export const ObjectOptionsDropdownCustomView = ({
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const viewsOnCurrentObject = useAtomFamilySelectorValue(
|
||||
coreViewsFromObjectMetadataItemFamilySelector,
|
||||
{ objectMetadataItemId: objectMetadataItem.id },
|
||||
);
|
||||
|
||||
const isDefaultView = currentView?.key === ViewKey.Index;
|
||||
const isLastView = viewsOnCurrentObject.length <= 1;
|
||||
|
||||
const recordIndexCalendarLayout = useAtomStateValue(
|
||||
recordIndexCalendarLayoutState,
|
||||
@@ -272,14 +280,18 @@ export const ObjectOptionsDropdownCustomView = ({
|
||||
onClick={() => handleDelete()}
|
||||
LeftIcon={IconTrash}
|
||||
text={t`Delete view`}
|
||||
disabled={isDefaultView}
|
||||
disabled={isDefaultView || isLastView}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
</div>
|
||||
{isDefaultView && (
|
||||
{(isDefaultView || isLastView) && (
|
||||
<AppTooltip
|
||||
anchorSelect={`#delete-view-menu-item`}
|
||||
content={t`Not available on Default View`}
|
||||
content={
|
||||
isDefaultView
|
||||
? t`Not available on Default View`
|
||||
: t`Cannot delete the only view`
|
||||
}
|
||||
noArrow
|
||||
place="bottom"
|
||||
width="100%"
|
||||
|
||||
Reference in New Issue
Block a user