Compare commits

...

2 Commits

Author SHA1 Message Date
Marie b9bc1264b3 Allow twenty standard app to access messaging items (#17659) 2026-02-03 13:38:30 +01:00
Thomas Trompette be358e398e Fix spaces in code step + suggestion overflow (#17664)
- fixedOverflowWidgets fixes the suggestions being overflow outside the
editor
- on focus, stop event propagation to avoid catching spaces as document
level events
2026-02-03 13:38:22 +01:00
6 changed files with 70 additions and 15 deletions
@@ -443,6 +443,7 @@ export const WorkflowEditActionCode = ({
scrollBeyondLastLine: false,
padding: { top: 4, bottom: 4 },
lineNumbersMinChars: 2,
fixedOverflowWidgets: true,
}}
readonly={actionOptions.readonly}
onEnterFullScreen={handleEnterFullScreen}
@@ -6,6 +6,7 @@ import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runne
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
import { ApplyCalendarEventsVisibilityRestrictionsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service';
import { type CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
@@ -25,10 +26,19 @@ export class CalendarEventFindManyPostQueryHook
_objectName: string,
payload: CalendarEventWorkspaceEntity[],
): Promise<void> {
const { user, apiKey } = authContext;
const { user, apiKey, application } = authContext;
if (!isDefined(user) && !isDefined(apiKey)) {
throw new ForbiddenError('User is required');
const isTwentyStandardApplication =
isDefined(application) &&
application.universalIdentifier ===
TWENTY_STANDARD_APPLICATION.universalIdentifier;
if (
!isDefined(user) &&
!isDefined(apiKey) &&
!isTwentyStandardApplication
) {
throw new ForbiddenError('Authentication is required');
}
const workspace = authContext.workspace;
@@ -6,6 +6,7 @@ import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runne
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
import { ApplyCalendarEventsVisibilityRestrictionsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service';
import { type CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
@@ -25,10 +26,19 @@ export class CalendarEventFindOnePostQueryHook
_objectName: string,
payload: CalendarEventWorkspaceEntity[],
): Promise<void> {
const { user, apiKey } = authContext;
const { user, apiKey, application } = authContext;
if (!isDefined(user) && !isDefined(apiKey)) {
throw new ForbiddenError('User is required');
const isTwentyStandardApplication =
isDefined(application) &&
application.universalIdentifier ===
TWENTY_STANDARD_APPLICATION.universalIdentifier;
if (
!isDefined(user) &&
!isDefined(apiKey) &&
!isTwentyStandardApplication
) {
throw new ForbiddenError('Authentication is required');
}
const workspace = authContext.workspace;
@@ -6,6 +6,7 @@ import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runne
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
import { ApplyMessagesVisibilityRestrictionsService } from 'src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service';
import { type MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
@@ -25,10 +26,19 @@ export class MessageFindManyPostQueryHook
_objectName: string,
payload: MessageWorkspaceEntity[],
): Promise<void> {
const { user, apiKey } = authContext;
const { user, apiKey, application } = authContext;
if (!isDefined(user) && !isDefined(apiKey)) {
throw new ForbiddenError('User is required');
const isTwentyStandardApplication =
isDefined(application) &&
application.universalIdentifier ===
TWENTY_STANDARD_APPLICATION.universalIdentifier;
if (
!isDefined(user) &&
!isDefined(apiKey) &&
!isTwentyStandardApplication
) {
throw new ForbiddenError('Authentication is required');
}
const workspace = authContext.workspace;
@@ -6,6 +6,7 @@ import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runne
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
import { ApplyMessagesVisibilityRestrictionsService } from 'src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service';
import { type MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
@@ -25,10 +26,19 @@ export class MessageFindOnePostQueryHook
_objectName: string,
payload: MessageWorkspaceEntity[],
): Promise<void> {
const { user, apiKey } = authContext;
const { user, apiKey, application } = authContext;
if (!isDefined(user) && !isDefined(apiKey)) {
throw new ForbiddenError('User is required');
const isTwentyStandardApplication =
isDefined(application) &&
application.universalIdentifier ===
TWENTY_STANDARD_APPLICATION.universalIdentifier;
if (
!isDefined(user) &&
!isDefined(apiKey) &&
!isTwentyStandardApplication
) {
throw new ForbiddenError('Authentication is required');
}
const workspace = authContext.workspace;
@@ -5,7 +5,7 @@ import { Loader } from '@ui/feedback/loader/components/Loader';
import { BASE_CODE_EDITOR_THEME_ID } from '@ui/input/code-editor/constants/BaseCodeEditorThemeId';
import { getBaseCodeEditorTheme } from '@ui/input/code-editor/theme/utils/getBaseCodeEditorTheme';
import { type editor } from 'monaco-editor';
import { useState } from 'react';
import { type KeyboardEvent, useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
type CodeEditorVariant = 'default' | 'with-header' | 'borderless';
@@ -113,6 +113,7 @@ export const CodeEditor = ({
const [editor, setEditor] = useState<
editor.IStandaloneCodeEditor | undefined
>(undefined);
const [isEditorFocused, setIsEditorFocused] = useState(false);
const setModelMarkers = (
editor: editor.IStandaloneCodeEditor | undefined,
@@ -128,12 +129,18 @@ export const CodeEditor = ({
}
};
const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
if (isEditorFocused) {
event.stopPropagation();
}
};
return isLoading ? (
<StyledEditorLoader height={height} variant={variant}>
<Loader />
</StyledEditorLoader>
) : (
<>
<div onKeyDown={handleKeyDown}>
<input
type="hidden"
data-testid="code-editor-value"
@@ -159,6 +166,13 @@ export const CodeEditor = ({
);
monaco.editor.setTheme(BASE_CODE_EDITOR_THEME_ID);
editor.onDidFocusEditorWidget(() => {
setIsEditorFocused(true);
});
editor.onDidBlurEditorWidget(() => {
setIsEditorFocused(false);
});
onMount?.(editor, monaco);
setModelMarkers(editor, monaco);
}}
@@ -185,6 +199,6 @@ export const CodeEditor = ({
...options,
}}
/>
</>
</div>
);
};