Added hotkeyScopes to serverless functions in settings (#6710)
Fixes #6656 Is this the right way to implement keyboard listeners? Please let me know, I'll make the changes accordingly. :) https://github.com/user-attachments/assets/af71d340-ead9-4659-81e6-a440522a194f --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
20
packages/twenty-front/src/hooks/useHotkeyScopeOnMount.ts
Normal file
20
packages/twenty-front/src/hooks/useHotkeyScopeOnMount.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const useHotkeyScopeOnMount = (hotkeyScope: string) => {
|
||||
const {
|
||||
goBackToPreviousHotkeyScope,
|
||||
setHotkeyScopeAndMemorizePreviousScope,
|
||||
} = usePreviousHotkeyScope();
|
||||
|
||||
useEffect(() => {
|
||||
setHotkeyScopeAndMemorizePreviousScope(hotkeyScope);
|
||||
return () => {
|
||||
goBackToPreviousHotkeyScope();
|
||||
};
|
||||
}, [
|
||||
hotkeyScope,
|
||||
setHotkeyScopeAndMemorizePreviousScope,
|
||||
goBackToPreviousHotkeyScope,
|
||||
]);
|
||||
};
|
||||
@ -1,14 +1,19 @@
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import styled from '@emotion/styled';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { useGetManyServerlessFunctions } from '@/settings/serverless-functions/hooks/useGetManyServerlessFunctions';
|
||||
import { SettingsServerlessFunctionsFieldItemTableRow } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsFieldItemTableRow';
|
||||
import { ServerlessFunction } from '~/generated-metadata/graphql';
|
||||
import { SettingsServerlessFunctionsTableEmpty } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsTableEmpty';
|
||||
import { useGetManyServerlessFunctions } from '@/settings/serverless-functions/hooks/useGetManyServerlessFunctions';
|
||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import styled from '@emotion/styled';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { ServerlessFunction } from '~/generated-metadata/graphql';
|
||||
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
|
||||
|
||||
const StyledTableRow = styled(TableRow)`
|
||||
grid-template-columns: 312px 132px 68px;
|
||||
@ -20,6 +25,19 @@ const StyledTableBody = styled(TableBody)`
|
||||
|
||||
export const SettingsServerlessFunctionsTable = () => {
|
||||
const { serverlessFunctions } = useGetManyServerlessFunctions();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useHotkeyScopeOnMount(
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunction,
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Enter],
|
||||
() => {
|
||||
navigate(getSettingsPagePath(SettingsPath.NewServerlessFunction));
|
||||
},
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunction,
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{serverlessFunctions.length ? (
|
||||
|
||||
@ -1,11 +1,18 @@
|
||||
import { H2Title, IconPlayerPlay, IconGitCommit, IconRestore } from 'twenty-ui';
|
||||
import { CodeEditor } from '@/ui/input/code-editor/components/CodeEditor';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { ServerlessFunctionFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { CodeEditor } from '@/ui/input/code-editor/components/CodeEditor';
|
||||
import { CoreEditorHeader } from '@/ui/input/code-editor/components/CodeEditorHeader';
|
||||
import styled from '@emotion/styled';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { TabList } from '@/ui/layout/tab/components/TabList';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import styled from '@emotion/styled';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { H2Title, IconGitCommit, IconPlayerPlay, IconRestore } from 'twenty-ui';
|
||||
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
|
||||
|
||||
const StyledTabList = styled(TabList)`
|
||||
border-bottom: none;
|
||||
@ -76,7 +83,18 @@ export const SettingsServerlessFunctionCodeEditorTab = ({
|
||||
rightNodes={[ResetButton, PublishButton, TestButton]}
|
||||
/>
|
||||
);
|
||||
const navigate = useNavigate();
|
||||
useHotkeyScopeOnMount(
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionEditorTab,
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
() => {
|
||||
navigate(getSettingsPagePath(SettingsPath.ServerlessFunctions));
|
||||
},
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionEditorTab,
|
||||
);
|
||||
return (
|
||||
<Section>
|
||||
<H2Title
|
||||
|
||||
@ -1,12 +1,18 @@
|
||||
import { H2Title } from 'twenty-ui';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { ServerlessFunctionFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { useState } from 'react';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { SettingsServerlessFunctionNewForm } from '@/settings/serverless-functions/components/SettingsServerlessFunctionNewForm';
|
||||
import { useDeleteOneServerlessFunction } from '@/settings/serverless-functions/hooks/useDeleteOneServerlessFunction';
|
||||
import { ServerlessFunctionFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { H2Title } from 'twenty-ui';
|
||||
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
|
||||
|
||||
export const SettingsServerlessFunctionSettingsTab = ({
|
||||
formValues,
|
||||
@ -26,6 +32,26 @@ export const SettingsServerlessFunctionSettingsTab = ({
|
||||
await deleteOneServerlessFunction({ id: serverlessFunctionId });
|
||||
navigate('/settings/functions');
|
||||
};
|
||||
|
||||
useHotkeyScopeOnMount(
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionSettingsTab,
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Delete],
|
||||
() => {
|
||||
setIsDeleteFunctionModalOpen(true);
|
||||
},
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionSettingsTab,
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
() => {
|
||||
navigate(getSettingsPagePath(SettingsPath.ServerlessFunctions));
|
||||
},
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionSettingsTab,
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<SettingsServerlessFunctionNewForm
|
||||
|
||||
@ -1,16 +1,23 @@
|
||||
import { H2Title, IconPlayerPlay } from 'twenty-ui';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { H2Title, IconPlayerPlay } from 'twenty-ui';
|
||||
|
||||
import { CodeEditor } from '@/ui/input/code-editor/components/CodeEditor';
|
||||
import styled from '@emotion/styled';
|
||||
import { CoreEditorHeader } from '@/ui/input/code-editor/components/CodeEditorHeader';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { LightCopyIconButton } from '@/object-record/record-field/components/LightCopyIconButton';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { settingsServerlessFunctionOutputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionOutputState';
|
||||
import { settingsServerlessFunctionInputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionInputState';
|
||||
import { settingsServerlessFunctionCodeEditorOutputParamsState } from '@/settings/serverless-functions/states/settingsServerlessFunctionCodeEditorOutputParamsState';
|
||||
import { SettingsServerlessFunctionsOutputMetadataInfo } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsOutputMetadataInfo';
|
||||
import { settingsServerlessFunctionCodeEditorOutputParamsState } from '@/settings/serverless-functions/states/settingsServerlessFunctionCodeEditorOutputParamsState';
|
||||
import { settingsServerlessFunctionInputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionInputState';
|
||||
import { settingsServerlessFunctionOutputState } from '@/settings/serverless-functions/states/settingsServerlessFunctionOutputState';
|
||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { CodeEditor } from '@/ui/input/code-editor/components/CodeEditor';
|
||||
import { CoreEditorHeader } from '@/ui/input/code-editor/components/CodeEditorHeader';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import styled from '@emotion/styled';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
|
||||
|
||||
const StyledInputsContainer = styled.div`
|
||||
display: flex;
|
||||
@ -59,6 +66,18 @@ export const SettingsServerlessFunctionTestTab = ({
|
||||
rightNodes={[<LightCopyIconButton copyText={result} />]}
|
||||
/>
|
||||
);
|
||||
const navigate = useNavigate();
|
||||
useHotkeyScopeOnMount(
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionTestTab,
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
() => {
|
||||
navigate(getSettingsPagePath(SettingsPath.ServerlessFunctions));
|
||||
},
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionTestTab,
|
||||
);
|
||||
|
||||
return (
|
||||
<Section>
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
export enum SettingsServerlessFunctionHotkeyScope {
|
||||
ServerlessFunction = 'serverless-function',
|
||||
ServerlessFunctionNew = 'serverless-function-new',
|
||||
ServerlessFunctionDetail = 'serverless-function-detail',
|
||||
ServerlessFunctionSettingsTab = 'serverless-function-settings-tab',
|
||||
ServerlessFunctionEditorTab = 'serverless-function-editor-tab',
|
||||
ServerlessFunctionTestTab = 'serverless-function-test-tab',
|
||||
}
|
||||
@ -7,11 +7,15 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { SettingsServerlessFunctionNewForm } from '@/settings/serverless-functions/components/SettingsServerlessFunctionNewForm';
|
||||
import { useCreateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useCreateOneServerlessFunction';
|
||||
import { ServerlessFunctionNewFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { DEFAULT_CODE } from '@/ui/input/code-editor/components/CodeEditor';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useState } from 'react';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { IconFunction } from 'twenty-ui';
|
||||
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const SettingsServerlessFunctionsNew = () => {
|
||||
@ -52,6 +56,28 @@ export const SettingsServerlessFunctionsNew = () => {
|
||||
|
||||
const canSave = !!formValues.name && createOneServerlessFunction;
|
||||
|
||||
useHotkeyScopeOnMount(
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionNew,
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Enter],
|
||||
() => {
|
||||
if (canSave !== false) {
|
||||
handleSave();
|
||||
}
|
||||
},
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionNew,
|
||||
[canSave],
|
||||
);
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
() => {
|
||||
navigate(getSettingsPagePath(SettingsPath.ServerlessFunctions));
|
||||
},
|
||||
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionNew,
|
||||
);
|
||||
|
||||
return (
|
||||
<SubMenuTopBarContainer
|
||||
Icon={IconFunction}
|
||||
|
||||
Reference in New Issue
Block a user