Fix/table rerenders (#609)
* Fixed top bar rerenders * Fixed rerender on editable cell * Fix lint * asd * Fix --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -27,15 +27,15 @@ root.render(
|
|||||||
<ApolloProvider>
|
<ApolloProvider>
|
||||||
<AppThemeProvider>
|
<AppThemeProvider>
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<HotkeysProvider initiallyActiveScopes={INITIAL_HOTKEYS_SCOPES}>
|
<BrowserRouter>
|
||||||
<BrowserRouter>
|
<UserProvider>
|
||||||
<UserProvider>
|
<ClientConfigProvider>
|
||||||
<ClientConfigProvider>
|
<HotkeysProvider initiallyActiveScopes={INITIAL_HOTKEYS_SCOPES}>
|
||||||
<App />
|
<App />
|
||||||
</ClientConfigProvider>
|
</HotkeysProvider>
|
||||||
</UserProvider>
|
</ClientConfigProvider>
|
||||||
</BrowserRouter>
|
</UserProvider>
|
||||||
</HotkeysProvider>
|
</BrowserRouter>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
</AppThemeProvider>
|
</AppThemeProvider>
|
||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
|
|||||||
@ -15,5 +15,11 @@ export function useGoToHotkeys(key: Keys, location: string) {
|
|||||||
navigate(location);
|
navigate(location);
|
||||||
},
|
},
|
||||||
InternalHotkeysScope.Goto,
|
InternalHotkeysScope.Goto,
|
||||||
|
{
|
||||||
|
enableOnContentEditable: true,
|
||||||
|
enableOnFormTags: true,
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
[navigate],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export function useSequenceHotkeys(
|
|||||||
enableOnFormTags: true,
|
enableOnFormTags: true,
|
||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
},
|
},
|
||||||
|
deps: any[] = [],
|
||||||
) {
|
) {
|
||||||
const [pendingHotkey, setPendingHotkey] = useRecoilState(pendingHotkeyState);
|
const [pendingHotkey, setPendingHotkey] = useRecoilState(pendingHotkeyState);
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ export function useSequenceHotkeys(
|
|||||||
setPendingHotkey(firstKey);
|
setPendingHotkey(firstKey);
|
||||||
},
|
},
|
||||||
{ ...options, scopes: [scope] },
|
{ ...options, scopes: [scope] },
|
||||||
[pendingHotkey],
|
[setPendingHotkey],
|
||||||
);
|
);
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
@ -36,6 +37,6 @@ export function useSequenceHotkeys(
|
|||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
{ ...options, scopes: [scope] },
|
{ ...options, scopes: [scope] },
|
||||||
[pendingHotkey, setPendingHotkey],
|
[pendingHotkey, setPendingHotkey, ...deps],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,16 @@ import { DEFAULT_HOTKEYS_SCOPE_CUSTOM_SCOPES } from '../constants';
|
|||||||
import { currentHotkeysScopeState } from '../states/internal/currentHotkeysScopeState';
|
import { currentHotkeysScopeState } from '../states/internal/currentHotkeysScopeState';
|
||||||
import { CustomHotkeysScopes } from '../types/internal/CustomHotkeysScope';
|
import { CustomHotkeysScopes } from '../types/internal/CustomHotkeysScope';
|
||||||
|
|
||||||
|
function isCustomScopesEqual(
|
||||||
|
customScopesA: CustomHotkeysScopes | undefined,
|
||||||
|
customScopesB: CustomHotkeysScopes | undefined,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
customScopesA?.commandMenu === customScopesB?.commandMenu &&
|
||||||
|
customScopesA?.goto === customScopesB?.goto
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function useSetHotkeysScope() {
|
export function useSetHotkeysScope() {
|
||||||
return useRecoilCallback(
|
return useRecoilCallback(
|
||||||
({ snapshot, set }) =>
|
({ snapshot, set }) =>
|
||||||
@ -14,16 +24,6 @@ export function useSetHotkeysScope() {
|
|||||||
currentHotkeysScopeState,
|
currentHotkeysScopeState,
|
||||||
);
|
);
|
||||||
|
|
||||||
function isCustomScopesEqual(
|
|
||||||
customScopesA: CustomHotkeysScopes | undefined,
|
|
||||||
customScopesB: CustomHotkeysScopes | undefined,
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
customScopesA?.commandMenu === customScopesB?.commandMenu &&
|
|
||||||
customScopesA?.goto === customScopesB?.goto
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentHotkeysScope.scope === hotkeysScopeToSet) {
|
if (currentHotkeysScope.scope === hotkeysScopeToSet) {
|
||||||
if (!isDefined(customScopes)) {
|
if (!isDefined(customScopes)) {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -2,12 +2,9 @@ import { ReactElement } from 'react';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { HotkeysScope } from '@/hotkeys/types/internal/HotkeysScope';
|
import { HotkeysScope } from '@/hotkeys/types/internal/HotkeysScope';
|
||||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
|
||||||
|
|
||||||
import { useCurrentCellEditMode } from './hooks/useCurrentCellEditMode';
|
import { useCurrentCellEditMode } from './hooks/useCurrentCellEditMode';
|
||||||
import { useEditableCell } from './hooks/useEditableCell';
|
|
||||||
import { useIsSoftFocusOnCurrentCell } from './hooks/useIsSoftFocusOnCurrentCell';
|
import { useIsSoftFocusOnCurrentCell } from './hooks/useIsSoftFocusOnCurrentCell';
|
||||||
import { useSetSoftFocusOnCurrentCell } from './hooks/useSetSoftFocusOnCurrentCell';
|
|
||||||
import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
||||||
import { EditableCellEditMode } from './EditableCellEditMode';
|
import { EditableCellEditMode } from './EditableCellEditMode';
|
||||||
import { EditableCellSoftFocusMode } from './EditableCellSoftFocusMode';
|
import { EditableCellSoftFocusMode } from './EditableCellSoftFocusMode';
|
||||||
@ -40,33 +37,10 @@ export function EditableCell({
|
|||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||||
|
|
||||||
const setSoftFocusOnCurrentCell = useSetSoftFocusOnCurrentCell();
|
|
||||||
|
|
||||||
const { openEditableCell } = useEditableCell();
|
|
||||||
|
|
||||||
const hasSoftFocus = useIsSoftFocusOnCurrentCell();
|
const hasSoftFocus = useIsSoftFocusOnCurrentCell();
|
||||||
|
|
||||||
// TODO: we might have silent problematic behavior because of the setTimeout in openEditableCell, investigate
|
|
||||||
// Maybe we could build a switchEditableCell to handle the case where we go from one cell to another.
|
|
||||||
// See https://github.com/twentyhq/twenty/issues/446
|
|
||||||
function handleOnClick() {
|
|
||||||
if (isCurrentCellInEditMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasSoftFocus) {
|
|
||||||
openEditableCell(
|
|
||||||
editHotkeysScope ?? {
|
|
||||||
scope: InternalHotkeysScope.CellEditMode,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
setSoftFocusOnCurrentCell();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CellBaseContainer onClick={handleOnClick}>
|
<CellBaseContainer>
|
||||||
{isCurrentCellInEditMode ? (
|
{isCurrentCellInEditMode ? (
|
||||||
<EditableCellEditMode
|
<EditableCellEditMode
|
||||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { useIsSoftFocusOnCurrentCell } from './hooks/useIsSoftFocusOnCurrentCell';
|
import { useSetSoftFocusOnCurrentCell } from './hooks/useSetSoftFocusOnCurrentCell';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
softFocus: boolean;
|
softFocus?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EditableCellNormalModeOuterContainer = styled.div<Props>`
|
export const EditableCellNormalModeOuterContainer = styled.div<Props>`
|
||||||
@ -35,10 +35,14 @@ export const EditableCellNormalModeInnerContainer = styled.div`
|
|||||||
export function EditableCellDisplayMode({
|
export function EditableCellDisplayMode({
|
||||||
children,
|
children,
|
||||||
}: React.PropsWithChildren<unknown>) {
|
}: React.PropsWithChildren<unknown>) {
|
||||||
const hasSoftFocus = useIsSoftFocusOnCurrentCell();
|
const setSoftFocusOnCurrentCell = useSetSoftFocusOnCurrentCell();
|
||||||
|
|
||||||
|
function handleOnClick() {
|
||||||
|
setSoftFocusOnCurrentCell();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableCellNormalModeOuterContainer softFocus={hasSoftFocus}>
|
<EditableCellNormalModeOuterContainer onClick={handleOnClick}>
|
||||||
<EditableCellNormalModeInnerContainer>
|
<EditableCellNormalModeInnerContainer>
|
||||||
{children}
|
{children}
|
||||||
</EditableCellNormalModeInnerContainer>
|
</EditableCellNormalModeInnerContainer>
|
||||||
|
|||||||
@ -6,25 +6,32 @@ import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysSc
|
|||||||
import { isNonTextWritingKey } from '@/utils/hotkeys/isNonTextWritingKey';
|
import { isNonTextWritingKey } from '@/utils/hotkeys/isNonTextWritingKey';
|
||||||
|
|
||||||
import { useEditableCell } from './hooks/useEditableCell';
|
import { useEditableCell } from './hooks/useEditableCell';
|
||||||
import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
import {
|
||||||
|
EditableCellNormalModeInnerContainer,
|
||||||
|
EditableCellNormalModeOuterContainer,
|
||||||
|
} from './EditableCellDisplayMode';
|
||||||
|
|
||||||
export function EditableCellSoftFocusMode({
|
export function EditableCellSoftFocusMode({
|
||||||
children,
|
children,
|
||||||
editHotkeysScope,
|
editHotkeysScope,
|
||||||
}: React.PropsWithChildren<{ editHotkeysScope?: HotkeysScope }>) {
|
}: React.PropsWithChildren<{ editHotkeysScope?: HotkeysScope }>) {
|
||||||
const { closeEditableCell, openEditableCell } = useEditableCell();
|
const { openEditableCell } = useEditableCell();
|
||||||
|
|
||||||
|
function openEditMode() {
|
||||||
|
openEditableCell(
|
||||||
|
editHotkeysScope ?? {
|
||||||
|
scope: InternalHotkeysScope.CellEditMode,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
'enter',
|
'enter',
|
||||||
() => {
|
() => {
|
||||||
openEditableCell(
|
openEditMode();
|
||||||
editHotkeysScope ?? {
|
|
||||||
scope: InternalHotkeysScope.CellEditMode,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
InternalHotkeysScope.TableSoftFocus,
|
InternalHotkeysScope.TableSoftFocus,
|
||||||
[closeEditableCell, editHotkeysScope],
|
[openEditMode],
|
||||||
);
|
);
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
@ -39,18 +46,27 @@ export function EditableCellSoftFocusMode({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
openEditableCell(
|
openEditMode();
|
||||||
editHotkeysScope ?? {
|
|
||||||
scope: InternalHotkeysScope.CellEditMode,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
InternalHotkeysScope.TableSoftFocus,
|
InternalHotkeysScope.TableSoftFocus,
|
||||||
[openEditableCell, editHotkeysScope],
|
[openEditMode],
|
||||||
{
|
{
|
||||||
preventDefault: false,
|
preventDefault: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return <EditableCellDisplayMode>{children}</EditableCellDisplayMode>;
|
function handleClick() {
|
||||||
|
openEditMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EditableCellNormalModeOuterContainer
|
||||||
|
onClick={handleClick}
|
||||||
|
softFocus={true}
|
||||||
|
>
|
||||||
|
<EditableCellNormalModeInnerContainer>
|
||||||
|
{children}
|
||||||
|
</EditableCellNormalModeInnerContainer>
|
||||||
|
</EditableCellNormalModeOuterContainer>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
||||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||||
@ -14,6 +14,7 @@ import { CellPosition } from '@/ui/tables/types/CellPosition';
|
|||||||
|
|
||||||
export function useSetSoftFocusOnCurrentCell() {
|
export function useSetSoftFocusOnCurrentCell() {
|
||||||
const setSoftFocusPosition = useSetSoftFocusPosition();
|
const setSoftFocusPosition = useSetSoftFocusPosition();
|
||||||
|
|
||||||
const [currentRowNumber] = useRecoilScopedState(
|
const [currentRowNumber] = useRecoilScopedState(
|
||||||
currentRowNumberScopedState,
|
currentRowNumberScopedState,
|
||||||
RowContext,
|
RowContext,
|
||||||
@ -32,18 +33,17 @@ export function useSetSoftFocusOnCurrentCell() {
|
|||||||
[currentColumnNumber, currentRowNumber],
|
[currentColumnNumber, currentRowNumber],
|
||||||
);
|
);
|
||||||
|
|
||||||
const [, setIsSoftFocusActive] = useRecoilState(isSoftFocusActiveState);
|
|
||||||
|
|
||||||
const setHotkeysScope = useSetHotkeysScope();
|
const setHotkeysScope = useSetHotkeysScope();
|
||||||
|
|
||||||
return useCallback(() => {
|
return useRecoilCallback(
|
||||||
setSoftFocusPosition(currentTablePosition);
|
({ set }) =>
|
||||||
setIsSoftFocusActive(true);
|
() => {
|
||||||
setHotkeysScope(InternalHotkeysScope.TableSoftFocus);
|
setSoftFocusPosition(currentTablePosition);
|
||||||
}, [
|
|
||||||
setSoftFocusPosition,
|
set(isSoftFocusActiveState, true);
|
||||||
currentTablePosition,
|
|
||||||
setIsSoftFocusActive,
|
setHotkeysScope(InternalHotkeysScope.TableSoftFocus);
|
||||||
setHotkeysScope,
|
},
|
||||||
]);
|
[setHotkeysScope, currentTablePosition, setSoftFocusPosition],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
export const FlexExpandingContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { ContentContainer } from './ContentContainer';
|
import { RightDrawerContainer } from './RightDrawerContainer';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
children: JSX.Element;
|
children: JSX.Element | JSX.Element[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
@ -15,7 +15,7 @@ const StyledContainer = styled.div`
|
|||||||
export function NoTopBarContainer({ children }: OwnProps) {
|
export function NoTopBarContainer({ children }: OwnProps) {
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<ContentContainer topMargin={16}>{children}</ContentContainer>
|
<RightDrawerContainer topMargin={16}>{children}</RightDrawerContainer>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,43 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { Panel } from '../Panel';
|
||||||
|
import { RightDrawer } from '../right-drawer/components/RightDrawer';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
children: JSX.Element | JSX.Element[];
|
||||||
|
topMargin?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledMainContainer = styled.div<{ topMargin: number }>`
|
||||||
|
background: ${({ theme }) => theme.background.noisy};
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
flex-direction: row;
|
||||||
|
gap: ${({ theme }) => theme.spacing(2)};
|
||||||
|
height: calc(100% - ${(props) => props.topMargin}px);
|
||||||
|
|
||||||
|
padding-bottom: ${({ theme }) => theme.spacing(3)};
|
||||||
|
padding-right: ${({ theme }) => theme.spacing(3)};
|
||||||
|
width: calc(100% - ${({ theme }) => theme.spacing(3)});
|
||||||
|
`;
|
||||||
|
|
||||||
|
type LeftContainerProps = {
|
||||||
|
isRightDrawerOpen?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledLeftContainer = styled.div<LeftContainerProps>`
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function RightDrawerContainer({ children, topMargin }: OwnProps) {
|
||||||
|
return (
|
||||||
|
<StyledMainContainer topMargin={topMargin ?? 0}>
|
||||||
|
<StyledLeftContainer>
|
||||||
|
<Panel>{children}</Panel>
|
||||||
|
</StyledLeftContainer>
|
||||||
|
<RightDrawer />
|
||||||
|
</StyledMainContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
const StyledContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function VerticalFullWidthContainer({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: JSX.Element[];
|
||||||
|
}) {
|
||||||
|
return <StyledContainer>{children}</StyledContainer>;
|
||||||
|
}
|
||||||
@ -1,12 +1,13 @@
|
|||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { TopBarHotkeys } from '../top-bar/TableTopBarHotkeys';
|
||||||
import { TOP_BAR_MIN_HEIGHT, TopBar } from '../top-bar/TopBar';
|
import { TOP_BAR_MIN_HEIGHT, TopBar } from '../top-bar/TopBar';
|
||||||
|
|
||||||
import { ContentContainer } from './ContentContainer';
|
import { RightDrawerContainer } from './RightDrawerContainer';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
children: JSX.Element;
|
children: JSX.Element | JSX.Element[];
|
||||||
title: string;
|
title: string;
|
||||||
icon: ReactNode;
|
icon: ReactNode;
|
||||||
onAddButtonClick?: () => void;
|
onAddButtonClick?: () => void;
|
||||||
@ -26,10 +27,11 @@ export function WithTopBarContainer({
|
|||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
|
<TopBarHotkeys onAddButtonClick={onAddButtonClick} />
|
||||||
<TopBar title={title} icon={icon} onAddButtonClick={onAddButtonClick} />
|
<TopBar title={title} icon={icon} onAddButtonClick={onAddButtonClick} />
|
||||||
<ContentContainer topMargin={TOP_BAR_MIN_HEIGHT + 16 + 16}>
|
<RightDrawerContainer topMargin={TOP_BAR_MIN_HEIGHT + 16 + 16}>
|
||||||
{children}
|
{children}
|
||||||
</ContentContainer>
|
</RightDrawerContainer>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
17
front/src/modules/ui/layout/top-bar/TableTopBarHotkeys.tsx
Normal file
17
front/src/modules/ui/layout/top-bar/TableTopBarHotkeys.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
||||||
|
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
onAddButtonClick?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function TopBarHotkeys({ onAddButtonClick }: OwnProps) {
|
||||||
|
useScopedHotkeys(
|
||||||
|
'c',
|
||||||
|
() => onAddButtonClick?.(),
|
||||||
|
InternalHotkeysScope.Table,
|
||||||
|
[onAddButtonClick],
|
||||||
|
);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
@ -1,8 +1,6 @@
|
|||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
|
||||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
|
||||||
import { IconPlus } from '@/ui/icons/index';
|
import { IconPlus } from '@/ui/icons/index';
|
||||||
|
|
||||||
import NavCollapseButton from '../navbar/NavCollapseButton';
|
import NavCollapseButton from '../navbar/NavCollapseButton';
|
||||||
@ -51,8 +49,6 @@ type OwnProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function TopBar({ title, icon, onAddButtonClick }: OwnProps) {
|
export function TopBar({ title, icon, onAddButtonClick }: OwnProps) {
|
||||||
useScopedHotkeys('c', () => onAddButtonClick?.(), InternalHotkeysScope.Table);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TopBarContainer>
|
<TopBarContainer>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
||||||
import { currentHotkeysScopeState } from '@/hotkeys/states/internal/currentHotkeysScopeState';
|
import { currentHotkeysScopeState } from '@/hotkeys/states/internal/currentHotkeysScopeState';
|
||||||
@ -11,29 +11,39 @@ import { useCloseCurrentCellInEditMode } from './useClearCellInEditMode';
|
|||||||
import { useDisableSoftFocus } from './useDisableSoftFocus';
|
import { useDisableSoftFocus } from './useDisableSoftFocus';
|
||||||
|
|
||||||
export function useLeaveTableFocus() {
|
export function useLeaveTableFocus() {
|
||||||
const currentHotkeysScope = useRecoilValue(currentHotkeysScopeState);
|
|
||||||
|
|
||||||
const disableSoftFocus = useDisableSoftFocus();
|
const disableSoftFocus = useDisableSoftFocus();
|
||||||
const closeCurrentCellInEditMode = useCloseCurrentCellInEditMode();
|
const closeCurrentCellInEditMode = useCloseCurrentCellInEditMode();
|
||||||
|
|
||||||
const setHotkeysScope = useSetHotkeysScope();
|
const setHotkeysScope = useSetHotkeysScope();
|
||||||
|
|
||||||
const isSoftFocusActive = useRecoilValue(isSoftFocusActiveState);
|
return useRecoilCallback(
|
||||||
const isSomeInputInEditMode = useRecoilValue(isSomeInputInEditModeState);
|
({ snapshot }) =>
|
||||||
|
() => {
|
||||||
|
const isSoftFocusActive = snapshot
|
||||||
|
.getLoadable(isSoftFocusActiveState)
|
||||||
|
.valueOrThrow();
|
||||||
|
|
||||||
return async function leaveTableFocus() {
|
const isSomeInputInEditMode = snapshot
|
||||||
// TODO: replace with scope ancestor ?
|
.getLoadable(isSomeInputInEditModeState)
|
||||||
if (!isSoftFocusActive && !isSomeInputInEditMode) {
|
.valueOrThrow();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentHotkeysScope?.scope === InternalHotkeysScope.Table) {
|
const currentHotkeysScope = snapshot
|
||||||
return;
|
.getLoadable(currentHotkeysScopeState)
|
||||||
}
|
.valueOrThrow();
|
||||||
|
|
||||||
closeCurrentCellInEditMode();
|
if (!isSoftFocusActive && !isSomeInputInEditMode) {
|
||||||
disableSoftFocus();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setHotkeysScope(InternalHotkeysScope.Table, { goto: true });
|
if (currentHotkeysScope?.scope === InternalHotkeysScope.Table) {
|
||||||
};
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeCurrentCellInEditMode();
|
||||||
|
disableSoftFocus();
|
||||||
|
|
||||||
|
setHotkeysScope(InternalHotkeysScope.Table, { goto: true });
|
||||||
|
},
|
||||||
|
[setHotkeysScope, closeCurrentCellInEditMode, disableSoftFocus],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { getOperationName } from '@apollo/client/utilities';
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import { GET_PEOPLE } from '@/people/services';
|
import { GET_PEOPLE } from '@/people/services';
|
||||||
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
|
||||||
import { EntityTableActionBar } from '@/ui/components/table/action-bar/EntityTableActionBar';
|
import { EntityTableActionBar } from '@/ui/components/table/action-bar/EntityTableActionBar';
|
||||||
import { IconUser } from '@/ui/icons/index';
|
import { IconBuildingSkyscraper } from '@/ui/icons/index';
|
||||||
|
import { FlexExpandingContainer } from '@/ui/layout/containers/FlexExpandingContainer';
|
||||||
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
||||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
import { TableContext } from '@/ui/tables/states/TableContext';
|
||||||
import { useInsertPersonMutation } from '~/generated/graphql';
|
import { useInsertPersonMutation } from '~/generated/graphql';
|
||||||
@ -15,12 +15,6 @@ import { TableActionBarButtonCreateCommentThreadPeople } from './table/TableActi
|
|||||||
import { TableActionBarButtonDeletePeople } from './table/TableActionBarButtonDeletePeople';
|
import { TableActionBarButtonDeletePeople } from './table/TableActionBarButtonDeletePeople';
|
||||||
import { PeopleTable } from './PeopleTable';
|
import { PeopleTable } from './PeopleTable';
|
||||||
|
|
||||||
const StyledPeopleContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export function People() {
|
export function People() {
|
||||||
const [insertPersonMutation] = useInsertPersonMutation();
|
const [insertPersonMutation] = useInsertPersonMutation();
|
||||||
|
|
||||||
@ -42,20 +36,20 @@ export function People() {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithTopBarContainer
|
<RecoilScope SpecificContext={TableContext}>
|
||||||
title="People"
|
<WithTopBarContainer
|
||||||
icon={<IconUser size={theme.icon.size.md} />}
|
title="Companies"
|
||||||
onAddButtonClick={handleAddButtonClick}
|
icon={<IconBuildingSkyscraper size={theme.icon.size.md} />}
|
||||||
>
|
onAddButtonClick={handleAddButtonClick}
|
||||||
<RecoilScope SpecificContext={TableContext}>
|
>
|
||||||
<StyledPeopleContainer>
|
<FlexExpandingContainer>
|
||||||
<PeopleTable />
|
<PeopleTable />
|
||||||
</StyledPeopleContainer>
|
</FlexExpandingContainer>
|
||||||
<EntityTableActionBar>
|
<EntityTableActionBar>
|
||||||
<TableActionBarButtonCreateCommentThreadPeople />
|
<TableActionBarButtonCreateCommentThreadPeople />
|
||||||
<TableActionBarButtonDeletePeople />
|
<TableActionBarButtonDeletePeople />
|
||||||
</EntityTableActionBar>
|
</EntityTableActionBar>
|
||||||
</RecoilScope>
|
</WithTopBarContainer>
|
||||||
</WithTopBarContainer>
|
</RecoilScope>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user