410 open in side panel (#10363)

Closes https://github.com/twentyhq/core-team-issues/issues/410

- Added `openRecordIn` column in the `view` entity, which is set to
`SIDE_PANEL` by default
- Created a new option inside the view option dropdown to be able to set
`openRecordIn`
- Updated all record show page openings to reflect the setting behavior
- For `workflow`, `workflowVersion` and `workflowRun` (what I call
workflow objects), we want the default view `openRecordIn` to be set to
`RECORD_PAGE`. When seeding the views for the new workspaces, we set
`openRecordIn` to `RECORD_PAGE` for workflow objects. Since the workflow
objects views `openRecordIn` will be set to the default value
`SIDE_PANEL` for the existing workspaces when the sync metadata runs, I
created a script to run in the 0.43 update to update this value.
- Updated `closeCommandMenu` because of problems introduced by the
animate presence wrapper around the command menu. We now reset the
states at the end of the animation.

Note: We want to be able to open all workflow objects pages in the side
panel, but this requires some refactoring of the workflow module. For
now @Bonapara wanted to allow the possibility to change the
`openRecordIn` setting to `SIDE_PANEL` even for the workflows even if
it's buggy and not ready for the moment. Since this is an experimental
feature, it shouldn't cause too many problems.
This commit is contained in:
Raphaël Bosi
2025-02-21 10:27:33 +01:00
committed by GitHub
parent e301c7856b
commit 9f454c565b
102 changed files with 921 additions and 218 deletions

View File

@ -48,7 +48,11 @@ export const CommandMenuContainer = ({
}: { }: {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
const { toggleCommandMenu, closeCommandMenu } = useCommandMenu(); const {
toggleCommandMenu,
closeCommandMenu,
onCommandMenuCloseAnimationComplete,
} = useCommandMenu();
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
@ -98,7 +102,7 @@ export const CommandMenuContainer = ({
> >
<ActionMenuContext.Provider <ActionMenuContext.Provider
value={{ value={{
isInRightDrawer: false, isInRightDrawer: true,
onActionExecutedCallback: ({ key }) => { onActionExecutedCallback: ({ key }) => {
if ( if (
key !== RecordAgnosticActionsKey.SEARCH_RECORDS && key !== RecordAgnosticActionsKey.SEARCH_RECORDS &&
@ -121,7 +125,10 @@ export const CommandMenuContainer = ({
<RunWorkflowRecordAgnosticActionMenuEntriesSetter /> <RunWorkflowRecordAgnosticActionMenuEntriesSetter />
)} )}
<ActionMenuConfirmationModals /> <ActionMenuConfirmationModals />
<AnimatePresence mode="wait"> <AnimatePresence
mode="wait"
onExitComplete={onCommandMenuCloseAnimationComplete}
>
{isCommandMenuOpened && ( {isCommandMenuOpened && (
<StyledCommandMenu <StyledCommandMenu
data-testid="command-menu" data-testid="command-menu"

View File

@ -34,16 +34,17 @@ export const CommandMenuContextChipGroupsWithRecordSelection = ({
/> />
)); ));
const recordSelectionContextChip = totalCount const recordSelectionContextChip =
? { totalCount && records.length > 0
text: getSelectedRecordsContextText( ? {
objectMetadataItem, text: getSelectedRecordsContextText(
records, objectMetadataItem,
totalCount, records,
), totalCount,
Icons: Avatars, ),
} Icons: Avatars,
: undefined; }
: undefined;
const contextChipsWithRecordSelection = [ const contextChipsWithRecordSelection = [
recordSelectionContextChip, recordSelectionContextChip,

View File

@ -21,7 +21,7 @@ export const CommandMenuContextRecordChip = ({
instanceId, instanceId,
}); });
if (loading || !totalCount) { if (loading || !totalCount || records.length === 0) {
return null; return null;
} }

View File

@ -192,6 +192,7 @@ describe('useCommandMenu', () => {
act(() => { act(() => {
result.current.commandMenu.goBackFromCommandMenu(); result.current.commandMenu.goBackFromCommandMenu();
result.current.commandMenu.onCommandMenuCloseAnimationComplete();
}); });
expect(result.current.commandMenuNavigationStack).toEqual([]); expect(result.current.commandMenuNavigationStack).toEqual([]);

View File

@ -74,31 +74,33 @@ export const useCommandMenu = () => {
); );
const closeCommandMenu = useRecoilCallback( const closeCommandMenu = useRecoilCallback(
({ snapshot, set }) => ({ set }) =>
() => { () => {
const isCommandMenuOpened = snapshot set(isCommandMenuOpenedState, false);
.getLoadable(isCommandMenuOpenedState) },
.getValue(); [],
);
if (isCommandMenuOpened) { const onCommandMenuCloseAnimationComplete = useRecoilCallback(
resetContextStoreStates('command-menu'); ({ set }) =>
resetContextStoreStates('command-menu-previous'); () => {
resetContextStoreStates('command-menu');
resetContextStoreStates('command-menu-previous');
set(viewableRecordIdState, null); set(viewableRecordIdState, null);
set(commandMenuPageState, CommandMenuPages.Root); set(commandMenuPageState, CommandMenuPages.Root);
set(commandMenuPageInfoState, { set(commandMenuPageInfoState, {
title: undefined, title: undefined,
Icon: undefined, Icon: undefined,
}); });
set(isCommandMenuOpenedState, false); set(isCommandMenuOpenedState, false);
set(commandMenuSearchState, ''); set(commandMenuSearchState, '');
set(commandMenuNavigationStackState, []); set(commandMenuNavigationStackState, []);
resetSelectedItem(); resetSelectedItem();
set(hasUserSelectedCommandState, false); set(hasUserSelectedCommandState, false);
goBackToPreviousHotkeyScope(); goBackToPreviousHotkeyScope();
emitRightDrawerCloseEvent(); emitRightDrawerCloseEvent();
}
}, },
[goBackToPreviousHotkeyScope, resetContextStoreStates, resetSelectedItem], [goBackToPreviousHotkeyScope, resetContextStoreStates, resetSelectedItem],
); );
@ -109,7 +111,10 @@ export const useCommandMenu = () => {
page, page,
pageTitle, pageTitle,
pageIcon, pageIcon,
}: CommandMenuNavigationStackItem) => { resetNavigationStack = false,
}: CommandMenuNavigationStackItem & {
resetNavigationStack?: boolean;
}) => {
set(commandMenuPageState, page); set(commandMenuPageState, page);
set(commandMenuPageInfoState, { set(commandMenuPageInfoState, {
title: pageTitle, title: pageTitle,
@ -120,10 +125,14 @@ export const useCommandMenu = () => {
.getLoadable(commandMenuNavigationStackState) .getLoadable(commandMenuNavigationStackState)
.getValue(); .getValue();
set(commandMenuNavigationStackState, [ if (resetNavigationStack) {
...currentNavigationStack, set(commandMenuNavigationStackState, [{ page, pageTitle, pageIcon }]);
{ page, pageTitle, pageIcon }, } else {
]); set(commandMenuNavigationStackState, [
...currentNavigationStack,
{ page, pageTitle, pageIcon },
]);
}
openCommandMenu(); openCommandMenu();
}; };
}, },
@ -248,6 +257,7 @@ export const useCommandMenu = () => {
? t`New ${capitalizedObjectNameSingular}` ? t`New ${capitalizedObjectNameSingular}`
: capitalizedObjectNameSingular, : capitalizedObjectNameSingular,
pageIcon: Icon, pageIcon: Icon,
resetNavigationStack: true,
}); });
}; };
}, },
@ -315,6 +325,7 @@ export const useCommandMenu = () => {
return { return {
openRootCommandMenu, openRootCommandMenu,
closeCommandMenu, closeCommandMenu,
onCommandMenuCloseAnimationComplete,
navigateCommandMenu, navigateCommandMenu,
navigateCommandMenuHistory, navigateCommandMenuHistory,
goBackFromCommandMenu, goBackFromCommandMenu,

View File

@ -7,6 +7,7 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations'; import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState'; import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { AppPath } from '@/types/AppPath'; import { AppPath } from '@/types/AppPath';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { getCompanyObjectMetadataItem } from '~/testing/mock-data/companies'; import { getCompanyObjectMetadataItem } from '~/testing/mock-data/companies';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems'; import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
@ -38,6 +39,7 @@ const renderHooks = ({
type: ViewType.Table, type: ViewType.Table,
key: null, key: null,
isCompact: false, isCompact: false,
openRecordIn: ViewOpenRecordInType.SIDE_PANEL,
viewFields: [], viewFields: [],
viewGroups: [], viewGroups: [],
viewSorts: [], viewSorts: [],

View File

@ -1,9 +1,13 @@
import { AvatarChip, AvatarChipVariant } from 'twenty-ui'; import { AvatarChip, AvatarChipVariant } from 'twenty-ui';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { getLinkToShowPage } from '@/object-metadata/utils/getLinkToShowPage'; import { getLinkToShowPage } from '@/object-metadata/utils/getLinkToShowPage';
import { useRecordChipData } from '@/object-record/hooks/useRecordChipData'; import { useRecordChipData } from '@/object-record/hooks/useRecordChipData';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { MouseEvent } from 'react'; import { MouseEvent } from 'react';
import { useRecoilValue } from 'recoil';
export type RecordChipProps = { export type RecordChipProps = {
objectNameSingular: string; objectNameSingular: string;
@ -23,8 +27,18 @@ export const RecordChip = ({
record, record,
}); });
const { openRecordInCommandMenu } = useCommandMenu();
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
const handleClick = (e: MouseEvent<Element>) => { const handleClick = (e: MouseEvent<Element>) => {
e.stopPropagation(); e.stopPropagation();
if (recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL) {
openRecordInCommandMenu({
recordId: record.id,
objectNameSingular,
});
}
}; };
return ( return (
@ -36,7 +50,11 @@ export const RecordChip = ({
className={className} className={className}
variant={variant} variant={variant}
onClick={handleClick} onClick={handleClick}
to={getLinkToShowPage(objectNameSingular, record)} to={
recordIndexOpenRecordIn === ViewOpenRecordInType.RECORD_PAGE
? getLinkToShowPage(objectNameSingular, record)
: undefined
}
/> />
); );
}; };

View File

@ -6,6 +6,7 @@ import { ObjectOptionsDropdownRecordGroupFieldsContent } from '@/object-record/o
import { ObjectOptionsDropdownRecordGroupsContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupsContent'; import { ObjectOptionsDropdownRecordGroupsContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupsContent';
import { ObjectOptionsDropdownRecordGroupSortContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupSortContent'; import { ObjectOptionsDropdownRecordGroupSortContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupSortContent';
import { ObjectOptionsDropdownViewSettingsContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownViewSettingsContent'; import { ObjectOptionsDropdownViewSettingsContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownViewSettingsContent';
import { ObjectOptionsDropdownViewSettingsOpenInContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownViewSettingsOpenInContent';
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown'; import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
export const ObjectOptionsDropdownContent = () => { export const ObjectOptionsDropdownContent = () => {
@ -14,6 +15,8 @@ export const ObjectOptionsDropdownContent = () => {
switch (currentContentId) { switch (currentContentId) {
case 'viewSettings': case 'viewSettings':
return <ObjectOptionsDropdownViewSettingsContent />; return <ObjectOptionsDropdownViewSettingsContent />;
case 'viewSettingsOpenIn':
return <ObjectOptionsDropdownViewSettingsOpenInContent />;
case 'fields': case 'fields':
return <ObjectOptionsDropdownFieldsContent />; return <ObjectOptionsDropdownFieldsContent />;
case 'hiddenFields': case 'hiddenFields':

View File

@ -31,7 +31,6 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewType } from '@/views/types/ViewType';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
export const ObjectOptionsDropdownMenuContent = () => { export const ObjectOptionsDropdownMenuContent = () => {
@ -104,20 +103,17 @@ export const ObjectOptionsDropdownMenuContent = () => {
<DropdownMenuHeader StartIcon={CurrentViewIcon ?? IconList}> <DropdownMenuHeader StartIcon={CurrentViewIcon ?? IconList}>
{currentView?.name} {currentView?.name}
</DropdownMenuHeader> </DropdownMenuHeader>
{/** TODO: Should be removed when view settings contains more options */}
{viewType === ViewType.Kanban && ( <DropdownMenuItemsContainer scrollable={false}>
<> <MenuItem
<DropdownMenuItemsContainer scrollable={false}> onClick={() => onContentChange('viewSettings')}
<MenuItem LeftIcon={IconLayout}
onClick={() => onContentChange('viewSettings')} text="View settings"
LeftIcon={IconLayout} hasSubMenu
text="View settings" />
hasSubMenu </DropdownMenuItemsContainer>
/> <DropdownMenuSeparator />
</DropdownMenuItemsContainer>
<DropdownMenuSeparator />
</>
)}
<DropdownMenuItemsContainer scrollable={false}> <DropdownMenuItemsContainer scrollable={false}>
<MenuItem <MenuItem
onClick={() => onContentChange('fields')} onClick={() => onContentChange('fields')}

View File

@ -1,21 +1,32 @@
import { import {
IconBaselineDensitySmall, IconBaselineDensitySmall,
IconChevronLeft, IconChevronLeft,
IconLayoutNavbar,
IconLayoutSidebarRight,
MenuItem,
MenuItemToggle, MenuItemToggle,
} from 'twenty-ui'; } from 'twenty-ui';
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard'; import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown'; import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader'; import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { useRecoilValue } from 'recoil';
export const ObjectOptionsDropdownViewSettingsContent = () => { export const ObjectOptionsDropdownViewSettingsContent = () => {
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
const { recordIndexId, objectMetadataItem, viewType, resetContent } = const {
useOptionsDropdown(); recordIndexId,
objectMetadataItem,
viewType,
resetContent,
onContentChange,
} = useOptionsDropdown();
const { isCompactModeActive, setAndPersistIsCompactModeActive } = const { isCompactModeActive, setAndPersistIsCompactModeActive } =
useObjectOptionsForBoard({ useObjectOptionsForBoard({
@ -24,12 +35,29 @@ export const ObjectOptionsDropdownViewSettingsContent = () => {
viewBarId: recordIndexId, viewBarId: recordIndexId,
}); });
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
return ( return (
<> <>
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={resetContent}> <DropdownMenuHeader StartIcon={IconChevronLeft} onClick={resetContent}>
View settings View settings
</DropdownMenuHeader> </DropdownMenuHeader>
<DropdownMenuItemsContainer> <DropdownMenuItemsContainer>
<MenuItem
onClick={() => onContentChange('viewSettingsOpenIn')}
LeftIcon={
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
? IconLayoutSidebarRight
: IconLayoutNavbar
}
text="Open in"
contextualText={
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
? 'Side Panel'
: 'Record Page'
}
hasSubMenu
/>
{viewType === ViewType.Kanban && ( {viewType === ViewType.Kanban && (
<MenuItemToggle <MenuItemToggle
LeftIcon={IconBaselineDensitySmall} LeftIcon={IconBaselineDensitySmall}

View File

@ -0,0 +1,60 @@
import {
IconChevronLeft,
IconLayoutNavbar,
IconLayoutSidebarRight,
MenuItemSelect,
} from 'twenty-ui';
import { useObjectOptions } from '@/object-record/object-options-dropdown/hooks/useObjectOptions';
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { t } from '@lingui/core/macro';
import { useRecoilValue } from 'recoil';
export const ObjectOptionsDropdownViewSettingsOpenInContent = () => {
const { onContentChange } = useOptionsDropdown();
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
const { setAndPersistOpenRecordIn } = useObjectOptions();
return (
<>
<DropdownMenuHeader
StartIcon={IconChevronLeft}
onClick={() => onContentChange('viewSettings')}
>
{t`Open in`}
</DropdownMenuHeader>
<DropdownMenuItemsContainer>
<MenuItemSelect
LeftIcon={IconLayoutSidebarRight}
text="Side Panel"
selected={recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL}
onClick={() =>
setAndPersistOpenRecordIn(
ViewOpenRecordInType.SIDE_PANEL,
currentViewWithCombinedFiltersAndSorts,
)
}
/>
<MenuItemSelect
LeftIcon={IconLayoutNavbar}
text="Record Page"
selected={
recordIndexOpenRecordIn === ViewOpenRecordInType.RECORD_PAGE
}
onClick={() =>
setAndPersistOpenRecordIn(
ViewOpenRecordInType.RECORD_PAGE,
currentViewWithCombinedFiltersAndSorts,
)
}
/>
</DropdownMenuItemsContainer>
</>
);
};

View File

@ -0,0 +1,29 @@
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
import { GraphQLView } from '@/views/types/GraphQLView';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { useCallback } from 'react';
import { useSetRecoilState } from 'recoil';
export const useObjectOptions = () => {
const setRecordIndexOpenRecordIn = useSetRecoilState(
recordIndexOpenRecordInState,
);
const { updateCurrentView } = useUpdateCurrentView();
const setAndPersistOpenRecordIn = useCallback(
(openRecordIn: ViewOpenRecordInType, view: GraphQLView | undefined) => {
if (!view) return;
setRecordIndexOpenRecordIn(openRecordIn);
updateCurrentView({
openRecordIn,
});
},
[setRecordIndexOpenRecordIn, updateCurrentView],
);
return {
setAndPersistOpenRecordIn,
};
};

View File

@ -1,5 +1,6 @@
export type ObjectOptionsContentId = export type ObjectOptionsContentId =
| 'viewSettings' | 'viewSettings'
| 'viewSettingsOpenIn'
| 'fields' | 'fields'
| 'hiddenFields' | 'hiddenFields'
| 'recordGroups' | 'recordGroups'

View File

@ -1,42 +1,45 @@
import { import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
AvatarChipVariant, import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
Checkbox, import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useRecordBoardSelection';
CheckboxVariant,
LightIconButton,
IconEye,
IconEyeOff,
} from 'twenty-ui';
import { RecordBoardCardHeaderContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeaderContainer'; import { RecordBoardCardHeaderContainer } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeaderContainer';
import { RecordInlineCellEditMode } from '@/object-record/record-inline-cell/components/RecordInlineCellEditMode'; import { StopPropagationContainer } from '@/object-record/record-board/record-board-card/components/StopPropagationContainer';
import styled from '@emotion/styled'; import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { TextInput } from '@/ui/input/components/TextInput';
import { Dispatch, SetStateAction, useContext, useState } from 'react';
import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard'; import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard';
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
import { RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition'; import { RecordBoardFieldDefinition } from '@/object-record/record-board/types/RecordBoardFieldDefinition';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { import {
FieldContext, FieldContext,
RecordUpdateHook, RecordUpdateHook,
RecordUpdateHookParams, RecordUpdateHookParams,
} from '@/object-record/record-field/contexts/FieldContext'; } from '@/object-record/record-field/contexts/FieldContext';
import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { getFieldButtonIcon } from '@/object-record/record-field/utils/getFieldButtonIcon'; import { getFieldButtonIcon } from '@/object-record/record-field/utils/getFieldButtonIcon';
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell';
import { useRecoilValue } from 'recoil';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip'; import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip';
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useRecordBoardSelection';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell';
import { RecordInlineCellEditMode } from '@/object-record/record-inline-cell/components/RecordInlineCellEditMode';
import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { TextInput } from '@/ui/input/components/TextInput';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState'; import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { StopPropagationContainer } from '@/object-record/record-board/record-board-card/components/StopPropagationContainer'; import styled from '@emotion/styled';
import { Dispatch, SetStateAction, useContext, useState } from 'react';
import { useRecoilValue } from 'recoil';
import {
AvatarChipVariant,
Checkbox,
CheckboxVariant,
IconEye,
IconEyeOff,
LightIconButton,
} from 'twenty-ui';
const StyledTextInput = styled(TextInput)` const StyledTextInput = styled(TextInput)`
border-radius: ${({ theme }) => theme.border.radius.sm}; border-radius: ${({ theme }) => theme.border.radius.sm};
@ -116,6 +119,10 @@ export const RecordBoardCardHeader = ({
return [updateEntity, { loading: false }]; return [updateEntity, { loading: false }];
}; };
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
const { openRecordInCommandMenu } = useCommandMenu();
return ( return (
<RecordBoardCardHeaderContainer showCompactView={showCompactView}> <RecordBoardCardHeaderContainer showCompactView={showCompactView}>
<StopPropagationContainer> <StopPropagationContainer>
@ -178,7 +185,21 @@ export const RecordBoardCardHeader = ({
record={record as ObjectRecord} record={record as ObjectRecord}
variant={AvatarChipVariant.Transparent} variant={AvatarChipVariant.Transparent}
maxWidth={150} maxWidth={150}
to={indexIdentifierUrl(recordId)} onClick={
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
? () => {
openRecordInCommandMenu({
recordId,
objectNameSingular: objectMetadataItem.nameSingular,
});
}
: undefined
}
to={
recordIndexOpenRecordIn === ViewOpenRecordInType.RECORD_PAGE
? indexIdentifierUrl(recordId)
: undefined
}
/> />
)} )}
</StopPropagationContainer> </StopPropagationContainer>

View File

@ -1,6 +1,10 @@
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { RecordChip } from '@/object-record/components/RecordChip'; import { RecordChip } from '@/object-record/components/RecordChip';
import { useChipFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useChipFieldDisplay'; import { useChipFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useChipFieldDisplay';
import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip'; import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { useRecoilValue } from 'recoil';
import { ChipSize } from 'twenty-ui'; import { ChipSize } from 'twenty-ui';
export const ChipFieldDisplay = () => { export const ChipFieldDisplay = () => {
@ -11,6 +15,10 @@ export const ChipFieldDisplay = () => {
labelIdentifierLink, labelIdentifierLink,
} = useChipFieldDisplay(); } = useChipFieldDisplay();
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
const { openRecordInCommandMenu } = useCommandMenu();
if (!recordValue) { if (!recordValue) {
return null; return null;
} }
@ -20,7 +28,21 @@ export const ChipFieldDisplay = () => {
objectNameSingular={objectNameSingular} objectNameSingular={objectNameSingular}
record={recordValue} record={recordValue}
size={ChipSize.Small} size={ChipSize.Small}
to={labelIdentifierLink} to={
recordIndexOpenRecordIn === ViewOpenRecordInType.RECORD_PAGE
? labelIdentifierLink
: undefined
}
onClick={
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
? () => {
openRecordInCommandMenu({
recordId: recordValue.id,
objectNameSingular,
});
}
: undefined
}
/> />
) : ( ) : (
<RecordChip objectNameSingular={objectNameSingular} record={recordValue} /> <RecordChip objectNameSingular={objectNameSingular} record={recordValue} />

View File

@ -11,6 +11,7 @@ export type RecordIdentifierChipProps = {
size?: ChipSize; size?: ChipSize;
to?: string; to?: string;
maxWidth?: number; maxWidth?: number;
onClick?: () => void;
}; };
export const RecordIdentifierChip = ({ export const RecordIdentifierChip = ({
@ -18,6 +19,7 @@ export const RecordIdentifierChip = ({
record, record,
variant, variant,
size, size,
onClick,
to, to,
maxWidth, maxWidth,
}: RecordIdentifierChipProps) => { }: RecordIdentifierChipProps) => {
@ -40,6 +42,7 @@ export const RecordIdentifierChip = ({
avatarType={recordChipData.avatarType} avatarType={recordChipData.avatarType}
avatarUrl={recordChipData.avatarUrl ?? ''} avatarUrl={recordChipData.avatarUrl ?? ''}
to={to} to={to}
onClick={onClick}
variant={variant} variant={variant}
LeftIcon={LeftIcon} LeftIcon={LeftIcon}
LeftIconColor={LeftIconColor} LeftIconColor={LeftIconColor}

View File

@ -10,6 +10,7 @@ import { recordIndexFiltersState } from '@/object-record/record-index/states/rec
import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState'; import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState';
import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState'; import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState';
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState'; import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState'; import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState';
@ -48,6 +49,9 @@ export const useLoadRecordIndexStates = () => {
recordIndexIsCompactModeActiveState, recordIndexIsCompactModeActiveState,
); );
const setRecordIndexViewType = useSetRecoilState(recordIndexViewTypeState); const setRecordIndexViewType = useSetRecoilState(recordIndexViewTypeState);
const setRecordIndexOpenRecordIn = useSetRecoilState(
recordIndexOpenRecordInState,
);
const setRecordIndexViewKanbanFieldMetadataIdState = useSetRecoilState( const setRecordIndexViewKanbanFieldMetadataIdState = useSetRecoilState(
recordIndexKanbanFieldMetadataIdState, recordIndexKanbanFieldMetadataIdState,
); );
@ -242,6 +246,7 @@ export const useLoadRecordIndexStates = () => {
mapViewSortsToSorts(view.viewSorts, sortDefinitions), mapViewSortsToSorts(view.viewSorts, sortDefinitions),
); );
setRecordIndexViewType(view.type); setRecordIndexViewType(view.type);
setRecordIndexOpenRecordIn(view.openRecordIn);
setRecordIndexViewKanbanFieldMetadataIdState( setRecordIndexViewKanbanFieldMetadataIdState(
view.kanbanFieldMetadataId, view.kanbanFieldMetadataId,
); );
@ -272,6 +277,7 @@ export const useLoadRecordIndexStates = () => {
setRecordIndexViewKanbanAggregateOperationState, setRecordIndexViewKanbanAggregateOperationState,
setRecordIndexViewKanbanFieldMetadataIdState, setRecordIndexViewKanbanFieldMetadataIdState,
setRecordIndexViewType, setRecordIndexViewType,
setRecordIndexOpenRecordIn,
], ],
); );

View File

@ -0,0 +1,8 @@
import { createState } from '@ui/utilities/state/utils/createState';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
export const recordIndexOpenRecordInState = createState<ViewOpenRecordInType>({
key: 'recordIndexOpenRecordInState',
defaultValue: ViewOpenRecordInType.SIDE_PANEL,
});

View File

@ -1,18 +1,19 @@
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2'; import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2';
import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode'; import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode';
import { recordTablePendingRecordIdByGroupComponentFamilyState } from '@/object-record/record-table/states/recordTablePendingRecordIdByGroupComponentFamilyState'; import { recordTablePendingRecordIdByGroupComponentFamilyState } from '@/object-record/record-table/states/recordTablePendingRecordIdByGroupComponentFamilyState';
import { recordTablePendingRecordIdComponentState } from '@/object-record/record-table/states/recordTablePendingRecordIdComponentState'; import { recordTablePendingRecordIdComponentState } from '@/object-record/record-table/states/recordTablePendingRecordIdComponentState';
import { useRecordTitleCell } from '@/object-record/record-title-cell/hooks/useRecordTitleCell'; import { useRecordTitleCell } from '@/object-record/record-title-cell/hooks/useRecordTitleCell';
import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField'; import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField';
import { shouldRedirectToShowPageOnCreation } from '@/object-record/utils/shouldRedirectToShowPageOnCreation';
import { AppPath } from '@/types/AppPath'; import { AppPath } from '@/types/AppPath';
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious'; import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -62,62 +63,71 @@ export const useCreateNewTableRecord = ({
const { openRecordTitleCell } = useRecordTitleCell(); const { openRecordTitleCell } = useRecordTitleCell();
const createNewTableRecord = async () => { const createNewTableRecord = useRecoilCallback(
const recordId = v4(); ({ snapshot }) =>
async () => {
const recordId = v4();
if (isCommandMenuV2Enabled) { if (isCommandMenuV2Enabled) {
// TODO: Generalize this behaviour, there will be a view setting to specify const recordIndexOpenRecordIn = snapshot
// if the new record should be displayed in the side panel or on the record page .getLoadable(recordIndexOpenRecordInState)
if (shouldRedirectToShowPageOnCreation(objectMetadataItem.nameSingular)) { .getValue();
await createOneRecord({
id: recordId,
name: 'Untitled',
});
navigate(AppPath.RecordShowPage, { await createOneRecord({ id: recordId });
objectNameSingular: objectMetadataItem.nameSingular,
objectRecordId: recordId,
});
// TODO: we should open the record title cell here but because if (recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL) {
// we are redirecting to the record show page, the hotkey scope will openRecordInCommandMenu({
// be overridden by the hotkey scope on mount. We need to deprecate recordId,
// the useHotkeyScopeOnMount hook. objectNameSingular: objectMetadataItem.nameSingular,
isNewRecord: true,
});
return; openRecordTitleCell({
} recordId,
fieldMetadataId:
objectMetadataItem.labelIdentifierFieldMetadataId,
});
} else {
navigate(AppPath.RecordShowPage, {
objectNameSingular: objectMetadataItem.nameSingular,
objectRecordId: recordId,
});
}
await createOneRecord({ id: recordId }); return;
}
openRecordInCommandMenu({ setPendingRecordId(recordId);
recordId, setSelectedTableCellEditMode(-1, 0);
objectNameSingular: objectMetadataItem.nameSingular, setHotkeyScope(
isNewRecord: true, DEFAULT_CELL_SCOPE.scope,
}); DEFAULT_CELL_SCOPE.customScopes,
);
openRecordTitleCell({
recordId,
fieldMetadataId: objectMetadataItem.labelIdentifierFieldMetadataId,
});
return;
}
setPendingRecordId(recordId);
setSelectedTableCellEditMode(-1, 0);
setHotkeyScope(DEFAULT_CELL_SCOPE.scope, DEFAULT_CELL_SCOPE.customScopes);
if (isDefined(objectMetadataItem.labelIdentifierFieldMetadataId)) {
setActiveDropdownFocusIdAndMemorizePrevious(
getDropdownFocusIdForRecordField(
recordId,
objectMetadataItem.labelIdentifierFieldMetadataId,
'table-cell',
),
);
}
};
if (isDefined(objectMetadataItem.labelIdentifierFieldMetadataId)) {
setActiveDropdownFocusIdAndMemorizePrevious(
getDropdownFocusIdForRecordField(
recordId,
objectMetadataItem.labelIdentifierFieldMetadataId,
'table-cell',
),
);
}
},
[
createOneRecord,
isCommandMenuV2Enabled,
navigate,
objectMetadataItem.labelIdentifierFieldMetadataId,
objectMetadataItem.nameSingular,
openRecordInCommandMenu,
openRecordTitleCell,
setActiveDropdownFocusIdAndMemorizePrevious,
setHotkeyScope,
setPendingRecordId,
setSelectedTableCellEditMode,
],
);
const createNewTableRecordInGroup = useRecoilCallback( const createNewTableRecordInGroup = useRecoilCallback(
({ set }) => ({ set }) =>
(recordGroupId: string) => { (recordGroupId: string) => {

View File

@ -20,11 +20,14 @@ import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useC
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/RecordTableClickOutsideListenerId'; import { RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/RecordTableClickOutsideListenerId';
import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField'; import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField';
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious'; import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
import { useClickOustideListenerStates } from '@/ui/utilities/pointer-event/hooks/useClickOustideListenerStates'; import { useClickOustideListenerStates } from '@/ui/utilities/pointer-event/hooks/useClickOustideListenerStates';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { IconList } from 'twenty-ui'; import { IconList } from 'twenty-ui';
import { TableHotkeyScope } from '../../types/TableHotkeyScope'; import { TableHotkeyScope } from '../../types/TableHotkeyScope';
@ -75,6 +78,8 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => {
const { setActiveDropdownFocusIdAndMemorizePrevious } = const { setActiveDropdownFocusIdAndMemorizePrevious } =
useSetActiveDropdownFocusIdAndMemorizePrevious(); useSetActiveDropdownFocusIdAndMemorizePrevious();
const { openRecordInCommandMenu } = useCommandMenu();
const openTableCell = useRecoilCallback( const openTableCell = useRecoilCallback(
({ snapshot, set }) => ({ snapshot, set }) =>
({ ({
@ -115,7 +120,20 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => {
) { ) {
leaveTableFocus(); leaveTableFocus();
navigate(indexIdentifierUrl(recordId)); const openRecordIn = snapshot
.getLoadable(recordIndexOpenRecordInState)
.getValue();
if (openRecordIn === ViewOpenRecordInType.RECORD_PAGE) {
navigate(indexIdentifierUrl(recordId));
}
if (openRecordIn === ViewOpenRecordInType.SIDE_PANEL) {
openRecordInCommandMenu({
recordId,
objectNameSingular,
});
}
return; return;
} }
@ -170,14 +188,15 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => {
moveEditModeToTableCellPosition, moveEditModeToTableCellPosition,
initDraftValue, initDraftValue,
toggleClickOutsideListener, toggleClickOutsideListener,
setActiveDropdownFocusIdAndMemorizePrevious,
leaveTableFocus, leaveTableFocus,
navigate, navigate,
indexIdentifierUrl, indexIdentifierUrl,
openRecordInCommandMenu,
setViewableRecordId, setViewableRecordId,
setViewableRecordNameSingular, setViewableRecordNameSingular,
openRightDrawer, openRightDrawer,
setHotkeyScope, setHotkeyScope,
setActiveDropdownFocusIdAndMemorizePrevious,
], ],
); );

View File

@ -1,11 +0,0 @@
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
export const shouldRedirectToShowPageOnCreation = (
objectNameSingular: string,
) => {
if (objectNameSingular === CoreObjectNameSingular.Workflow) {
return true;
}
return false;
};

View File

@ -10,6 +10,7 @@ export const findAllViewsOperationSignatureFactory: RecordGqlOperationSignatureF
createdAt: true, createdAt: true,
updatedAt: true, updatedAt: true,
isCompact: true, isCompact: true,
openRecordIn: true,
objectMetadataId: true, objectMetadataId: true,
position: true, position: true,
type: true, type: true,

View File

@ -10,6 +10,7 @@ import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/
import { View } from '@/views/types/View'; import { View } from '@/views/types/View';
import { ViewFilter } from '@/views/types/ViewFilter'; import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { act } from 'react'; import { act } from 'react';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -51,6 +52,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
type: ViewType.Table, type: ViewType.Table,
key: null, key: null,
isCompact: false, isCompact: false,
openRecordIn: ViewOpenRecordInType.SIDE_PANEL,
viewFields: [], viewFields: [],
viewGroups: [], viewGroups: [],
viewSorts: [], viewSorts: [],

View File

@ -4,6 +4,7 @@ import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewFilterGroup } from '@/views/types/ViewFilterGroup'; import { ViewFilterGroup } from '@/views/types/ViewFilterGroup';
import { ViewGroup } from '@/views/types/ViewGroup'; import { ViewGroup } from '@/views/types/ViewGroup';
import { ViewKey } from '@/views/types/ViewKey'; import { ViewKey } from '@/views/types/ViewKey';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewSort } from '@/views/types/ViewSort'; import { ViewSort } from '@/views/types/ViewSort';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
@ -20,6 +21,7 @@ export type GraphQLView = {
kanbanAggregateOperationFieldMetadataId?: string | null; kanbanAggregateOperationFieldMetadataId?: string | null;
objectMetadataId: string; objectMetadataId: string;
isCompact: boolean; isCompact: boolean;
openRecordIn: ViewOpenRecordInType;
viewFields: ViewField[]; viewFields: ViewField[];
viewFilters: ViewFilter[]; viewFilters: ViewFilter[];
viewFilterGroups?: ViewFilterGroup[]; viewFilterGroups?: ViewFilterGroup[];

View File

@ -4,6 +4,7 @@ import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewFilterGroup } from '@/views/types/ViewFilterGroup'; import { ViewFilterGroup } from '@/views/types/ViewFilterGroup';
import { ViewGroup } from '@/views/types/ViewGroup'; import { ViewGroup } from '@/views/types/ViewGroup';
import { ViewKey } from '@/views/types/ViewKey'; import { ViewKey } from '@/views/types/ViewKey';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewSort } from '@/views/types/ViewSort'; import { ViewSort } from '@/views/types/ViewSort';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
@ -27,5 +28,6 @@ export type View = {
kanbanAggregateOperationFieldMetadataId: string | null; kanbanAggregateOperationFieldMetadataId: string | null;
position: number; position: number;
icon: string; icon: string;
openRecordIn: ViewOpenRecordInType;
__typename: 'View'; __typename: 'View';
}; };

View File

@ -0,0 +1,4 @@
export enum ViewOpenRecordInType {
SIDE_PANEL = 'SIDE_PANEL',
RECORD_PAGE = 'RECORD_PAGE',
}

View File

@ -1,3 +1,4 @@
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState'; import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
@ -16,7 +17,7 @@ import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWor
import { isCreateStepNode } from '@/workflow/workflow-diagram/utils/isCreateStepNode'; import { isCreateStepNode } from '@/workflow/workflow-diagram/utils/isCreateStepNode';
import { useLingui } from '@lingui/react/macro'; import { useLingui } from '@lingui/react/macro';
import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react'; import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react';
import { useCallback } from 'react'; import { useCallback, useContext } from 'react';
import { useSetRecoilState } from 'recoil'; import { useSetRecoilState } from 'recoil';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
import { IconBolt, useIcons } from 'twenty-ui'; import { IconBolt, useIcons } from 'twenty-ui';
@ -37,12 +38,16 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
commandMenuNavigationStackState, commandMenuNavigationStackState,
); );
const { isInRightDrawer } = useContext(ActionMenuContext);
const handleSelectionChange = useCallback( const handleSelectionChange = useCallback(
({ nodes }: OnSelectionChangeParams) => { ({ nodes }: OnSelectionChangeParams) => {
const selectedNode = nodes[0] as WorkflowDiagramNode; const selectedNode = nodes[0] as WorkflowDiagramNode;
const isClosingStep = isDefined(selectedNode) === false; const isClosingStep = isDefined(selectedNode) === false;
setCommandMenuNavigationStack([]); if (!isInRightDrawer) {
setCommandMenuNavigationStack([]);
}
if (isClosingStep) { if (isClosingStep) {
closeRightDrawer(); closeRightDrawer();
@ -76,11 +81,12 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
}); });
}, },
[ [
setCommandMenuNavigationStack, isInRightDrawer,
setWorkflowSelectedNode, setWorkflowSelectedNode,
setHotkeyScope, setHotkeyScope,
openRightDrawer, openRightDrawer,
getIcon, getIcon,
setCommandMenuNavigationStack,
closeRightDrawer, closeRightDrawer,
closeCommandMenu, closeCommandMenu,
t, t,

View File

@ -1,6 +1,7 @@
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations'; import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { View } from '@/views/types/View'; import { View } from '@/views/types/View';
import { ViewKey } from '@/views/types/ViewKey'; import { ViewKey } from '@/views/types/ViewKey';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems'; import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
@ -29,6 +30,7 @@ export const mockedViewsData: View[] = [
kanbanAggregateOperationFieldMetadataId: '', kanbanAggregateOperationFieldMetadataId: '',
position: 0, position: 0,
isCompact: false, isCompact: false,
openRecordIn: ViewOpenRecordInType.SIDE_PANEL,
viewFilterGroups: [], viewFilterGroups: [],
viewGroups: [], viewGroups: [],
viewFields: [], viewFields: [],
@ -48,6 +50,7 @@ export const mockedViewsData: View[] = [
kanbanAggregateOperationFieldMetadataId: '', kanbanAggregateOperationFieldMetadataId: '',
position: 0, position: 0,
isCompact: false, isCompact: false,
openRecordIn: ViewOpenRecordInType.SIDE_PANEL,
viewFilterGroups: [], viewFilterGroups: [],
viewGroups: [], viewGroups: [],
viewFields: [], viewFields: [],
@ -67,6 +70,7 @@ export const mockedViewsData: View[] = [
kanbanAggregateOperationFieldMetadataId: '', kanbanAggregateOperationFieldMetadataId: '',
position: 0, position: 0,
isCompact: false, isCompact: false,
openRecordIn: ViewOpenRecordInType.SIDE_PANEL,
viewFilterGroups: [], viewFilterGroups: [],
viewGroups: [], viewGroups: [],
viewFields: [], viewFields: [],
@ -86,6 +90,7 @@ export const mockedViewsData: View[] = [
kanbanAggregateOperationFieldMetadataId: '', kanbanAggregateOperationFieldMetadataId: '',
position: 0, position: 0,
isCompact: false, isCompact: false,
openRecordIn: ViewOpenRecordInType.SIDE_PANEL,
viewFilterGroups: [], viewFilterGroups: [],
viewGroups: [], viewGroups: [],
viewFields: [], viewFields: [],

View File

@ -0,0 +1,128 @@
import { InjectRepository } from '@nestjs/typeorm';
import chalk from 'chalk';
import { Command } from 'nest-commander';
import { In, Repository } from 'typeorm';
import {
ActiveWorkspacesCommandOptions,
ActiveWorkspacesCommandRunner,
} from 'src/database/commands/active-workspaces.command';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
@Command({
name: 'upgrade-0.43:update-default-view-record-opening-on-workflow-objects',
description:
'Update default view record opening on workflow objects to record page',
})
export class UpdateDefaultViewRecordOpeningOnWorkflowObjectsCommand extends ActiveWorkspacesCommandRunner {
constructor(
@InjectRepository(Workspace, 'core')
protected readonly workspaceRepository: Repository<Workspace>,
@InjectRepository(ObjectMetadataEntity, 'metadata')
protected readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
) {
super(workspaceRepository);
}
async executeActiveWorkspacesCommand(
_passedParam: string[],
_options: ActiveWorkspacesCommandOptions,
workspaceIds: string[],
): Promise<void> {
this.logger.log(
'Running command to update default view record opening on workflow objects to record page',
);
for (const [index, workspaceId] of workspaceIds.entries()) {
await this.processWorkspace(workspaceId, index, workspaceIds.length);
}
this.logger.log(chalk.green('Command completed!'));
}
async processWorkspace(
workspaceId: string,
index: number,
total: number,
): Promise<void> {
try {
this.logger.log(
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
);
const workflowObjectsMetadata = await this.objectMetadataRepository.find({
select: ['id'],
where: {
workspaceId,
standardId: In([
STANDARD_OBJECT_IDS.workflow,
STANDARD_OBJECT_IDS.workflowVersion,
STANDARD_OBJECT_IDS.workflowRun,
]),
},
});
if (workflowObjectsMetadata.length === 0) {
this.logger.log(
chalk.yellow(
`No workflow objects found for workspace ${workspaceId}`,
),
);
return;
}
await this.updateDefaultViewsRecordOpening(
workflowObjectsMetadata.map((metadata) => metadata.id),
workspaceId,
);
await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
workspaceId,
);
await this.workspaceMetadataVersionService.incrementMetadataVersion(
workspaceId,
);
this.logger.log(
chalk.green(`Command completed for workspace ${workspaceId}.`),
);
} catch (error) {
this.logger.log(
chalk.red(`Error in workspace ${workspaceId} - ${error.message}`),
);
}
}
private async updateDefaultViewsRecordOpening(
workflowObjectMetadataIds: string[],
workspaceId: string,
): Promise<void> {
const viewRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace(
workspaceId,
'view',
);
await viewRepository.update(
{
objectMetadataId: In(workflowObjectMetadataIds),
key: 'INDEX',
},
{
openRecordIn: ViewOpenRecordInType.RECORD_PAGE,
},
);
}
}

View File

@ -7,6 +7,8 @@ import { ActiveWorkspacesCommandRunner } from 'src/database/commands/active-work
import { BaseCommandOptions } from 'src/database/commands/base.command'; import { BaseCommandOptions } from 'src/database/commands/base.command';
import { StandardizationOfActorCompositeContextTypeCommand } from 'src/database/commands/upgrade-version/0-42/0-42-standardization-of-actor-composite-context-type'; import { StandardizationOfActorCompositeContextTypeCommand } from 'src/database/commands/upgrade-version/0-42/0-42-standardization-of-actor-composite-context-type';
import { AddTasksAssignedToMeViewCommand } from 'src/database/commands/upgrade-version/0-43/0-43-add-tasks-assigned-to-me-view.command'; import { AddTasksAssignedToMeViewCommand } from 'src/database/commands/upgrade-version/0-43/0-43-add-tasks-assigned-to-me-view.command';
import { MigrateSearchVectorOnNoteAndTaskEntitiesCommand } from 'src/database/commands/upgrade-version/0-43/0-43-migrate-search-vector-on-note-and-task-entities.command';
import { UpdateDefaultViewRecordOpeningOnWorkflowObjectsCommand } from 'src/database/commands/upgrade-version/0-43/0-43-update-default-view-record-opening-on-workflow-objects.command';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
@Command({ @Command({
@ -18,6 +20,8 @@ export class UpgradeTo0_43Command extends ActiveWorkspacesCommandRunner {
@InjectRepository(Workspace, 'core') @InjectRepository(Workspace, 'core')
protected readonly workspaceRepository: Repository<Workspace>, protected readonly workspaceRepository: Repository<Workspace>,
private readonly addTasksAssignedToMeViewCommand: AddTasksAssignedToMeViewCommand, private readonly addTasksAssignedToMeViewCommand: AddTasksAssignedToMeViewCommand,
private readonly migrateSearchVectorOnNoteAndTaskEntitiesCommand: MigrateSearchVectorOnNoteAndTaskEntitiesCommand,
private readonly updateDefaultViewRecordOpeningOnWorkflowObjectsCommand: UpdateDefaultViewRecordOpeningOnWorkflowObjectsCommand,
private readonly standardizationOfActorCompositeContextTypeCommand: StandardizationOfActorCompositeContextTypeCommand, private readonly standardizationOfActorCompositeContextTypeCommand: StandardizationOfActorCompositeContextTypeCommand,
) { ) {
super(workspaceRepository); super(workspaceRepository);
@ -36,6 +40,18 @@ export class UpgradeTo0_43Command extends ActiveWorkspacesCommandRunner {
workspaceIds, workspaceIds,
); );
await this.migrateSearchVectorOnNoteAndTaskEntitiesCommand.executeActiveWorkspacesCommand(
passedParam,
options,
workspaceIds,
);
await this.updateDefaultViewRecordOpeningOnWorkflowObjectsCommand.executeActiveWorkspacesCommand(
passedParam,
options,
workspaceIds,
);
// Note: Introduced in 0.42, ran manually on prod. Introduced to self-host globally on 0.43 // Note: Introduced in 0.42, ran manually on prod. Introduced to self-host globally on 0.43
await this.standardizationOfActorCompositeContextTypeCommand.executeActiveWorkspacesCommand( await this.standardizationOfActorCompositeContextTypeCommand.executeActiveWorkspacesCommand(
passedParam, passedParam,

View File

@ -4,6 +4,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { StandardizationOfActorCompositeContextTypeCommand } from 'src/database/commands/upgrade-version/0-42/0-42-standardization-of-actor-composite-context-type'; import { StandardizationOfActorCompositeContextTypeCommand } from 'src/database/commands/upgrade-version/0-42/0-42-standardization-of-actor-composite-context-type';
import { AddTasksAssignedToMeViewCommand } from 'src/database/commands/upgrade-version/0-43/0-43-add-tasks-assigned-to-me-view.command'; import { AddTasksAssignedToMeViewCommand } from 'src/database/commands/upgrade-version/0-43/0-43-add-tasks-assigned-to-me-view.command';
import { MigrateSearchVectorOnNoteAndTaskEntitiesCommand } from 'src/database/commands/upgrade-version/0-43/0-43-migrate-search-vector-on-note-and-task-entities.command'; import { MigrateSearchVectorOnNoteAndTaskEntitiesCommand } from 'src/database/commands/upgrade-version/0-43/0-43-migrate-search-vector-on-note-and-task-entities.command';
import { UpdateDefaultViewRecordOpeningOnWorkflowObjectsCommand } from 'src/database/commands/upgrade-version/0-43/0-43-update-default-view-record-opening-on-workflow-objects.command';
import { UpgradeTo0_43Command } from 'src/database/commands/upgrade-version/0-43/0-43-upgrade-version.command'; import { UpgradeTo0_43Command } from 'src/database/commands/upgrade-version/0-43/0-43-upgrade-version.command';
import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
@ -30,6 +31,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor
UpgradeTo0_43Command, UpgradeTo0_43Command,
AddTasksAssignedToMeViewCommand, AddTasksAssignedToMeViewCommand,
MigrateSearchVectorOnNoteAndTaskEntitiesCommand, MigrateSearchVectorOnNoteAndTaskEntitiesCommand,
UpdateDefaultViewRecordOpeningOnWorkflowObjectsCommand,
StandardizationOfActorCompositeContextTypeCommand, StandardizationOfActorCompositeContextTypeCommand,
], ],
}) })

View File

@ -586,6 +586,10 @@ msgstr "Rigting"
msgid "Display Name" msgid "Display Name"
msgstr "Wys Naam" msgstr "Wys Naam"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Vertoon Waarde" msgstr "Vertoon Waarde"
@ -1327,6 +1331,10 @@ msgstr "Objek Metadata Id"
msgid "Object name" msgid "Object name"
msgstr "Objek naam" msgstr "Objek naam"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operant" msgstr "Operant"

View File

@ -586,6 +586,10 @@ msgstr "الاتجاه"
msgid "Display Name" msgid "Display Name"
msgstr "اسم العرض" msgstr "اسم العرض"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "قيمة العرض" msgstr "قيمة العرض"
@ -1327,6 +1331,10 @@ msgstr "معرف بيانات الكائن"
msgid "Object name" msgid "Object name"
msgstr "اسم الكائن" msgstr "اسم الكائن"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "العملية" msgstr "العملية"
@ -1584,7 +1592,9 @@ msgstr "مؤشر التزامن"
#: src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts #: src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts
msgid "Sync Cursor. Used for syncing events from the calendar provider" msgid "Sync Cursor. Used for syncing events from the calendar provider"
msgstr "\n" msgstr ""
"\n"
""
#: src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts #: src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts
#: src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts #: src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts

View File

@ -586,6 +586,10 @@ msgstr "Direcció"
msgid "Display Name" msgid "Display Name"
msgstr "Nom Visible" msgstr "Nom Visible"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Valor Visible" msgstr "Valor Visible"
@ -1327,6 +1331,10 @@ msgstr "Id de Metadades de l'Objecte"
msgid "Object name" msgid "Object name"
msgstr "Nom de l'objecte" msgstr "Nom de l'objecte"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operador" msgstr "Operador"

View File

@ -586,6 +586,10 @@ msgstr "Směr"
msgid "Display Name" msgid "Display Name"
msgstr "Zobrazovaný název" msgstr "Zobrazovaný název"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Zobrazovaná hodnota" msgstr "Zobrazovaná hodnota"
@ -1327,6 +1331,10 @@ msgstr "ID metadat objektu"
msgid "Object name" msgid "Object name"
msgstr "Název objektu" msgstr "Název objektu"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operand" msgstr "Operand"

View File

@ -586,6 +586,10 @@ msgstr "Retning"
msgid "Display Name" msgid "Display Name"
msgstr "Visningsnavn" msgstr "Visningsnavn"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Visningsværdi" msgstr "Visningsværdi"
@ -1327,6 +1331,10 @@ msgstr "Objekt Metadata-id"
msgid "Object name" msgid "Object name"
msgstr "Objektnavn" msgstr "Objektnavn"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operand" msgstr "Operand"
@ -1540,7 +1548,8 @@ msgstr "Køringer"
#: src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts #: src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts
#: src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts #: src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts
msgid "Scopes" msgid "Scopes"
msgstr "R\n" msgstr ""
"R\n"
"ettigheder" "ettigheder"
#: src/engine/metadata-modules/constants/search-vector-field.constants.ts #: src/engine/metadata-modules/constants/search-vector-field.constants.ts

View File

@ -586,6 +586,10 @@ msgstr "Richtung"
msgid "Display Name" msgid "Display Name"
msgstr "Anzeigename" msgstr "Anzeigename"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Anzeigewert" msgstr "Anzeigewert"
@ -1327,6 +1331,10 @@ msgstr "Objekt-Metadaten-ID"
msgid "Object name" msgid "Object name"
msgstr "Objektname" msgstr "Objektname"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operand" msgstr "Operand"

View File

@ -586,6 +586,10 @@ msgstr "Κατεύθυνση"
msgid "Display Name" msgid "Display Name"
msgstr "Εμφανιζόμενο Όνομα" msgstr "Εμφανιζόμενο Όνομα"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Εμφανιζόμενη Αξία" msgstr "Εμφανιζόμενη Αξία"
@ -1327,6 +1331,10 @@ msgstr "Αναγνωριστικό Μετα-δεδομένων Αντικειμ
msgid "Object name" msgid "Object name"
msgstr "Όνομα αντικειμένου" msgstr "Όνομα αντικειμένου"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Οπεράνδος" msgstr "Οπεράνδος"

View File

@ -581,6 +581,10 @@ msgstr "Direction"
msgid "Display Name" msgid "Display Name"
msgstr "Display Name" msgstr "Display Name"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr "Display the records in a side panel or in a record page"
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Display Value" msgstr "Display Value"
@ -1322,6 +1326,10 @@ msgstr "Object Metadata Id"
msgid "Object name" msgid "Object name"
msgstr "Object name" msgstr "Object name"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr "Open Record In"
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operand" msgstr "Operand"

View File

@ -586,6 +586,10 @@ msgstr "Dirección"
msgid "Display Name" msgid "Display Name"
msgstr "Nombre para mostrar" msgstr "Nombre para mostrar"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Valor para mostrar" msgstr "Valor para mostrar"
@ -1327,6 +1331,10 @@ msgstr "ID de metadatos del objeto"
msgid "Object name" msgid "Object name"
msgstr "Nombre del objeto" msgstr "Nombre del objeto"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operando" msgstr "Operando"

View File

@ -586,6 +586,10 @@ msgstr "Suunta"
msgid "Display Name" msgid "Display Name"
msgstr "Näyttönimi" msgstr "Näyttönimi"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Näyttöarvo" msgstr "Näyttöarvo"
@ -1327,6 +1331,10 @@ msgstr "Kohdemetadatatunniste"
msgid "Object name" msgid "Object name"
msgstr "Kohteen nimi" msgstr "Kohteen nimi"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operaattori" msgstr "Operaattori"

View File

@ -586,6 +586,10 @@ msgstr "Direction"
msgid "Display Name" msgid "Display Name"
msgstr "Nom d'affichage" msgstr "Nom d'affichage"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Valeur affichée" msgstr "Valeur affichée"
@ -1327,6 +1331,10 @@ msgstr "ID des métadonnées de l'objet"
msgid "Object name" msgid "Object name"
msgstr "Nom de l'objet" msgstr "Nom de l'objet"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Opérande" msgstr "Opérande"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -586,6 +586,10 @@ msgstr "כיוון"
msgid "Display Name" msgid "Display Name"
msgstr "שם תצוגה" msgstr "שם תצוגה"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "ערך תצוגה" msgstr "ערך תצוגה"
@ -1327,6 +1331,10 @@ msgstr "מזהה מטא-נתונים של אובייקט"
msgid "Object name" msgid "Object name"
msgstr "שם האובייקט" msgstr "שם האובייקט"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "אופרנד" msgstr "אופרנד"

View File

@ -586,6 +586,10 @@ msgstr "Irány"
msgid "Display Name" msgid "Display Name"
msgstr "Megjelenítendő név" msgstr "Megjelenítendő név"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Megjelenítési érték" msgstr "Megjelenítési érték"
@ -1327,6 +1331,10 @@ msgstr "Objektum Metaadat Azonosító"
msgid "Object name" msgid "Object name"
msgstr "Objektum neve" msgstr "Objektum neve"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operándus" msgstr "Operándus"

View File

@ -586,6 +586,10 @@ msgstr "Direzione"
msgid "Display Name" msgid "Display Name"
msgstr "Nome visualizzato" msgstr "Nome visualizzato"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Valore visualizzato" msgstr "Valore visualizzato"
@ -1327,6 +1331,10 @@ msgstr "ID metadati dell'oggetto"
msgid "Object name" msgid "Object name"
msgstr "Nome oggetto" msgstr "Nome oggetto"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operando" msgstr "Operando"

View File

@ -586,6 +586,10 @@ msgstr "方向"
msgid "Display Name" msgid "Display Name"
msgstr "表示名" msgstr "表示名"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "表示値" msgstr "表示値"
@ -1327,6 +1331,10 @@ msgstr "オブジェクトメタデータID"
msgid "Object name" msgid "Object name"
msgstr "オブジェクト名" msgstr "オブジェクト名"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "オペランド" msgstr "オペランド"

View File

@ -586,6 +586,10 @@ msgstr "방향"
msgid "Display Name" msgid "Display Name"
msgstr "표시 이름" msgstr "표시 이름"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "표시 값" msgstr "표시 값"
@ -1327,6 +1331,10 @@ msgstr "객체 메타데이터 ID"
msgid "Object name" msgid "Object name"
msgstr "객체 이름" msgstr "객체 이름"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "피연산자" msgstr "피연산자"

View File

@ -586,6 +586,10 @@ msgstr "Richting"
msgid "Display Name" msgid "Display Name"
msgstr "Weergavenaam" msgstr "Weergavenaam"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Weergavewaarde" msgstr "Weergavewaarde"
@ -1327,6 +1331,10 @@ msgstr "Object Metadata-ID"
msgid "Object name" msgid "Object name"
msgstr "Object naam" msgstr "Object naam"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operand" msgstr "Operand"

View File

@ -586,6 +586,10 @@ msgstr "Retning"
msgid "Display Name" msgid "Display Name"
msgstr "Visningsnavn" msgstr "Visningsnavn"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Visningsverdi" msgstr "Visningsverdi"
@ -1327,6 +1331,10 @@ msgstr "Objekt Metadata-id"
msgid "Object name" msgid "Object name"
msgstr "Objektnavn" msgstr "Objektnavn"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operant" msgstr "Operant"

View File

@ -586,6 +586,10 @@ msgstr "Kierunek"
msgid "Display Name" msgid "Display Name"
msgstr "Nazwa wyświetlana" msgstr "Nazwa wyświetlana"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Wartość wyświetlana" msgstr "Wartość wyświetlana"
@ -1327,6 +1331,10 @@ msgstr "Identyfikator metadanych obiektu"
msgid "Object name" msgid "Object name"
msgstr "Nazwa obiektu" msgstr "Nazwa obiektu"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Składnik" msgstr "Składnik"

View File

@ -581,6 +581,10 @@ msgstr ""
msgid "Display Name" msgid "Display Name"
msgstr "" msgstr ""
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "" msgstr ""
@ -1322,6 +1326,10 @@ msgstr ""
msgid "Object name" msgid "Object name"
msgstr "" msgstr ""
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "" msgstr ""

View File

@ -586,6 +586,10 @@ msgstr "Direção"
msgid "Display Name" msgid "Display Name"
msgstr "Nome de Exibição" msgstr "Nome de Exibição"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Valor de Exibição" msgstr "Valor de Exibição"
@ -1327,6 +1331,10 @@ msgstr "ID de Metadados do Objeto"
msgid "Object name" msgid "Object name"
msgstr "Nome do Objeto" msgstr "Nome do Objeto"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operando" msgstr "Operando"

View File

@ -586,6 +586,10 @@ msgstr "Direção"
msgid "Display Name" msgid "Display Name"
msgstr "Nome de Exibição" msgstr "Nome de Exibição"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Valor de Exibição" msgstr "Valor de Exibição"
@ -1327,6 +1331,10 @@ msgstr "ID de Metadados do Objeto"
msgid "Object name" msgid "Object name"
msgstr "Nome do Objeto" msgstr "Nome do Objeto"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operando" msgstr "Operando"

View File

@ -586,6 +586,10 @@ msgstr "Direcție"
msgid "Display Name" msgid "Display Name"
msgstr "Nume afișat" msgstr "Nume afișat"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Valoare afișată" msgstr "Valoare afișată"
@ -1327,6 +1331,10 @@ msgstr "Id-ul Metadatelor Obiectului"
msgid "Object name" msgid "Object name"
msgstr "Numele obiectului" msgstr "Numele obiectului"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operand" msgstr "Operand"

View File

@ -586,6 +586,10 @@ msgstr "Направление"
msgid "Display Name" msgid "Display Name"
msgstr "Отображаемое имя" msgstr "Отображаемое имя"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Отображаемое значение" msgstr "Отображаемое значение"
@ -1327,6 +1331,10 @@ msgstr "Идентификатор метаданных объекта"
msgid "Object name" msgid "Object name"
msgstr "Имя объекта" msgstr "Имя объекта"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Операнд" msgstr "Операнд"

View File

@ -586,6 +586,10 @@ msgstr "Смер"
msgid "Display Name" msgid "Display Name"
msgstr "Приказно име" msgstr "Приказно име"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Приказна вредност" msgstr "Приказна вредност"
@ -1327,6 +1331,10 @@ msgstr "Идентификатор метаподатака објекта"
msgid "Object name" msgid "Object name"
msgstr "Назив објекта" msgstr "Назив објекта"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Операнд" msgstr "Операнд"

View File

@ -586,6 +586,10 @@ msgstr "Riktning"
msgid "Display Name" msgid "Display Name"
msgstr "Visningsnamn" msgstr "Visningsnamn"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Visningsvärde" msgstr "Visningsvärde"
@ -1327,6 +1331,10 @@ msgstr "Objektmetadata-id"
msgid "Object name" msgid "Object name"
msgstr "Objektnamn" msgstr "Objektnamn"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Operand" msgstr "Operand"
@ -1481,7 +1489,8 @@ msgstr "F\"or\"aldrade f\"argschema"
#: src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts #: src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts
msgid "Preferred language" msgid "Preferred language"
msgstr "F\"or\"aldrat spr\n" msgstr ""
"F\"or\"aldrat spr\n"
"k" "k"
#: src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts #: src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts
@ -1585,7 +1594,8 @@ msgstr "Synkkurs"
#: src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts #: src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts
msgid "Sync Cursor. Used for syncing events from the calendar provider" msgid "Sync Cursor. Used for syncing events from the calendar provider"
msgstr "Synkkurs. Anv\"ands f\"or att synkronisera h\"andelser fr\n" msgstr ""
"Synkkurs. Anv\"ands f\"or att synkronisera h\"andelser fr\n"
"n kalenderleverant\"oren" "n kalenderleverant\"oren"
#: src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts #: src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts

View File

@ -586,6 +586,10 @@ msgstr "Yön"
msgid "Display Name" msgid "Display Name"
msgstr "Görünen Ad" msgstr "Görünen Ad"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Görüntü Değeri" msgstr "Görüntü Değeri"
@ -1327,6 +1331,10 @@ msgstr "Nesne Metaveri Kimliği"
msgid "Object name" msgid "Object name"
msgstr "Nesne adı" msgstr "Nesne adı"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "İşlenen" msgstr "İşlenen"

View File

@ -586,6 +586,10 @@ msgstr "Напрямок"
msgid "Display Name" msgid "Display Name"
msgstr "Назва для відображення" msgstr "Назва для відображення"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Значення для відображення" msgstr "Значення для відображення"
@ -1327,6 +1331,10 @@ msgstr "ID метаданих об'єкту"
msgid "Object name" msgid "Object name"
msgstr "Назва об'єкта" msgstr "Назва об'єкта"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Операнд" msgstr "Операнд"

View File

@ -586,6 +586,10 @@ msgstr "Hướng"
msgid "Display Name" msgid "Display Name"
msgstr "Tên hiển thị" msgstr "Tên hiển thị"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "Giá trị hiển thị" msgstr "Giá trị hiển thị"
@ -1327,6 +1331,10 @@ msgstr "Mã Id Metadata Đối Tượng"
msgid "Object name" msgid "Object name"
msgstr "Tên đối tượng" msgstr "Tên đối tượng"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "Toán hạng" msgstr "Toán hạng"

View File

@ -586,6 +586,10 @@ msgstr "方向"
msgid "Display Name" msgid "Display Name"
msgstr "显示名称" msgstr "显示名称"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "显示值" msgstr "显示值"
@ -1327,6 +1331,10 @@ msgstr "对象元数据 ID"
msgid "Object name" msgid "Object name"
msgstr "对象名称" msgstr "对象名称"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "操作数" msgstr "操作数"

View File

@ -586,6 +586,10 @@ msgstr "方向"
msgid "Display Name" msgid "Display Name"
msgstr "顯示名稱" msgstr "顯示名稱"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Display the records in a side panel or in a record page"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Display Value" msgid "Display Value"
msgstr "顯示值" msgstr "顯示值"
@ -1327,6 +1331,10 @@ msgstr "對象元數據 ID"
msgid "Object name" msgid "Object name"
msgstr "對象名稱" msgstr "對象名稱"
#: src/modules/view/standard-objects/view.workspace-entity.ts
msgid "Open Record In"
msgstr ""
#: src/modules/view/standard-objects/view-filter.workspace-entity.ts #: src/modules/view/standard-objects/view-filter.workspace-entity.ts
msgid "Operand" msgid "Operand"
msgstr "操作數" msgstr "操作數"

View File

@ -24,6 +24,7 @@ export const createWorkspaceViews = async (
'key', 'key',
'position', 'position',
'icon', 'icon',
'openRecordIn',
'kanbanFieldMetadataId', 'kanbanFieldMetadataId',
'kanbanAggregateOperation', 'kanbanAggregateOperation',
'kanbanAggregateOperationFieldMetadataId', 'kanbanAggregateOperationFieldMetadataId',
@ -38,6 +39,7 @@ export const createWorkspaceViews = async (
key, key,
position, position,
icon, icon,
openRecordIn,
kanbanFieldMetadataId, kanbanFieldMetadataId,
kanbanAggregateOperation, kanbanAggregateOperation,
kanbanAggregateOperationFieldMetadataId, kanbanAggregateOperationFieldMetadataId,
@ -49,6 +51,7 @@ export const createWorkspaceViews = async (
key, key,
position, position,
icon, icon,
openRecordIn,
kanbanFieldMetadataId, kanbanFieldMetadataId,
kanbanAggregateOperation, kanbanAggregateOperation,
kanbanAggregateOperationFieldMetadataId, kanbanAggregateOperationFieldMetadataId,

View File

@ -1,4 +1,5 @@
import { AGGREGATE_OPERATIONS } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant'; import { AGGREGATE_OPERATIONS } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
export interface ViewDefinition { export interface ViewDefinition {
id?: string; id?: string;
@ -8,6 +9,7 @@ export interface ViewDefinition {
key: string | null; key: string | null;
position: number; position: number;
icon?: string; icon?: string;
openRecordIn?: ViewOpenRecordInType;
kanbanFieldMetadataId?: string; kanbanFieldMetadataId?: string;
kanbanAggregateOperation?: AGGREGATE_OPERATIONS; kanbanAggregateOperation?: AGGREGATE_OPERATIONS;
kanbanAggregateOperationFieldMetadataId?: string; kanbanAggregateOperationFieldMetadataId?: string;

View File

@ -2,6 +2,7 @@ import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/obj
import { WORKFLOW_RUN_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { WORKFLOW_RUN_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'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
export const workflowRunsAllView = ( export const workflowRunsAllView = (
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap, objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
@ -14,6 +15,7 @@ export const workflowRunsAllView = (
key: 'INDEX', key: 'INDEX',
position: 0, position: 0,
icon: 'IconHistory', icon: 'IconHistory',
openRecordIn: ViewOpenRecordInType.RECORD_PAGE,
kanbanFieldMetadataId: '', kanbanFieldMetadataId: '',
filters: [], filters: [],
fields: [ fields: [

View File

@ -5,6 +5,7 @@ import {
WORKFLOW_VERSION_STANDARD_FIELD_IDS, WORKFLOW_VERSION_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/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'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
export const workflowVersionsAllView = ( export const workflowVersionsAllView = (
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap, objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
@ -17,6 +18,7 @@ export const workflowVersionsAllView = (
key: 'INDEX', key: 'INDEX',
position: 0, position: 0,
icon: 'IconVersions', icon: 'IconVersions',
openRecordIn: ViewOpenRecordInType.RECORD_PAGE,
kanbanFieldMetadataId: '', kanbanFieldMetadataId: '',
filters: [], filters: [],
fields: [ fields: [

View File

@ -5,6 +5,7 @@ import {
WORKFLOW_STANDARD_FIELD_IDS, WORKFLOW_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/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'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
export const workflowsAllView = ( export const workflowsAllView = (
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap, objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
@ -17,6 +18,7 @@ export const workflowsAllView = (
key: 'INDEX', key: 'INDEX',
position: 0, position: 0,
icon: 'IconSettingsAutomation', icon: 'IconSettingsAutomation',
openRecordIn: ViewOpenRecordInType.RECORD_PAGE,
kanbanFieldMetadataId: '', kanbanFieldMetadataId: '',
filters: [], filters: [],
fields: [ fields: [

View File

@ -435,6 +435,7 @@ export const VIEW_STANDARD_FIELD_IDS = {
'20202020-b1b3-4bf3-85e4-dc7d58aa9b02', '20202020-b1b3-4bf3-85e4-dc7d58aa9b02',
position: '20202020-e9db-4303-b271-e8250c450172', position: '20202020-e9db-4303-b271-e8250c450172',
isCompact: '20202020-674e-4314-994d-05754ea7b22b', isCompact: '20202020-674e-4314-994d-05754ea7b22b',
openRecordIn: '20202020-086d-4eef-9f03-56c6392eacb8',
viewFields: '20202020-542b-4bdc-b177-b63175d48edf', viewFields: '20202020-542b-4bdc-b177-b63175d48edf',
viewGroups: '20202020-e1a1-419f-ac81-1986a5ea59a8', viewGroups: '20202020-e1a1-419f-ac81-1986a5ea59a8',
viewFilters: '20202020-ff23-4154-b63c-21fb36cd0967', viewFilters: '20202020-ff23-4154-b63c-21fb36cd0967',

View File

@ -1,3 +1,5 @@
import { registerEnumType } from '@nestjs/graphql';
import { msg } from '@lingui/core/macro'; import { msg } from '@lingui/core/macro';
import { FieldMetadataType } from 'twenty-shared'; import { FieldMetadataType } from 'twenty-shared';
@ -25,6 +27,15 @@ import { ViewFilterWorkspaceEntity } from 'src/modules/view/standard-objects/vie
import { ViewGroupWorkspaceEntity } from 'src/modules/view/standard-objects/view-group.workspace-entity'; import { ViewGroupWorkspaceEntity } from 'src/modules/view/standard-objects/view-group.workspace-entity';
import { ViewSortWorkspaceEntity } from 'src/modules/view/standard-objects/view-sort.workspace-entity'; import { ViewSortWorkspaceEntity } from 'src/modules/view/standard-objects/view-sort.workspace-entity';
export enum ViewOpenRecordInType {
SIDE_PANEL = 'SIDE_PANEL',
RECORD_PAGE = 'RECORD_PAGE',
}
registerEnumType(ViewOpenRecordInType, {
name: 'ViewOpenRecordInType',
});
@WorkspaceEntity({ @WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.view, standardId: STANDARD_OBJECT_IDS.view,
namePlural: 'views', namePlural: 'views',
@ -111,6 +122,29 @@ export class ViewWorkspaceEntity extends BaseWorkspaceEntity {
}) })
isCompact: boolean; isCompact: boolean;
@WorkspaceField({
standardId: VIEW_STANDARD_FIELD_IDS.openRecordIn,
type: FieldMetadataType.SELECT,
label: msg`Open Record In`,
description: msg`Display the records in a side panel or in a record page`,
defaultValue: `'${ViewOpenRecordInType.SIDE_PANEL}'`,
options: [
{
value: ViewOpenRecordInType.SIDE_PANEL,
label: 'Side Panel',
position: 0,
color: 'green',
},
{
value: ViewOpenRecordInType.RECORD_PAGE,
label: 'Record Page',
position: 1,
color: 'blue',
},
],
})
openRecordIn: ViewOpenRecordInType;
@WorkspaceRelation({ @WorkspaceRelation({
standardId: VIEW_STANDARD_FIELD_IDS.viewFields, standardId: VIEW_STANDARD_FIELD_IDS.viewFields,
type: RelationMetadataType.ONE_TO_MANY, type: RelationMetadataType.ONE_TO_MANY,

Some files were not shown because too many files have changed in this diff Show More