Refactor/context and scopes (#1602)

* Put onImport in a context

* Refactored RecoilScopeContexts

* Refactored naming

* Fix tests

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2023-09-15 21:51:46 +02:00
committed by GitHub
parent d07474ece7
commit 0a7a0ac6cb
102 changed files with 639 additions and 552 deletions

View File

@ -16,7 +16,7 @@ type OwnProps = {
export function ActivityAssigneeEditableField({ activity }: OwnProps) {
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<RecoilScope>
<EditableField
customEditHotkeyScope={{

View File

@ -21,7 +21,7 @@ type OwnProps = {
export function ActivityRelationEditableField({ activity }: OwnProps) {
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<RecoilScope>
<EditableField
useEditButton

View File

@ -12,7 +12,7 @@ const meta: Meta<typeof TaskGroups> = {
decorators: [ComponentWithRouterDecorator, ComponentWithRecoilScopeDecorator],
parameters: {
msw: graphqlMocks,
recoilScopeContext: TasksRecoilScopeContext,
customRecoilScopeContext: TasksRecoilScopeContext,
},
};

View File

@ -15,7 +15,7 @@ const meta: Meta<typeof TaskGroups> = {
decorators: [ComponentWithRouterDecorator, ComponentWithRecoilScopeDecorator],
parameters: {
msw: graphqlMocks,
recoilScopeContext: TasksRecoilScopeContext,
customRecoilScopeContext: TasksRecoilScopeContext,
},
};

View File

@ -16,7 +16,7 @@ const StyledContainer = styled.div`
export function EntityTasks({ entity }: { entity: ActivityTargetableEntity }) {
return (
<StyledContainer>
<RecoilScope SpecificContext={TasksRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={TasksRecoilScopeContext}>
<TaskGroups entity={entity} showAddButton />
</RecoilScope>
</StyledContainer>

View File

@ -27,7 +27,7 @@ export function PageAddTaskButton() {
}
return (
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageAddButton onClick={handleClick} />
</RecoilScope>
);

View File

@ -14,7 +14,7 @@ const meta: Meta<typeof CompanyBoard> = {
component: CompanyBoard,
decorators: [
(Story) => (
<RecoilScope SpecificContext={CompanyBoardRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={CompanyBoardRecoilScopeContext}>
<HooksCompanyBoardEffect />
<MemoryRouter>
<Story />

View File

@ -15,6 +15,7 @@ import { graphqlMocks } from '~/testing/graphqlMocks';
import { mockedPipelineProgressData } from '~/testing/mock-data/pipeline-progress';
import { HooksCompanyBoardEffect } from '../components/HooksCompanyBoardEffect';
import { BoardContext } from '../states/contexts/BoardContext';
import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
const meta: Meta<typeof CompanyBoardCard> = {
@ -24,7 +25,7 @@ const meta: Meta<typeof CompanyBoardCard> = {
(Story, context) => {
const [, setBoardCardFields] = useRecoilScopedState(
boardCardFieldsScopedState,
context.parameters.recoilScopeContext,
context.parameters.customRecoilScopeContext,
);
useEffect(() => {
@ -32,9 +33,14 @@ const meta: Meta<typeof CompanyBoardCard> = {
}, [setBoardCardFields]);
return (
<>
<HooksCompanyBoardEffect />
<RecoilScope SpecificContext={BoardColumnRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={BoardColumnRecoilScopeContext}>
<BoardContext.Provider
value={{
BoardRecoilScopeContext:
context.parameters.customRecoilScopeContext,
}}
>
<HooksCompanyBoardEffect />
<BoardCardIdContext.Provider
value={mockedPipelineProgressData[1].id}
>
@ -42,18 +48,18 @@ const meta: Meta<typeof CompanyBoardCard> = {
<Story />
</MemoryRouter>
</BoardCardIdContext.Provider>
</RecoilScope>
</>
</BoardContext.Provider>
</RecoilScope>
);
},
ComponentWithRecoilScopeDecorator,
ComponentDecorator,
],
args: { scopeContext: CompanyBoardRecoilScopeContext },
argTypes: { scopeContext: { control: false } },
args: {},
argTypes: {},
parameters: {
msw: graphqlMocks,
recoilScopeContext: CompanyBoardRecoilScopeContext,
customRecoilScopeContext: CompanyBoardRecoilScopeContext,
},
};

View File

@ -1,3 +1,4 @@
import { BoardContext } from '@/companies/states/contexts/BoardContext';
import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions';
import {
EntityBoard,
@ -22,35 +23,43 @@ export const CompanyBoard = ({
onColumnDelete,
onEditColumnTitle,
}: CompanyBoardProps) => {
// TODO: we can store objectId and fieldDefinitions in the ViewBarContext
// And then use the useBoardViews hook wherever we need it in the board
const { createView, deleteView, submitCurrentView, updateView } =
useBoardViews({
objectId: 'company',
scopeContext: CompanyBoardRecoilScopeContext,
RecoilScopeContext: CompanyBoardRecoilScopeContext,
fieldDefinitions: pipelineAvailableFieldDefinitions,
});
return (
<>
<HooksCompanyBoardEffect />
<ViewBarContext.Provider
<BoardContext.Provider
value={{
defaultViewName: 'All Opportunities',
onCurrentViewSubmit: submitCurrentView,
onViewCreate: createView,
onViewEdit: updateView,
onViewRemove: deleteView,
BoardRecoilScopeContext: CompanyBoardRecoilScopeContext,
}}
>
<EntityBoard
boardOptions={opportunitiesBoardOptions}
onColumnAdd={onColumnAdd}
onColumnDelete={onColumnDelete}
onEditColumnTitle={onEditColumnTitle}
scopeContext={CompanyBoardRecoilScopeContext}
/>
</ViewBarContext.Provider>
<EntityBoardActionBar />
<EntityBoardContextMenu />
<HooksCompanyBoardEffect />
<ViewBarContext.Provider
value={{
defaultViewName: 'All Opportunities',
onCurrentViewSubmit: submitCurrentView,
onViewCreate: createView,
onViewEdit: updateView,
onViewRemove: deleteView,
ViewBarRecoilScopeContext: CompanyBoardRecoilScopeContext,
}}
>
<EntityBoard
boardOptions={opportunitiesBoardOptions}
onColumnAdd={onColumnAdd}
onColumnDelete={onColumnDelete}
onEditColumnTitle={onEditColumnTitle}
/>
</ViewBarContext.Provider>
<EntityBoardActionBar />
<EntityBoardContextMenu />
</BoardContext.Provider>
</>
);
};

View File

@ -1,8 +1,9 @@
import { type Context, type ReactNode, useContext } from 'react';
import { type ReactNode, useContext } from 'react';
import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
import { BoardCardIdContext } from '@/ui/board/contexts/BoardCardIdContext';
import { useBoardContext } from '@/ui/board/hooks/useBoardContext';
import { useCurrentCardSelected } from '@/ui/board/hooks/useCurrentCardSelected';
import { visibleBoardCardFieldsScopedSelector } from '@/ui/board/states/selectors/visibleBoardCardFieldsScopedSelector';
import { EntityChipVariant } from '@/ui/chip/components/EntityChip';
@ -19,10 +20,6 @@ import { companyProgressesFamilyState } from '../states/companyProgressesFamilyS
import { CompanyChip } from './CompanyChip';
type OwnProps = {
scopeContext: Context<string | null>;
};
const StyledBoardCard = styled.div<{ selected: boolean }>`
background-color: ${({ theme, selected }) =>
selected ? theme.accent.quaternary : theme.background.secondary};
@ -103,7 +100,9 @@ const StyledFieldContainer = styled.div`
width: 100%;
`;
export function CompanyBoardCard({ scopeContext }: OwnProps) {
export function CompanyBoardCard() {
const { BoardRecoilScopeContext } = useBoardContext();
const { currentCardSelected, setCurrentCardSelected } =
useCurrentCardSelected();
const boardCardId = useContext(BoardCardIdContext);
@ -115,7 +114,7 @@ export function CompanyBoardCard({ scopeContext }: OwnProps) {
const visibleBoardCardFields = useRecoilScopedValue(
visibleBoardCardFieldsScopedSelector,
scopeContext,
BoardRecoilScopeContext,
);
// boardCardId check can be moved to a wrapper to avoid unnecessary logic above

View File

@ -1,26 +1,23 @@
import { Context } from 'react';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { FilterDropdownEntitySearchSelect } from '@/ui/view-bar/components/FilterDropdownEntitySearchSelect';
import { useViewBarContext } from '@/ui/view-bar/hooks/useViewBarContext';
import { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filterDropdownSearchInputScopedState';
import { filterDropdownSelectedEntityIdScopedState } from '@/ui/view-bar/states/filterDropdownSelectedEntityIdScopedState';
import { useFilteredSearchCompanyQuery } from '../hooks/useFilteredSearchCompanyQuery';
export function FilterDropdownCompanySearchSelect({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownCompanySearchSelect() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const filterDropdownSearchInput = useRecoilScopedValue(
filterDropdownSearchInputScopedState,
context,
ViewBarRecoilScopeContext,
);
const [filterDropdownSelectedEntityId] = useRecoilScopedState(
filterDropdownSelectedEntityIdScopedState,
context,
ViewBarRecoilScopeContext,
);
const usersForSelect = useFilteredSearchCompanyQuery({
@ -31,9 +28,6 @@ export function FilterDropdownCompanySearchSelect({
});
return (
<FilterDropdownEntitySearchSelect
entitiesForSelect={usersForSelect}
context={context}
/>
<FilterDropdownEntitySearchSelect entitiesForSelect={usersForSelect} />
);
}

View File

@ -60,7 +60,7 @@ export function CompanyNameEditableField({ company }: OwnProps) {
}
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<StyledEditableTitleInput
autoComplete="off"
onChange={(event) => handleChange(event.target.value)}

View File

@ -0,0 +1,9 @@
import { createContext } from 'react';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
export const BoardContext = createContext<{
BoardRecoilScopeContext: RecoilScopeContext;
}>({
BoardRecoilScopeContext: createContext<string | null>(null),
});

View File

@ -0,0 +1,5 @@
import { createContext } from 'react';
export const CompanyBoardViewBarRecoilScopeContext = createContext<
string | null
>(null);

View File

@ -44,10 +44,6 @@ export function CompanyTable() {
const { setContextMenuEntries } = useCompanyTableContextMenuEntries();
const { setActionBarEntries } = useCompanyTableActionBarEntries();
function handleImport() {
openCompanySpreadsheetImport();
}
return (
<>
<EntityTableEffect
@ -70,10 +66,11 @@ export function CompanyTable() {
onViewCreate: createView,
onViewEdit: updateView,
onViewRemove: deleteView,
onImport: openCompanySpreadsheetImport,
ViewBarRecoilScopeContext: TableRecoilScopeContext,
}}
>
<EntityTable
onImport={handleImport}
updateEntityMutation={({
variables,
}: {

View File

@ -1,4 +1,5 @@
import { EntityTable } from '@/ui/table/components/EntityTable';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { useUpdateOneCompanyMutation } from '~/generated/graphql';
@ -8,7 +9,12 @@ export function CompanyTableMockMode() {
return (
<>
<CompanyTableMockDataEffect />
<ViewBarContext.Provider value={{ defaultViewName: 'All Companies' }}>
<ViewBarContext.Provider
value={{
defaultViewName: 'All Companies',
ViewBarRecoilScopeContext: TableRecoilScopeContext,
}}
>
<EntityTable updateEntityMutation={[useUpdateOneCompanyMutation()]} />
</ViewBarContext.Provider>
</>

View File

@ -1,25 +1,22 @@
import { Context } from 'react';
import { useFilteredSearchPeopleQuery } from '@/people/hooks/useFilteredSearchPeopleQuery';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { FilterDropdownEntitySearchSelect } from '@/ui/view-bar/components/FilterDropdownEntitySearchSelect';
import { useViewBarContext } from '@/ui/view-bar/hooks/useViewBarContext';
import { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filterDropdownSearchInputScopedState';
import { filterDropdownSelectedEntityIdScopedState } from '@/ui/view-bar/states/filterDropdownSelectedEntityIdScopedState';
export function FilterDropdownPeopleSearchSelect({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownPeopleSearchSelect() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const filterDropdownSearchInput = useRecoilScopedValue(
filterDropdownSearchInputScopedState,
context,
ViewBarRecoilScopeContext,
);
const [filterDropdownSelectedEntityId] = useRecoilScopedState(
filterDropdownSelectedEntityIdScopedState,
context,
ViewBarRecoilScopeContext,
);
const peopleForSelect = useFilteredSearchPeopleQuery({
@ -30,9 +27,6 @@ export function FilterDropdownPeopleSearchSelect({
});
return (
<FilterDropdownEntitySearchSelect
entitiesForSelect={peopleForSelect}
context={context}
/>
<FilterDropdownEntitySearchSelect entitiesForSelect={peopleForSelect} />
);
}

View File

@ -46,7 +46,7 @@ export function PeopleFullNameEditableField({ people }: OwnProps) {
}
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<DoubleTextInputEdit
firstValuePlaceholder="Empty"
secondValuePlaceholder="Empty"

View File

@ -7,7 +7,7 @@ import { numberOfTableRowsState } from '@/ui/table/states/numberOfTableRowsState
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState';
import { currentPageLocationState } from '@/ui/utilities/loading-state/states/currentPageLocationState';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { availableFiltersScopedState } from '@/ui/view-bar/states/availableFiltersScopedState';
import { GetPeopleQuery } from '~/generated/graphql';
import { peopleFilters } from '~/pages/people/people-filters';
@ -24,7 +24,7 @@ import { peoplePhoneFamilyState } from '../states/peoplePhoneFamilyState';
export function useSetPeopleEntityTable() {
const resetTableRowSelection = useResetTableRowSelection();
const tableContextScopeId = useContextScopeId(TableRecoilScopeContext);
const tableContextScopeId = useRecoilScopeId(TableRecoilScopeContext);
const currentLocation = useLocation().pathname;

View File

@ -69,10 +69,11 @@ export function PeopleTable() {
onViewCreate: createView,
onViewEdit: updateView,
onViewRemove: deleteView,
onImport: handleImport,
ViewBarRecoilScopeContext: TableRecoilScopeContext,
}}
>
<EntityTable
onImport={handleImport}
updateEntityMutation={({
variables,
}: {

View File

@ -0,0 +1,3 @@
import { Context } from 'react';
export type RecoilScopeContext = Context<string | null>;

View File

@ -24,7 +24,7 @@ const meta: Meta<typeof ActionBar> = {
component: FilledActionBar,
decorators: [
(Story) => (
<RecoilScope SpecificContext={TableRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={TableRecoilScopeContext}>
<CompanyTableMockMode />
<MemoryRouter>
<Story />

View File

@ -1,12 +1,13 @@
import { useContext } from 'react';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { BoardContext } from '@/companies/states/contexts/BoardContext';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { ViewBar, type ViewBarProps } from '@/ui/view-bar/components/ViewBar';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBar } from '@/ui/view-bar/components/ViewBar';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
@ -22,30 +23,33 @@ import { BoardOptionsDropdown } from './BoardOptionsDropdown';
export type BoardHeaderProps = {
className?: string;
onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
} & Pick<ViewBarProps, 'scopeContext'>;
};
export function BoardHeader({
className,
onStageAdd,
scopeContext,
}: BoardHeaderProps) {
export function BoardHeader({ className, onStageAdd }: BoardHeaderProps) {
const { onCurrentViewSubmit, ...viewBarContextProps } =
useContext(ViewBarContext);
const tableScopeId = useContextScopeId(scopeContext);
const BoardRecoilScopeContext =
useContext(BoardContext).BoardRecoilScopeContext;
const ViewBarRecoilScopeContext =
useContext(ViewBarContext).ViewBarRecoilScopeContext;
const boardRecoilScopeId = useRecoilScopeId(BoardRecoilScopeContext);
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
scopeContext,
ViewBarRecoilScopeContext,
);
const canPersistBoardCardFields = useRecoilValue(
canPersistBoardCardFieldsScopedFamilySelector([
tableScopeId,
currentViewId,
]),
canPersistBoardCardFieldsScopedFamilySelector({
recoilScopeId: boardRecoilScopeId,
viewId: currentViewId,
}),
);
const [boardCardFields, setBoardCardFields] = useRecoilScopedState(
boardCardFieldsScopedState,
scopeContext,
BoardRecoilScopeContext,
);
const [savedBoardCardFields, setSavedBoardCardFields] = useRecoilState(
savedBoardCardFieldsFamilyState(currentViewId),
@ -59,9 +63,12 @@ export function BoardHeader({
const savedBoardCardFields = await snapshot.getPromise(
savedBoardCardFieldsFamilyState(viewId),
);
set(boardCardFieldsScopedState(tableScopeId), savedBoardCardFields);
set(
boardCardFieldsScopedState(boardRecoilScopeId),
savedBoardCardFields,
);
},
[tableScopeId],
[boardRecoilScopeId],
);
const handleCurrentViewSubmit = async () => {
@ -73,7 +80,7 @@ export function BoardHeader({
};
return (
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<ViewBarContext.Provider
value={{
...viewBarContextProps,
@ -89,11 +96,9 @@ export function BoardHeader({
<BoardOptionsDropdown
customHotkeyScope={{ scope: BoardOptionsHotkeyScope.Dropdown }}
onStageAdd={onStageAdd}
scopeContext={scopeContext}
/>
}
optionsDropdownKey={BoardOptionsDropdownKey}
scopeContext={scopeContext}
/>
</ViewBarContext.Provider>
</RecoilScope>

View File

@ -10,13 +10,12 @@ import {
type BoardOptionsDropdownProps = Pick<
BoardOptionsDropdownContentProps,
'customHotkeyScope' | 'onStageAdd' | 'scopeContext'
'customHotkeyScope' | 'onStageAdd'
>;
export function BoardOptionsDropdown({
customHotkeyScope,
onStageAdd,
scopeContext,
}: BoardOptionsDropdownProps) {
return (
<DropdownButton
@ -25,7 +24,6 @@ export function BoardOptionsDropdown({
<BoardOptionsDropdownContent
customHotkeyScope={customHotkeyScope}
onStageAdd={onStageAdd}
scopeContext={scopeContext}
/>
}
dropdownHotkeyScope={customHotkeyScope}

View File

@ -1,10 +1,11 @@
import { type Context, useRef, useState } from 'react';
import { useContext, useRef, useState } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
import { v4 } from 'uuid';
import { BoardContext } from '@/companies/states/contexts/BoardContext';
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
@ -23,8 +24,8 @@ import { MenuItemNavigate } from '@/ui/menu-item/components/MenuItemNavigate';
import { ThemeColor } from '@/ui/theme/constants/colors';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewFieldsVisibilityDropdownSection } from '@/ui/view-bar/components/ViewFieldsVisibilityDropdownSection';
import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
@ -42,7 +43,6 @@ import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
export type BoardOptionsDropdownContentProps = {
customHotkeyScope: HotkeyScope;
onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
scopeContext: Context<string | null>;
};
const StyledIconSettings = styled(IconSettings)`
@ -61,10 +61,13 @@ type ColumnForCreate = {
export function BoardOptionsDropdownContent({
customHotkeyScope,
onStageAdd,
scopeContext,
}: BoardOptionsDropdownContentProps) {
const theme = useTheme();
const scopeId = useContextScopeId(scopeContext);
const BoardRecoilScopeContext =
useContext(BoardContext).BoardRecoilScopeContext;
const boardRecoilScopeId = useRecoilScopeId(BoardRecoilScopeContext);
const stageInputRef = useRef<HTMLInputElement>(null);
const viewEditInputRef = useRef<HTMLInputElement>(null);
@ -77,16 +80,19 @@ export function BoardOptionsDropdownContent({
const hiddenBoardCardFields = useRecoilScopedValue(
hiddenBoardCardFieldsScopedSelector,
scopeContext,
BoardRecoilScopeContext,
);
const hasHiddenFields = hiddenBoardCardFields.length > 0;
const visibleBoardCardFields = useRecoilScopedValue(
visibleBoardCardFieldsScopedSelector,
scopeContext,
BoardRecoilScopeContext,
);
const hasVisibleFields = visibleBoardCardFields.length > 0;
const viewsById = useRecoilScopedValue(viewsByIdScopedSelector, scopeContext);
const viewsById = useRecoilScopedValue(
viewsByIdScopedSelector,
BoardRecoilScopeContext, // TODO: replace with ViewBarRecoilScopeContext
);
const viewEditMode = useRecoilValue(viewEditModeState);
const handleStageSubmit = () => {
@ -107,13 +113,13 @@ export function BoardOptionsDropdownContent({
onStageAdd?.(columnToCreate);
};
const { upsertView } = useUpsertView({ scopeContext });
const { upsertView } = useUpsertView();
const handleViewNameSubmit = useRecoilCallback(
({ set, snapshot }) =>
async () => {
const boardCardFields = await snapshot.getPromise(
boardCardFieldsScopedState(scopeId),
boardCardFieldsScopedState(boardRecoilScopeId),
);
const isCreateMode = viewEditMode.mode === 'create';
const name = viewEditInputRef.current?.value;
@ -123,7 +129,7 @@ export function BoardOptionsDropdownContent({
set(savedBoardCardFieldsFamilyState(view.id), boardCardFields);
}
},
[scopeId, upsertView, viewEditMode.mode],
[boardRecoilScopeId, upsertView, viewEditMode.mode],
);
const resetMenu = () => setCurrentMenu(undefined);
@ -133,7 +139,7 @@ export function BoardOptionsDropdownContent({
setCurrentMenu(menu);
};
const { handleFieldVisibilityChange } = useBoardCardFields({ scopeContext });
const { handleFieldVisibilityChange } = useBoardCardFields();
const { closeDropdownButton } = useDropdownButton({
dropdownId: BoardOptionsDropdownKey,

View File

@ -1,4 +1,4 @@
import { type Context, useCallback, useRef } from 'react';
import { useCallback, useRef } from 'react';
import { getOperationName } from '@apollo/client/utilities';
import styled from '@emotion/styled';
import { DragDropContext, OnDragEndResponder } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350
@ -35,7 +35,6 @@ export type EntityBoardProps = {
onColumnAdd?: (boardColumn: BoardColumnDefinition) => void;
onColumnDelete?: (boardColumnId: string) => void;
onEditColumnTitle: (columnId: string, title: string, color: string) => void;
scopeContext: Context<string | null>;
};
const StyledWrapper = styled.div`
@ -54,7 +53,6 @@ export function EntityBoard({
onColumnAdd,
onColumnDelete,
onEditColumnTitle,
scopeContext,
}: EntityBoardProps) {
const [boardColumns] = useRecoilState(boardColumnsState);
const setCardSelected = useSetCardSelected();
@ -130,14 +128,14 @@ export function EntityBoard({
return (boardColumns?.length ?? 0) > 0 ? (
<StyledWrapper>
<StyledBoardHeader onStageAdd={onColumnAdd} scopeContext={scopeContext} />
<StyledBoardHeader onStageAdd={onColumnAdd} />
<ScrollWrapper>
<StyledBoard ref={boardRef}>
<DragDropContext onDragEnd={onDragEnd}>
{sortedBoardColumns.map((column) => (
<BoardColumnIdContext.Provider value={column.id} key={column.id}>
<RecoilScope
SpecificContext={BoardColumnRecoilScopeContext}
CustomRecoilScopeContext={BoardColumnRecoilScopeContext}
key={column.id}
>
<EntityBoardColumn
@ -145,7 +143,6 @@ export function EntityBoard({
column={column}
onDelete={onColumnDelete}
onTitleEdit={onEditColumnTitle}
scopeContext={scopeContext}
/>
</RecoilScope>
</BoardColumnIdContext.Provider>

View File

@ -1,4 +1,3 @@
import type { Context } from 'react';
import { Draggable } from '@hello-pangea/dnd';
import { useSetRecoilState } from 'recoil';
@ -12,12 +11,10 @@ export function EntityBoardCard({
boardOptions,
cardId,
index,
scopeContext,
}: {
boardOptions: BoardOptions;
cardId: string;
index: number;
scopeContext: Context<string | null>;
}) {
const setContextMenuPosition = useSetRecoilState(contextMenuPositionState);
const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState);
@ -46,7 +43,7 @@ export function EntityBoardCard({
data-select-disable
onContextMenu={handleContextMenu}
>
{<boardOptions.CardComponent scopeContext={scopeContext} />}
{<boardOptions.CardComponent />}
</div>
)}
</Draggable>

View File

@ -1,4 +1,4 @@
import { type Context, useContext } from 'react';
import { useContext } from 'react';
import styled from '@emotion/styled';
import { Draggable, Droppable, DroppableProvided } from '@hello-pangea/dnd';
import { useRecoilValue } from 'recoil';
@ -52,13 +52,11 @@ export function EntityBoardColumn({
column,
onDelete,
onTitleEdit,
scopeContext,
}: {
boardOptions: BoardOptions;
column: BoardColumnDefinition;
onDelete?: (columnId: string) => void;
onTitleEdit: (columnId: string, title: string, color: string) => void;
scopeContext: Context<string | null>;
}) {
const boardColumnId = useContext(BoardColumnIdContext) ?? '';
@ -94,7 +92,6 @@ export function EntityBoardColumn({
index={index}
cardId={cardId}
boardOptions={boardOptions}
scopeContext={scopeContext}
/>
</BoardCardIdContext.Provider>
))}

View File

@ -1,5 +1,3 @@
import type { Context } from 'react';
import type {
ViewFieldDefinition,
ViewFieldMetadata,
@ -10,18 +8,18 @@ import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoi
import { boardCardFieldsScopedState } from '../states/boardCardFieldsScopedState';
import { boardCardFieldsByKeyScopedSelector } from '../states/selectors/boardCardFieldsByKeyScopedSelector';
export const useBoardCardFields = ({
scopeContext,
}: {
scopeContext: Context<string | null>;
}) => {
import { useBoardContext } from './useBoardContext';
export const useBoardCardFields = () => {
const { BoardRecoilScopeContext } = useBoardContext();
const [boardCardFields, setBoardCardFields] = useRecoilScopedState(
boardCardFieldsScopedState,
scopeContext,
BoardRecoilScopeContext,
);
const boardCardFieldsByKey = useRecoilScopedValue(
boardCardFieldsByKeyScopedSelector,
scopeContext,
BoardRecoilScopeContext,
);
const handleFieldVisibilityChange = (

View File

@ -0,0 +1,7 @@
import { useContext } from 'react';
import { BoardContext } from '@/companies/states/contexts/BoardContext';
export const useBoardContext = () => {
return useContext(BoardContext);
};

View File

@ -8,10 +8,16 @@ import { savedBoardCardFieldsFamilyState } from '../savedBoardCardFieldsFamilySt
export const canPersistBoardCardFieldsScopedFamilySelector = selectorFamily({
key: 'canPersistBoardCardFieldsScopedFamilySelector',
get:
([scopeId, viewId]: [string, string | undefined]) =>
({
recoilScopeId,
viewId,
}: {
recoilScopeId: string;
viewId: string | undefined;
}) =>
({ get }) =>
!isDeeplyEqual(
get(savedBoardCardFieldsFamilyState(viewId)),
get(boardCardFieldsScopedState(scopeId)),
get(boardCardFieldsScopedState(recoilScopeId)),
),
});

View File

@ -1,4 +1,4 @@
import type { ComponentType, Context } from 'react';
import type { ComponentType } from 'react';
import { FilterDefinitionByEntity } from '@/ui/view-bar/types/FilterDefinitionByEntity';
import { SortDefinition } from '@/ui/view-bar/types/SortDefinition';
@ -6,7 +6,7 @@ import { PipelineProgress } from '~/generated/graphql';
export type BoardOptions = {
newCardComponent: React.ReactNode;
CardComponent: ComponentType<{ scopeContext: Context<string | null> }>;
CardComponent: ComponentType;
filters: FilterDefinitionByEntity<PipelineProgress>[];
sorts: SortDefinition[];
};

View File

@ -30,7 +30,7 @@ const meta: Meta<typeof ContextMenu> = {
component: FilledContextMenu,
decorators: [
(Story) => (
<RecoilScope SpecificContext={TableRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={TableRecoilScopeContext}>
<CompanyTableMockMode></CompanyTableMockMode>
<MemoryRouter>
<Story />

View File

@ -16,7 +16,7 @@ export function GenericEditableBooleanField() {
) as FieldDefinition<FieldBooleanMetadata>;
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<EditableField
IconLabel={currentEditableFieldDefinition.Icon}
displayModeContent={<GenericEditableBooleanFieldDisplayMode />}

View File

@ -30,7 +30,7 @@ export function GenericEditableDateField() {
);
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<EditableField
IconLabel={currentEditableFieldDefinition.Icon}
editModeContent={<GenericEditableDateFieldEditMode />}

View File

@ -30,7 +30,7 @@ export function GenericEditableNumberField() {
);
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<EditableField
IconLabel={currentEditableFieldDefinition.Icon}
editModeContent={<GenericEditableNumberFieldEditMode />}

View File

@ -30,7 +30,7 @@ export function GenericEditablePhoneField() {
);
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<EditableField
useEditButton
IconLabel={currentEditableFieldDefinition.Icon}

View File

@ -31,7 +31,7 @@ export function GenericEditableRelationField() {
);
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<RecoilScope>
<EditableField
useEditButton={currentEditableFieldDefinition.metadata.useEditButton}

View File

@ -30,7 +30,7 @@ export function GenericEditableTextField() {
);
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<EditableField
IconLabel={currentEditableFieldDefinition.Icon}
editModeContent={<GenericEditableTextFieldEditMode />}

View File

@ -30,7 +30,7 @@ export function GenericEditableURLField() {
);
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<EditableField
useEditButton
IconLabel={currentEditableFieldDefinition.Icon}

View File

@ -16,7 +16,7 @@ export function ProbabilityEditableField() {
) as FieldDefinition<FieldProbabilityMetadata>;
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<EditableField
IconLabel={currentEditableFieldDefinition.Icon}
displayModeContent={<ProbabilityEditableFieldEditMode />}

View File

@ -29,7 +29,7 @@ export function DateEditableField({
const internalDateValue = value ? parseDate(value).toJSDate() : null;
return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<EditableField
IconLabel={Icon}
label={label}

View File

@ -14,10 +14,7 @@ import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus';
import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus';
import { useResetTableRowSelection } from '../hooks/useResetTableRowSelection';
import { useSetRowSelectedState } from '../hooks/useSetRowSelectedState';
import {
TableHeader,
type TableHeaderProps,
} from '../table-header/components/TableHeader';
import { TableHeader } from '../table-header/components/TableHeader';
import { TableHotkeyScope } from '../types/TableHotkeyScope';
import { EntityTableBody } from './EntityTableBody';
@ -87,9 +84,9 @@ const StyledTableContainer = styled.div`
type OwnProps = {
updateEntityMutation: any;
} & Pick<TableHeaderProps, 'onImport'>;
};
export function EntityTable({ onImport, updateEntityMutation }: OwnProps) {
export function EntityTable({ updateEntityMutation }: OwnProps) {
const tableBodyRef = useRef<HTMLDivElement>(null);
const setRowSelectedState = useSetRowSelectedState();
@ -126,7 +123,7 @@ export function EntityTable({ onImport, updateEntityMutation }: OwnProps) {
<EntityUpdateMutationContext.Provider value={updateEntityMutation}>
<StyledTableWithHeader>
<StyledTableContainer ref={tableBodyRef}>
<TableHeader onImport={onImport} />
<TableHeader />
<ScrollWrapper>
<div>
<StyledTable className="entity-table-cell">

View File

@ -13,7 +13,7 @@ const meta: Meta<typeof PhoneInput> = {
autoFocus: true,
},
parameters: {
recoilScopeContext: TableRecoilScopeContext,
customRecoilScopeContext: TableRecoilScopeContext,
},
};

View File

@ -1,6 +1,6 @@
import { useRecoilCallback } from 'recoil';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { numberOfTableRowsState } from '../states/numberOfTableRowsState';
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
@ -11,7 +11,7 @@ import { useSetSoftFocusPosition } from './useSetSoftFocusPosition';
// TODO: stories
export function useMoveSoftFocus() {
const tableScopeId = useContextScopeId(TableRecoilScopeContext);
const tableScopeId = useRecoilScopeId(TableRecoilScopeContext);
const setSoftFocusPosition = useSetSoftFocusPosition();
const moveUp = useRecoilCallback(

View File

@ -4,7 +4,7 @@ import { useResetTableRowSelection } from '@/ui/table/hooks/useResetTableRowSele
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableEntitiesFamilyState } from '@/ui/table/states/tableEntitiesFamilyState';
import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { availableFiltersScopedState } from '@/ui/view-bar/states/availableFiltersScopedState';
import { availableSortsScopedState } from '@/ui/view-bar/states/availableSortsScopedState';
import { FilterDefinition } from '@/ui/view-bar/types/FilterDefinition';
@ -16,7 +16,7 @@ import { numberOfTableRowsState } from '../states/numberOfTableRowsState';
export function useSetEntityTableData() {
const resetTableRowSelection = useResetTableRowSelection();
const tableContextScopeId = useContextScopeId(TableRecoilScopeContext);
const tableContextScopeId = useRecoilScopeId(TableRecoilScopeContext);
return useRecoilCallback(
({ set, snapshot }) =>

View File

@ -10,12 +10,10 @@ import { TableOptionsDropdownButton } from './TableOptionsDropdownButton';
import { TableOptionsDropdownContent } from './TableOptionsDropdownContent';
type TableOptionsDropdownProps = {
onImport?: () => void;
customHotkeyScope: HotkeyScope;
};
export function TableOptionsDropdown({
onImport,
customHotkeyScope,
}: TableOptionsDropdownProps) {
const resetViewEditMode = useResetRecoilState(viewEditModeState);
@ -25,7 +23,7 @@ export function TableOptionsDropdown({
buttonComponents={<TableOptionsDropdownButton />}
dropdownHotkeyScope={customHotkeyScope}
dropdownId={TableOptionsDropdownId}
dropdownComponents={<TableOptionsDropdownContent onImport={onImport} />}
dropdownComponents={<TableOptionsDropdownContent />}
onClickOutside={resetViewEditMode}
/>
);

View File

@ -1,4 +1,4 @@
import { useRef, useState } from 'react';
import { useContext, useRef, useState } from 'react';
import styled from '@emotion/styled';
import { useRecoilCallback, useRecoilValue, useResetRecoilState } from 'recoil';
import { Key } from 'ts-key-enum';
@ -13,9 +13,10 @@ import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { rgba } from '@/ui/theme/constants/colors';
import { textInputStyle } from '@/ui/theme/constants/effects';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewFieldsVisibilityDropdownSection } from '@/ui/view-bar/components/ViewFieldsVisibilityDropdownSection';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
import { currentViewScopedSelector } from '@/ui/view-bar/states/selectors/currentViewScopedSelector';
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
@ -30,10 +31,6 @@ import { visibleTableColumnsScopedSelector } from '../../states/selectors/visibl
import { tableColumnsScopedState } from '../../states/tableColumnsScopedState';
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
type TableOptionsDropdownButtonProps = {
onImport?: () => void;
};
type TableOptionsMenu = 'fields';
const StyledInputContainer = styled.div`
@ -59,11 +56,10 @@ const StyledViewNameInput = styled.input`
}
`;
export function TableOptionsDropdownContent({
onImport,
}: TableOptionsDropdownButtonProps) {
const scopeId = useContextScopeId(TableRecoilScopeContext);
export function TableOptionsDropdownContent() {
const scopeId = useRecoilScopeId(TableRecoilScopeContext);
const { onImport } = useContext(ViewBarContext);
const { closeDropdownButton } = useDropdownButton({
dropdownId: TableOptionsDropdownId,
});
@ -95,9 +91,7 @@ export function TableOptionsDropdownContent({
const { handleColumnVisibilityChange } = useTableColumns();
const { upsertView } = useUpsertView({
scopeContext: TableRecoilScopeContext,
});
const { upsertView } = useUpsertView();
const handleViewNameSubmit = useRecoilCallback(
({ set, snapshot }) =>

View File

@ -3,6 +3,7 @@ import { userEvent, within } from '@storybook/testing-library';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { TableRecoilScopeContext } from '../../../states/recoil-scope-contexts/TableRecoilScopeContext';
@ -13,10 +14,16 @@ const meta: Meta<typeof TableOptionsDropdown> = {
component: TableOptionsDropdown,
decorators: [
(Story) => (
<RecoilScope SpecificContext={TableRecoilScopeContext}>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<Story />
</RecoilScope>
<RecoilScope CustomRecoilScopeContext={TableRecoilScopeContext}>
<ViewBarContext.Provider
value={{
ViewBarRecoilScopeContext: TableRecoilScopeContext,
}}
>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<Story />
</RecoilScope>
</ViewBarContext.Provider>
</RecoilScope>
),
ComponentDecorator,

View File

@ -8,10 +8,16 @@ import { tableColumnsScopedState } from '../tableColumnsScopedState';
export const canPersistTableColumnsScopedFamilySelector = selectorFamily({
key: 'canPersistTableColumnsScopedFamilySelector',
get:
([scopeId, viewId]: [string, string | undefined]) =>
({
recoilScopeId,
viewId,
}: {
recoilScopeId: string;
viewId: string | undefined;
}) =>
({ get }) =>
!isDeeplyEqual(
get(savedTableColumnsFamilyState(viewId)),
get(tableColumnsScopedState(scopeId)),
get(tableColumnsScopedState(recoilScopeId)),
),
});

View File

@ -3,9 +3,9 @@ import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBar } from '@/ui/view-bar/components/ViewBar';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
@ -18,21 +18,20 @@ import { canPersistTableColumnsScopedFamilySelector } from '../../states/selecto
import { tableColumnsScopedState } from '../../states/tableColumnsScopedState';
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
export type TableHeaderProps = {
onImport?: () => void;
};
export function TableHeader({ onImport }: TableHeaderProps) {
export function TableHeader() {
const { onCurrentViewSubmit, ...viewBarContextProps } =
useContext(ViewBarContext);
const tableScopeId = useContextScopeId(TableRecoilScopeContext);
const tableRecoilScopeId = useRecoilScopeId(TableRecoilScopeContext);
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
TableRecoilScopeContext,
);
const canPersistTableColumns = useRecoilValue(
canPersistTableColumnsScopedFamilySelector([tableScopeId, currentViewId]),
canPersistTableColumnsScopedFamilySelector({
recoilScopeId: tableRecoilScopeId,
viewId: currentViewId,
}),
);
const [tableColumns, setTableColumns] = useRecoilScopedState(
tableColumnsScopedState,
@ -50,9 +49,9 @@ export function TableHeader({ onImport }: TableHeaderProps) {
const savedTableColumns = await snapshot.getPromise(
savedTableColumnsFamilyState(viewId),
);
set(tableColumnsScopedState(tableScopeId), savedTableColumns);
set(tableColumnsScopedState(tableRecoilScopeId), savedTableColumns);
},
[tableScopeId],
[tableRecoilScopeId],
);
async function handleCurrentViewSubmit() {
@ -64,7 +63,7 @@ export function TableHeader({ onImport }: TableHeaderProps) {
}
return (
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<ViewBarContext.Provider
value={{
...viewBarContextProps,
@ -77,12 +76,10 @@ export function TableHeader({ onImport }: TableHeaderProps) {
<ViewBar
optionsDropdownButton={
<TableOptionsDropdown
onImport={onImport}
customHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }}
/>
}
optionsDropdownKey={TableOptionsDropdownId}
scopeContext={TableRecoilScopeContext}
/>
</ViewBarContext.Provider>
</RecoilScope>

View File

@ -1,23 +1,25 @@
import { Context, useRef } from 'react';
import { useRef } from 'react';
import { v4 } from 'uuid';
import { type RecoilScopeContext as RecoilScopeContextType } from '@/types/RecoilScopeContext';
import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function RecoilScope({
children,
scopeId,
SpecificContext,
CustomRecoilScopeContext,
}: {
children: React.ReactNode;
scopeId?: string;
SpecificContext?: Context<string | null>;
CustomRecoilScopeContext?: RecoilScopeContextType;
}) {
const currentScopeId = useRef(scopeId ?? v4());
return SpecificContext ? (
<SpecificContext.Provider value={currentScopeId.current}>
return CustomRecoilScopeContext ? (
<CustomRecoilScopeContext.Provider value={currentScopeId.current}>
{children}
</SpecificContext.Provider>
</CustomRecoilScopeContext.Provider>
) : (
<RecoilScopeContext.Provider value={currentScopeId.current}>
{children}

View File

@ -1,12 +0,0 @@
import { Context, useContext } from 'react';
export function useContextScopeId(SpecificContext: Context<string | null>) {
const recoilScopeId = useContext(SpecificContext);
if (!recoilScopeId)
throw new Error(
`Using useContextScopedId outside of the specified context : ${SpecificContext.displayName}, verify that you are using a RecoilScope with the specific context you want to use.`,
);
return recoilScopeId;
}

View File

@ -0,0 +1,14 @@
import { useContext } from 'react';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
export function useRecoilScopeId(RecoilScopeContext: RecoilScopeContext) {
const recoilScopeId = useContext(RecoilScopeContext);
if (!recoilScopeId)
throw new Error(
`Using useRecoilScopeId outside of the specified context : ${RecoilScopeContext.displayName}, verify that you are using a RecoilScope with the specific context you want to use.`,
);
return recoilScopeId;
}

View File

@ -6,9 +6,11 @@ import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function useRecoilScopedFamilyState<StateType>(
recoilState: (familyUniqueId: string) => RecoilState<StateType>,
uniqueIdInRecoilScope: string,
SpecificContext?: Context<string | null>,
CustomRecoilScopeContext?: Context<string | null>,
) {
const recoilScopeId = useContext(SpecificContext ?? RecoilScopeContext);
const recoilScopeId = useContext(
CustomRecoilScopeContext ?? RecoilScopeContext,
);
if (!recoilScopeId)
throw new Error(

View File

@ -5,9 +5,11 @@ import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function useRecoilScopedState<StateType>(
recoilState: (param: string) => RecoilState<StateType>,
SpecificContext?: Context<string | null>,
CustomRecoilScopeContext?: Context<string | null>,
) {
const recoilScopeId = useContext(SpecificContext ?? RecoilScopeContext);
const recoilScopeId = useContext(
CustomRecoilScopeContext ?? RecoilScopeContext,
);
if (!recoilScopeId)
throw new Error(

View File

@ -5,9 +5,11 @@ import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function useRecoilScopedValue<T>(
recoilState: (param: string) => RecoilState<T> | RecoilValueReadOnly<T>,
SpecificContext?: Context<string | null>,
CustomRecoilScopeContext?: Context<string | null>,
) {
const recoilScopeId = useContext(SpecificContext ?? RecoilScopeContext);
const recoilScopeId = useContext(
CustomRecoilScopeContext ?? RecoilScopeContext,
);
if (!recoilScopeId)
throw new Error(

View File

@ -1,25 +1,24 @@
import { Context } from 'react';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
import { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton';
import { SingleEntityFilterDropdownButton } from './SingleEntityFilterDropdownButton';
type FilterDropdownButtonProps = {
context: Context<string | null>;
hotkeyScope: HotkeyScope;
};
export function FilterDropdownButton({
hotkeyScope,
context,
}: FilterDropdownButtonProps) {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [availableFilters] = useRecoilScopedState(
availableFiltersScopedState,
context,
ViewBarRecoilScopeContext,
);
const hasOnlyOneEntityFilter =
@ -30,14 +29,8 @@ export function FilterDropdownButton({
}
return hasOnlyOneEntityFilter ? (
<SingleEntityFilterDropdownButton
context={context}
hotkeyScope={hotkeyScope}
/>
<SingleEntityFilterDropdownButton hotkeyScope={hotkeyScope} />
) : (
<MultipleFiltersDropdownButton
context={context}
hotkeyScope={hotkeyScope}
/>
<MultipleFiltersDropdownButton hotkeyScope={hotkeyScope} />
);
}

View File

@ -1,35 +1,31 @@
import { Context } from 'react';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { DatePicker } from '@/ui/input/components/DatePicker';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useUpsertFilter } from '@/ui/view-bar/hooks/useUpsertFilter';
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState';
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { isFilterDropdownUnfoldedScopedState } from '../states/isFilterDropdownUnfoldedScopedState';
export function FilterDropdownDateSearchInput({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownDateSearchInput() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setIsFilterDropdownUnfolded] = useRecoilScopedState(
isFilterDropdownUnfoldedScopedState,
DropdownRecoilScopeContext,
ViewBarRecoilScopeContext,
);
const upsertFilter = useUpsertFilter(context);
const upsertFilter = useUpsertFilter();
function handleChange(date: Date) {
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;

View File

@ -1,4 +1,4 @@
import { ChangeEvent, Context } from 'react';
import { ChangeEvent } from 'react';
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
@ -6,23 +6,26 @@ import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/
import { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filterDropdownSearchInputScopedState';
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
export function FilterDropdownEntitySearchInput({
context,
}: {
context: Context<string | null>;
}) {
import { useViewBarContext } from '../hooks/useViewBarContext';
export function FilterDropdownEntitySearchInput() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [filterDropdownSearchInput, setFilterDropdownSearchInput] =
useRecoilScopedState(filterDropdownSearchInputScopedState, context);
useRecoilScopedState(
filterDropdownSearchInputScopedState,
ViewBarRecoilScopeContext,
);
return (
filterDefinitionUsedInDropdown &&

View File

@ -11,30 +11,35 @@ import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/
import { filterDropdownSelectedEntityIdScopedState } from '@/ui/view-bar/states/filterDropdownSelectedEntityIdScopedState';
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
import { useViewBarContext } from '../hooks/useViewBarContext';
export function FilterDropdownEntitySearchSelect({
entitiesForSelect,
context,
}: {
entitiesForSelect: EntitiesForMultipleEntitySelect<EntityForSelect>;
context: React.Context<string | null>;
}) {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filterDropdownSelectedEntityId, setFilterDropdownSelectedEntityId] =
useRecoilScopedState(filterDropdownSelectedEntityIdScopedState, context);
useRecoilScopedState(
filterDropdownSelectedEntityIdScopedState,
ViewBarRecoilScopeContext,
);
const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const upsertFilter = useUpsertFilter(context);
const removeFilter = useRemoveFilter(context);
const upsertFilter = useUpsertFilter();
const removeFilter = useRemoveFilter();
const filterCurrentlyEdited = useFilterCurrentlyEdited(context);
const filterCurrentlyEdited = useFilterCurrentlyEdited();
function handleUserSelected(
selectedEntity: EntityForSelect | null | undefined,

View File

@ -1,19 +1,16 @@
import { Context } from 'react';
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
export function FilterDropdownEntitySelect({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownEntitySelect() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
if (filterDefinitionUsedInDropdown?.type !== 'entity') {

View File

@ -1,5 +1,3 @@
import { Context } from 'react';
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
@ -7,35 +5,34 @@ import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
import { filterDropdownSearchInputScopedState } from '../states/filterDropdownSearchInputScopedState';
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
export function FilterDropdownFilterSelect({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownFilterSelect() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [, setFilterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setFilterDropdownSearchInput] = useRecoilScopedState(
filterDropdownSearchInputScopedState,
context,
ViewBarRecoilScopeContext,
);
const availableFilters = useRecoilScopedValue(
availableFiltersScopedState,
context,
ViewBarRecoilScopeContext,
);
const setHotkeyScope = useSetHotkeyScope();

View File

@ -1,30 +1,29 @@
import { ChangeEvent, Context } from 'react';
import { ChangeEvent } from 'react';
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRemoveFilter } from '../hooks/useRemoveFilter';
import { useUpsertFilter } from '../hooks/useUpsertFilter';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
export function FilterDropdownNumberSearchInput({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownNumberSearchInput() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const upsertFilter = useUpsertFilter(context);
const removeFilter = useRemoveFilter(context);
const upsertFilter = useUpsertFilter();
const removeFilter = useRemoveFilter();
return (
filterDefinitionUsedInDropdown &&

View File

@ -1,21 +1,18 @@
import { Context } from 'react';
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
import { IconChevronDown } from '@/ui/icon';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
import { getOperandLabel } from '../utils/getOperandLabel';
export function FilterDropdownOperandButton({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownOperandButton() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [
@ -23,7 +20,7 @@ export function FilterDropdownOperandButton({
setIsFilterDropdownOperandSelectUnfolded,
] = useRecoilScopedState(
isFilterDropdownOperandSelectUnfoldedScopedState,
context,
ViewBarRecoilScopeContext,
);
if (isFilterDropdownOperandSelectUnfolded) {

View File

@ -1,11 +1,10 @@
import { Context } from 'react';
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
import { useUpsertFilter } from '../hooks/useUpsertFilter';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
@ -13,19 +12,17 @@ import { FilterOperand } from '../types/FilterOperand';
import { getOperandLabel } from '../utils/getOperandLabel';
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
export function FilterDropdownOperandSelect({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownOperandSelect() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const operandsForFilterType = getOperandsForFilterType(
@ -37,12 +34,12 @@ export function FilterDropdownOperandSelect({
setIsFilterDropdownOperandSelectUnfolded,
] = useRecoilScopedState(
isFilterDropdownOperandSelectUnfoldedScopedState,
context,
ViewBarRecoilScopeContext,
);
const filterCurrentlyEdited = useFilterCurrentlyEdited(context);
const filterCurrentlyEdited = useFilterCurrentlyEdited();
const upsertFilter = useUpsertFilter(context);
const upsertFilter = useUpsertFilter();
function handleOperangeChange(newOperand: FilterOperand) {
setSelectedOperandInDropdown(newOperand);

View File

@ -1,4 +1,4 @@
import { ChangeEvent, Context } from 'react';
import { ChangeEvent } from 'react';
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
@ -6,32 +6,34 @@ import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoi
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
import { useRemoveFilter } from '../hooks/useRemoveFilter';
import { useUpsertFilter } from '../hooks/useUpsertFilter';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
import { filterDropdownSearchInputScopedState } from '../states/filterDropdownSearchInputScopedState';
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
export function FilterDropdownTextSearchInput({
context,
}: {
context: Context<string | null>;
}) {
export function FilterDropdownTextSearchInput() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [filterDropdownSearchInput, setFilterDropdownSearchInput] =
useRecoilScopedState(filterDropdownSearchInputScopedState, context);
useRecoilScopedState(
filterDropdownSearchInputScopedState,
ViewBarRecoilScopeContext,
);
const upsertFilter = useUpsertFilter(context);
const removeFilter = useRemoveFilter(context);
const upsertFilter = useUpsertFilter();
const removeFilter = useRemoveFilter();
const filterCurrentlyEdited = useFilterCurrentlyEdited(context);
const filterCurrentlyEdited = useFilterCurrentlyEdited();
return (
filterDefinitionUsedInDropdown &&

View File

@ -1,42 +1,39 @@
import { Context } from 'react';
import { StyledHeaderDropdownButton } from '@/ui/dropdown/components/StyledHeaderDropdownButton';
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { FilterDropdownId } from '../constants/FilterDropdownId';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
import { filterDropdownSearchInputScopedState } from '../states/filterDropdownSearchInputScopedState';
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
type OwnProps = {
context: Context<string | null>;
};
export function MultipleFiltersButton() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
export function MultipleFiltersButton({ context }: OwnProps) {
const { isDropdownButtonOpen, toggleDropdownButton } = useDropdownButton({
dropdownId: FilterDropdownId,
});
const [, setIsFilterDropdownOperandSelectUnfolded] = useRecoilScopedState(
isFilterDropdownOperandSelectUnfoldedScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setFilterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setFilterDropdownSearchInput] = useRecoilScopedState(
filterDropdownSearchInputScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const resetState = () => {

View File

@ -1,5 +1,3 @@
import { Context } from 'react';
import { DropdownButton } from '@/ui/dropdown/components/DropdownButton';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
@ -9,19 +7,17 @@ import { MultipleFiltersButton } from './MultipleFiltersButton';
import { MultipleFiltersDropdownContent } from './MultipleFiltersDropdownContent';
type MultipleFiltersDropdownButtonProps = {
context: Context<string | null>;
hotkeyScope: HotkeyScope;
};
export function MultipleFiltersDropdownButton({
context,
hotkeyScope,
}: MultipleFiltersDropdownButtonProps) {
return (
<DropdownButton
dropdownId={FilterDropdownId}
buttonComponents={<MultipleFiltersButton context={context} />}
dropdownComponents={<MultipleFiltersDropdownContent context={context} />}
buttonComponents={<MultipleFiltersButton />}
dropdownComponents={<MultipleFiltersDropdownContent />}
dropdownHotkeyScope={hotkeyScope}
/>
);

View File

@ -1,9 +1,8 @@
import { Context } from 'react';
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
@ -17,54 +16,50 @@ import { FilterDropdownOperandButton } from './FilterDropdownOperandButton';
import { FilterDropdownOperandSelect } from './FilterDropdownOperandSelect';
import { FilterDropdownTextSearchInput } from './FilterDropdownTextSearchInput';
export type MultipleFiltersDropdownContentProps = {
context: Context<string | null>;
};
export function MultipleFiltersDropdownContent() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
export function MultipleFiltersDropdownContent({
context,
}: MultipleFiltersDropdownContentProps) {
const [isFilterDropdownOperandSelectUnfolded] = useRecoilScopedState(
isFilterDropdownOperandSelectUnfoldedScopedState,
context,
ViewBarRecoilScopeContext,
);
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
return (
<StyledDropdownMenu>
<>
{!filterDefinitionUsedInDropdown ? (
<FilterDropdownFilterSelect context={context} />
<FilterDropdownFilterSelect />
) : isFilterDropdownOperandSelectUnfolded ? (
<FilterDropdownOperandSelect context={context} />
<FilterDropdownOperandSelect />
) : (
selectedOperandInDropdown && (
<>
<FilterDropdownOperandButton context={context} />
<FilterDropdownOperandButton />
<StyledDropdownMenuSeparator />
{filterDefinitionUsedInDropdown.type === 'text' && (
<FilterDropdownTextSearchInput context={context} />
<FilterDropdownTextSearchInput />
)}
{filterDefinitionUsedInDropdown.type === 'number' && (
<FilterDropdownNumberSearchInput context={context} />
<FilterDropdownNumberSearchInput />
)}
{filterDefinitionUsedInDropdown.type === 'date' && (
<FilterDropdownDateSearchInput context={context} />
<FilterDropdownDateSearchInput />
)}
{filterDefinitionUsedInDropdown.type === 'entity' && (
<FilterDropdownEntitySearchInput context={context} />
<FilterDropdownEntitySearchInput />
)}
{filterDefinitionUsedInDropdown.type === 'entity' && (
<FilterDropdownEntitySelect context={context} />
<FilterDropdownEntitySelect />
)}
</>
)

View File

@ -1,4 +1,3 @@
import { Context } from 'react';
import React from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
@ -14,6 +13,7 @@ import { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filte
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
import { StyledHeaderDropdownButton } from '../../dropdown/components/StyledHeaderDropdownButton';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
import { filtersScopedState } from '../states/filtersScopedState';
import { isFilterDropdownUnfoldedScopedState } from '../states/isFilterDropdownUnfoldedScopedState';
@ -30,17 +30,17 @@ const StyledDropdownButtonContainer = styled.div`
`;
export function SingleEntityFilterDropdownButton({
context,
hotkeyScope,
}: {
context: Context<string | null>;
hotkeyScope: HotkeyScope;
}) {
const theme = useTheme();
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [availableFilters] = useRecoilScopedState(
availableFiltersScopedState,
context,
ViewBarRecoilScopeContext,
);
const availableFilter = availableFilters[0];
@ -50,21 +50,24 @@ export function SingleEntityFilterDropdownButton({
DropdownRecoilScopeContext,
);
const [filters] = useRecoilScopedState(filtersScopedState, context);
const [filters] = useRecoilScopedState(
filtersScopedState,
ViewBarRecoilScopeContext,
);
const [, setFilterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setFilterDropdownSearchInput] = useRecoilScopedState(
filterDropdownSearchInputScopedState,
context,
ViewBarRecoilScopeContext,
);
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
React.useEffect(() => {
@ -105,8 +108,8 @@ export function SingleEntityFilterDropdownButton({
</StyledHeaderDropdownButton>
{isFilterDropdownUnfolded && (
<DropdownMenuContainer onClose={() => handleIsUnfoldedChange(false)}>
<FilterDropdownEntitySearchInput context={context} />
<FilterDropdownEntitySelect context={context} />
<FilterDropdownEntitySearchInput />
<FilterDropdownEntitySelect />
</DropdownMenuContainer>
)}
</StyledDropdownButtonContainer>

View File

@ -1,4 +1,4 @@
import { Context, useCallback, useState } from 'react';
import { useCallback, useState } from 'react';
import { produce } from 'immer';
import { LightButton } from '@/ui/button/components/LightButton';
@ -14,21 +14,20 @@ import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { SortDropdownId } from '../constants/SortDropdownId';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { availableSortsScopedState } from '../states/availableSortsScopedState';
import { sortsScopedState } from '../states/sortsScopedState';
import { SortDefinition } from '../types/SortDefinition';
import { SORT_DIRECTIONS, SortDirection } from '../types/SortDirection';
export type SortDropdownButtonProps = {
context: Context<string | null>;
hotkeyScope: HotkeyScope;
isPrimaryButton?: boolean;
};
export function SortDropdownButton({
hotkeyScope,
context,
}: SortDropdownButtonProps) {
export function SortDropdownButton({ hotkeyScope }: SortDropdownButtonProps) {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [isSortDirectionMenuUnfolded, setIsSortDirectionMenuUnfolded] =
useState(false);
@ -42,10 +41,13 @@ export function SortDropdownButton({
const [availableSorts] = useRecoilScopedState(
availableSortsScopedState,
context,
ViewBarRecoilScopeContext,
);
const [sorts, setSorts] = useRecoilScopedState(sortsScopedState, context);
const [sorts, setSorts] = useRecoilScopedState(
sortsScopedState,
ViewBarRecoilScopeContext,
);
const isSortSelected = sorts.length > 0;

View File

@ -1,4 +1,4 @@
import { type Context, useCallback, useContext, useState } from 'react';
import { useCallback, useContext, useState } from 'react';
import styled from '@emotion/styled';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { Key } from 'ts-key-enum';
@ -10,8 +10,8 @@ import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/Style
import { IconChevronDown, IconPlus } from '@/ui/icon';
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
@ -32,37 +32,51 @@ const StyledContainer = styled.div`
export type UpdateViewButtonGroupProps = {
hotkeyScope: string;
onViewEditModeChange?: () => void;
scopeContext: Context<string | null>;
};
export const UpdateViewButtonGroup = ({
hotkeyScope,
onViewEditModeChange,
scopeContext,
}: UpdateViewButtonGroupProps) => {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const { canPersistViewFields, onCurrentViewSubmit } =
useContext(ViewBarContext);
const recoilScopeId = useContextScopeId(scopeContext);
const {
canPersistViewFields,
onCurrentViewSubmit,
ViewBarRecoilScopeContext,
} = useContext(ViewBarContext);
const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
scopeContext,
ViewBarRecoilScopeContext,
);
const filters = useRecoilScopedValue(filtersScopedState, scopeContext);
const filters = useRecoilScopedValue(
filtersScopedState,
ViewBarRecoilScopeContext,
);
const setSavedFilters = useSetRecoilState(
savedFiltersFamilyState(currentViewId),
);
const canPersistFilters = useRecoilValue(
canPersistFiltersScopedFamilySelector([recoilScopeId, currentViewId]),
canPersistFiltersScopedFamilySelector({
recoilScopeId,
viewId: currentViewId,
}),
);
const sorts = useRecoilScopedValue(sortsScopedState, scopeContext);
const sorts = useRecoilScopedValue(
sortsScopedState,
ViewBarRecoilScopeContext,
);
const setSavedSorts = useSetRecoilState(savedSortsFamilyState(currentViewId));
const canPersistSorts = useRecoilValue(
canPersistSortsScopedFamilySelector([recoilScopeId, currentViewId]),
canPersistSortsScopedFamilySelector({
recoilScopeId,
viewId: currentViewId,
}),
);
const setViewEditMode = useSetRecoilState(viewEditModeState);

View File

@ -1,4 +1,4 @@
import type { Context, ReactNode } from 'react';
import type { ReactNode } from 'react';
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
import { TopBar } from '@/ui/top-bar/TopBar';
@ -9,21 +9,19 @@ import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
import { FilterDropdownButton } from './FilterDropdownButton';
import { SortDropdownButton } from './SortDropdownButton';
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
import ViewBarDetails from './ViewBarDetails';
import { ViewBarDetails } from './ViewBarDetails';
import { ViewsDropdownButton } from './ViewsDropdownButton';
export type ViewBarProps = {
className?: string;
optionsDropdownButton: ReactNode;
optionsDropdownKey: string;
scopeContext: Context<string | null>;
};
export const ViewBar = ({
className,
optionsDropdownButton,
optionsDropdownKey,
scopeContext,
}: ViewBarProps) => {
const { openDropdownButton: openOptionsDropdownButton } = useDropdownButton({
dropdownId: optionsDropdownKey,
@ -36,7 +34,6 @@ export const ViewBar = ({
<ViewsDropdownButton
onViewEditModeChange={openOptionsDropdownButton}
hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
scopeContext={scopeContext}
/>
}
displayBottomBorder={false}
@ -44,10 +41,8 @@ export const ViewBar = ({
<>
<FilterDropdownButton
hotkeyScope={{ scope: FiltersHotkeyScope.FilterDropdownButton }}
context={scopeContext}
/>
<SortDropdownButton
context={scopeContext}
hotkeyScope={{ scope: FiltersHotkeyScope.FilterDropdownButton }}
isPrimaryButton
/>
@ -56,13 +51,11 @@ export const ViewBar = ({
}
bottomComponent={
<ViewBarDetails
context={scopeContext}
hasFilterButton
rightComponent={
<UpdateViewButtonGroup
onViewEditModeChange={openOptionsDropdownButton}
hotkeyScope={ViewsHotkeyScope.CreateDropdown}
scopeContext={scopeContext}
/>
}
/>

View File

@ -1,11 +1,11 @@
import { type Context, type ReactNode, useContext } from 'react';
import { type ReactNode, useContext } from 'react';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { IconArrowNarrowDown, IconArrowNarrowUp } from '@/ui/icon/index';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBarContext } from '../contexts/ViewBarContext';
import { useRemoveFilter } from '../hooks/useRemoveFilter';
@ -24,7 +24,6 @@ import { AddFilterFromDropdownButton } from './AddFilterFromDetailsButton';
import SortOrFilterChip from './SortOrFilterChip';
export type ViewBarDetailsProps = {
context: Context<string | null>;
hasFilterButton?: boolean;
rightComponent?: ReactNode;
};
@ -97,19 +96,23 @@ const StyledAddFilterContainer = styled.div`
z-index: 5;
`;
function ViewBarDetails({
context,
export function ViewBarDetails({
hasFilterButton = false,
rightComponent,
}: ViewBarDetailsProps) {
const { canPersistViewFields, onViewBarReset } = useContext(ViewBarContext);
const recoilScopeId = useContextScopeId(context);
const { canPersistViewFields, onViewBarReset, ViewBarRecoilScopeContext } =
useContext(ViewBarContext);
const currentViewId = useRecoilScopedValue(currentViewIdScopedState, context);
const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
ViewBarRecoilScopeContext,
);
const [filters, setFilters] = useRecoilScopedState(
filtersScopedState,
context,
ViewBarRecoilScopeContext,
);
const savedFilters = useRecoilValue(
@ -120,16 +123,25 @@ function ViewBarDetails({
const [availableFilters] = useRecoilScopedState(
availableFiltersScopedState,
context,
ViewBarRecoilScopeContext,
);
const canPersistFilters = useRecoilValue(
canPersistFiltersScopedFamilySelector([recoilScopeId, currentViewId]),
canPersistFiltersScopedFamilySelector({
recoilScopeId,
viewId: currentViewId,
}),
);
const [sorts, setSorts] = useRecoilScopedState(sortsScopedState, context);
const [sorts, setSorts] = useRecoilScopedState(
sortsScopedState,
ViewBarRecoilScopeContext,
);
const canPersistSorts = useRecoilValue(
canPersistSortsScopedFamilySelector([recoilScopeId, currentViewId]),
canPersistSortsScopedFamilySelector({
recoilScopeId,
viewId: currentViewId,
}),
);
const canPersistView =
@ -137,7 +149,7 @@ function ViewBarDetails({
const [isViewBarExpanded] = useRecoilScopedState(
isViewBarExpandedScopedState,
context,
ViewBarRecoilScopeContext,
);
const filtersWithDefinition = filters.map((filter) => {
@ -151,7 +163,8 @@ function ViewBarDetails({
};
});
const removeFilter = useRemoveFilter(context);
const removeFilter = useRemoveFilter();
function handleCancelClick() {
onViewBarReset?.();
setFilters(savedFilters);
@ -231,5 +244,3 @@ function ViewBarDetails({
</StyledBar>
);
}
export default ViewBarDetails;

View File

@ -1,4 +1,4 @@
import { type Context, type MouseEvent, useContext } from 'react';
import { type MouseEvent, useContext } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRecoilCallback, useSetRecoilState } from 'recoil';
@ -19,9 +19,9 @@ import {
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { MOBILE_VIEWPORT } from '@/ui/theme/constants/theme';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
@ -72,24 +72,27 @@ const StyledViewName = styled.span`
export type ViewsDropdownButtonProps = {
hotkeyScope: HotkeyScope;
onViewEditModeChange?: () => void;
scopeContext: Context<string | null>;
};
export const ViewsDropdownButton = ({
hotkeyScope,
onViewEditModeChange,
scopeContext,
}: ViewsDropdownButtonProps) => {
const theme = useTheme();
const { defaultViewName, onViewSelect } = useContext(ViewBarContext);
const recoilScopeId = useContextScopeId(scopeContext);
const { defaultViewName, onViewSelect, ViewBarRecoilScopeContext } =
useContext(ViewBarContext);
const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
const currentView = useRecoilScopedValue(
currentViewScopedSelector,
scopeContext,
ViewBarRecoilScopeContext,
);
const [views] = useRecoilScopedState(
viewsScopedState,
ViewBarRecoilScopeContext,
);
const [views] = useRecoilScopedState(viewsScopedState, scopeContext);
const { isDropdownButtonOpen, closeDropdownButton, toggleDropdownButton } =
useDropdownButton({
@ -134,7 +137,7 @@ export const ViewsDropdownButton = ({
closeDropdownButton();
};
const { removeView } = useRemoveView({ scopeContext });
const { removeView } = useRemoveView();
const handleDeleteViewButtonClick = async (
event: MouseEvent<HTMLButtonElement>,

View File

@ -1,5 +1,7 @@
import { createContext } from 'react';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import type { View } from '../types/View';
export const ViewBarContext = createContext<{
@ -11,4 +13,8 @@ export const ViewBarContext = createContext<{
onViewEdit?: (view: View) => void | Promise<void>;
onViewRemove?: (viewId: string) => void | Promise<void>;
onViewSelect?: (viewId: string) => void | Promise<void>;
}>({});
onImport?: () => void | Promise<void>;
ViewBarRecoilScopeContext: RecoilScopeContext;
}>({
ViewBarRecoilScopeContext: createContext<string | null>(null),
});

View File

@ -1,16 +1,23 @@
import { Context, useMemo } from 'react';
import { useMemo } from 'react';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
import { filtersScopedState } from '../states/filtersScopedState';
export function useFilterCurrentlyEdited(context: Context<string | null>) {
const [filters] = useRecoilScopedState(filtersScopedState, context);
import { useViewBarContext } from './useViewBarContext';
export function useFilterCurrentlyEdited() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filters] = useRecoilScopedState(
filtersScopedState,
ViewBarRecoilScopeContext,
);
const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState,
context,
ViewBarRecoilScopeContext,
);
return useMemo(() => {

View File

@ -1,11 +1,17 @@
import { Context } from 'react';
import { useContext } from 'react';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { ViewBarContext } from '../contexts/ViewBarContext';
import { filtersScopedState } from '../states/filtersScopedState';
export function useRemoveFilter(context: Context<string | null>) {
const [, setFilters] = useRecoilScopedState(filtersScopedState, context);
export function useRemoveFilter() {
const { ViewBarRecoilScopeContext } = useContext(ViewBarContext);
const [, setFilters] = useRecoilScopedState(
filtersScopedState,
ViewBarRecoilScopeContext,
);
return function removeFilter(filterKey: string) {
setFilters((filters) => {

View File

@ -1,19 +1,17 @@
import { type Context, useContext } from 'react';
import { useContext } from 'react';
import { useRecoilCallback } from 'recoil';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBarContext } from '../contexts/ViewBarContext';
import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
import { viewsScopedState } from '../states/viewsScopedState';
export const useRemoveView = ({
scopeContext,
}: {
scopeContext: Context<string | null>;
}) => {
const { onViewRemove } = useContext(ViewBarContext);
const recoilScopeId = useContextScopeId(scopeContext);
export const useRemoveView = () => {
const { onViewRemove, ViewBarRecoilScopeContext } =
useContext(ViewBarContext);
const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
const removeView = useRecoilCallback(
({ set, snapshot }) =>

View File

@ -1,4 +1,3 @@
import { Context } from 'react';
import { produce } from 'immer';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
@ -6,8 +5,15 @@ import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoi
import { filtersScopedState } from '../states/filtersScopedState';
import { Filter } from '../types/Filter';
export function useUpsertFilter(context: Context<string | null>) {
const [, setFilters] = useRecoilScopedState(filtersScopedState, context);
import { useViewBarContext } from './useViewBarContext';
export function useUpsertFilter() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [, setFilters] = useRecoilScopedState(
filtersScopedState,
ViewBarRecoilScopeContext,
);
return function upsertFilter(filterToUpsert: Filter) {
setFilters((filters) => {

View File

@ -1,9 +1,9 @@
import { type Context, useContext } from 'react';
import { useContext } from 'react';
import { useRecoilCallback, useRecoilValue, useResetRecoilState } from 'recoil';
import { v4 } from 'uuid';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBarContext } from '../contexts/ViewBarContext';
import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
@ -16,16 +16,19 @@ import { sortsScopedState } from '../states/sortsScopedState';
import { viewEditModeState } from '../states/viewEditModeState';
import { viewsScopedState } from '../states/viewsScopedState';
export const useUpsertView = ({
scopeContext,
}: {
scopeContext: Context<string | null>;
}) => {
const { onViewCreate, onViewEdit } = useContext(ViewBarContext);
const recoilScopeId = useContextScopeId(scopeContext);
export const useUpsertView = () => {
const { onViewCreate, onViewEdit, ViewBarRecoilScopeContext } =
useContext(ViewBarContext);
const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
const filters = useRecoilScopedValue(filtersScopedState, scopeContext);
const sorts = useRecoilScopedValue(sortsScopedState, scopeContext);
const filters = useRecoilScopedValue(
filtersScopedState,
ViewBarRecoilScopeContext,
);
const sorts = useRecoilScopedValue(
sortsScopedState,
ViewBarRecoilScopeContext,
);
const viewEditMode = useRecoilValue(viewEditModeState);
const resetViewEditMode = useResetRecoilState(viewEditModeState);

View File

@ -0,0 +1,7 @@
import { useContext } from 'react';
import { ViewBarContext } from '../contexts/ViewBarContext';
export const useViewBarContext = () => {
return useContext(ViewBarContext);
};

View File

@ -8,10 +8,16 @@ import { savedFiltersFamilyState } from '../savedFiltersFamilyState';
export const canPersistFiltersScopedFamilySelector = selectorFamily({
key: 'canPersistFiltersScopedFamilySelector',
get:
([scopeId, viewId]: [string, string | undefined]) =>
({
recoilScopeId,
viewId,
}: {
recoilScopeId: string;
viewId: string | undefined;
}) =>
({ get }) =>
!isDeeplyEqual(
get(savedFiltersFamilyState(viewId)),
get(filtersScopedState(scopeId)),
get(filtersScopedState(recoilScopeId)),
),
});

View File

@ -8,10 +8,16 @@ import { sortsScopedState } from '../sortsScopedState';
export const canPersistSortsScopedFamilySelector = selectorFamily({
key: 'canPersistSortsScopedFamilySelector',
get:
([scopeId, viewId]: [string, string | undefined]) =>
({
recoilScopeId,
viewId,
}: {
recoilScopeId: string;
viewId: string | undefined;
}) =>
({ get }) =>
!isDeeplyEqual(
get(savedSortsFamilyState(viewId)),
get(sortsScopedState(scopeId)),
get(sortsScopedState(recoilScopeId)),
),
});

View File

@ -46,9 +46,6 @@ export function FilterDropdownUserSearchSelect({
});
return (
<FilterDropdownEntitySearchSelect
entitiesForSelect={usersForSelect}
context={context}
/>
<FilterDropdownEntitySearchSelect entitiesForSelect={usersForSelect} />
);
}

View File

@ -1,6 +1,6 @@
import { type Context } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import { availableBoardCardFieldsScopedState } from '@/ui/board/states/availableBoardCardFieldsScopedState';
import { boardCardFieldsScopedState } from '@/ui/board/states/boardCardFieldsScopedState';
import { savedBoardCardFieldsFamilyState } from '@/ui/board/states/savedBoardCardFieldsFamilyState';
@ -35,23 +35,26 @@ const toViewFieldInput = (
export const useBoardViewFields = ({
objectId,
fieldDefinitions,
scopeContext,
skipFetch,
RecoilScopeContext,
}: {
objectId: 'company' | 'person';
fieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
scopeContext: Context<string | null>;
skipFetch?: boolean;
RecoilScopeContext: RecoilScopeContext;
}) => {
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
scopeContext,
RecoilScopeContext,
);
const [availableBoardCardFields, setAvailableBoardCardFields] =
useRecoilScopedState(availableBoardCardFieldsScopedState, scopeContext);
useRecoilScopedState(
availableBoardCardFieldsScopedState,
RecoilScopeContext,
);
const [boardCardFields, setBoardCardFields] = useRecoilScopedState(
boardCardFieldsScopedState,
scopeContext,
RecoilScopeContext,
);
const setSavedBoardCardFields = useSetRecoilState(
savedBoardCardFieldsFamilyState(currentViewId),

View File

@ -1,5 +1,4 @@
import type { Context } from 'react';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import { boardCardFieldsScopedState } from '@/ui/board/states/boardCardFieldsScopedState';
import type {
ViewFieldDefinition,
@ -18,41 +17,41 @@ import { useViewSorts } from './useViewSorts';
export const useBoardViews = ({
fieldDefinitions,
objectId,
scopeContext,
RecoilScopeContext,
}: {
fieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
objectId: 'company';
scopeContext: Context<string | null>;
RecoilScopeContext: RecoilScopeContext;
}) => {
const boardCardFields = useRecoilScopedValue(
boardCardFieldsScopedState,
scopeContext,
RecoilScopeContext,
);
const filters = useRecoilScopedValue(filtersScopedState, scopeContext);
const sorts = useRecoilScopedValue(sortsScopedState, scopeContext);
const filters = useRecoilScopedValue(filtersScopedState, RecoilScopeContext);
const sorts = useRecoilScopedValue(sortsScopedState, RecoilScopeContext);
const { createView, deleteView, isFetchingViews, updateView } = useViews({
objectId,
onViewCreate: handleViewCreate,
type: ViewType.Pipeline,
scopeContext,
RecoilScopeContext,
});
const { createViewFields, persistCardFields } = useBoardViewFields({
objectId,
fieldDefinitions,
scopeContext,
skipFetch: isFetchingViews,
RecoilScopeContext,
});
const { createViewFilters, persistFilters } = useViewFilters({
scopeContext,
skipFetch: isFetchingViews,
RecoilScopeContext,
});
const { createViewSorts, persistSorts } = useViewSorts({
scopeContext,
skipFetch: isFetchingViews,
RecoilScopeContext,
});
async function handleViewCreate(viewId: string) {

View File

@ -33,7 +33,7 @@ export const useTableViews = ({
objectId,
onViewCreate: handleViewCreate,
type: ViewType.Table,
scopeContext: TableRecoilScopeContext,
RecoilScopeContext: TableRecoilScopeContext,
});
const { createViewFields, persistColumns } = useTableViewFields({
objectId,
@ -41,11 +41,11 @@ export const useTableViews = ({
skipFetch: isFetchingViews,
});
const { createViewFilters, persistFilters } = useViewFilters({
scopeContext: TableRecoilScopeContext,
RecoilScopeContext: TableRecoilScopeContext,
skipFetch: isFetchingViews,
});
const { createViewSorts, persistSorts } = useViewSorts({
scopeContext: TableRecoilScopeContext,
RecoilScopeContext: TableRecoilScopeContext,
skipFetch: isFetchingViews,
});

View File

@ -1,6 +1,7 @@
import { Context, useCallback } from 'react';
import { useCallback } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { availableFiltersScopedState } from '@/ui/view-bar/states/availableFiltersScopedState';
@ -18,23 +19,23 @@ import {
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useViewFilters = ({
scopeContext,
RecoilScopeContext,
skipFetch,
}: {
scopeContext: Context<string | null>;
RecoilScopeContext: RecoilScopeContext;
skipFetch?: boolean;
}) => {
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
scopeContext,
RecoilScopeContext,
);
const [filters, setFilters] = useRecoilScopedState(
filtersScopedState,
scopeContext,
RecoilScopeContext,
);
const [availableFilters] = useRecoilScopedState(
availableFiltersScopedState,
scopeContext,
RecoilScopeContext,
);
const [, setSavedFilters] = useRecoilState(
savedFiltersFamilyState(currentViewId),

View File

@ -1,6 +1,7 @@
import { Context, useCallback } from 'react';
import { useCallback } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { availableSortsScopedState } from '@/ui/view-bar/states/availableSortsScopedState';
@ -19,23 +20,23 @@ import {
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useViewSorts = ({
scopeContext,
RecoilScopeContext,
skipFetch,
}: {
scopeContext: Context<string | null>;
RecoilScopeContext: RecoilScopeContext;
skipFetch?: boolean;
}) => {
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
scopeContext,
RecoilScopeContext,
);
const [sorts, setSorts] = useRecoilScopedState(
sortsScopedState,
scopeContext,
RecoilScopeContext,
);
const [availableSorts] = useRecoilScopedState(
availableSortsScopedState,
scopeContext,
RecoilScopeContext,
);
const [, setSavedSorts] = useRecoilState(
savedSortsFamilyState(currentViewId),

View File

@ -1,7 +1,7 @@
import type { Context } from 'react';
import { getOperationName } from '@apollo/client/utilities';
import { useRecoilCallback } from 'recoil';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import { savedBoardCardFieldsFamilyState } from '@/ui/board/states/savedBoardCardFieldsFamilyState';
import { savedTableColumnsFamilyState } from '@/ui/table/states/savedTableColumnsFamilyState';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
@ -24,21 +24,21 @@ import { GET_VIEWS } from '../graphql/queries/getViews';
export const useViews = ({
objectId,
onViewCreate,
scopeContext,
RecoilScopeContext,
type,
}: {
objectId: 'company' | 'person';
onViewCreate?: (viewId: string) => Promise<void>;
scopeContext: Context<string | null>;
RecoilScopeContext: RecoilScopeContext;
type: ViewType;
}) => {
const [currentViewId, setCurrentViewId] = useRecoilScopedState(
currentViewIdScopedState,
scopeContext,
RecoilScopeContext,
);
const [views, setViews] = useRecoilScopedState(
viewsScopedState,
scopeContext,
RecoilScopeContext,
);
const [createViewMutation] = useCreateViewMutation();

View File

@ -58,7 +58,7 @@ export function Companies() {
<SpreadsheetImportProvider>
<PageContainer>
<PageHeader title="Companies" Icon={IconBuildingSkyscraper}>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</RecoilScope>
@ -66,7 +66,7 @@ export function Companies() {
<PageBody>
<RecoilScope
scopeId="companies"
SpecificContext={TableRecoilScopeContext}
CustomRecoilScopeContext={TableRecoilScopeContext}
>
<StyledTableContainer>
<CompanyTable />

View File

@ -18,7 +18,7 @@ export function CompaniesMockMode() {
<PageContainer>
<PageHeader title="Companies" Icon={IconBuildingSkyscraper} />
<PageBody>
<RecoilScope SpecificContext={TableRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={TableRecoilScopeContext}>
<StyledTableContainer>
<CompanyTableMockMode />
</StyledTableContainer>

View File

@ -63,7 +63,7 @@ export function CompanyShow() {
hasBackButton
Icon={IconBuildingSkyscraper}
>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageFavoriteButton
isFavorite={isFavorite}
onClick={handleFavoriteButtonClick}
@ -78,7 +78,7 @@ export function CompanyShow() {
</RecoilScope>
</PageHeader>
<PageBody>
<RecoilScope SpecificContext={ShowPageRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={ShowPageRecoilScopeContext}>
<ShowPageContainer>
<ShowPageLeftContainer>
<ShowPageSummaryCard

View File

@ -44,7 +44,7 @@ export function Opportunities() {
<PageContainer>
<RecoilScope>
<PageHeader title="Opportunities" Icon={IconTargetArrow}>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PipelineAddButton />
</RecoilScope>
</PageHeader>
@ -52,7 +52,7 @@ export function Opportunities() {
<BoardOptionsContext.Provider value={opportunitiesBoardOptions}>
<RecoilScope
scopeId="opportunities"
SpecificContext={CompanyBoardRecoilScopeContext}
CustomRecoilScopeContext={CompanyBoardRecoilScopeContext}
>
<CompanyBoard
onColumnAdd={handlePipelineStageAdd}

View File

@ -1,5 +1,4 @@
import { FilterDropdownCompanySearchSelect } from '@/companies/components/FilterDropdownCompanySearchSelect';
import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
import {
IconBuildingSkyscraper,
IconCalendarEvent,
@ -30,21 +29,13 @@ export const opportunitiesFilters: FilterDefinitionByEntity<PipelineProgress>[]
label: 'Company',
Icon: IconBuildingSkyscraper,
type: 'entity',
entitySelectComponent: (
<FilterDropdownCompanySearchSelect
context={CompanyBoardRecoilScopeContext}
/>
),
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
},
{
key: 'pointOfContactId',
label: 'Point of contact',
Icon: IconUser,
type: 'entity',
entitySelectComponent: (
<FilterDropdownPeopleSearchSelect
context={CompanyBoardRecoilScopeContext}
/>
),
entitySelectComponent: <FilterDropdownPeopleSearchSelect />,
},
];

View File

@ -54,7 +54,7 @@ export function People() {
<SpreadsheetImportProvider>
<PageContainer>
<PageHeader title="People" Icon={IconUser}>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</RecoilScope>
@ -62,7 +62,7 @@ export function People() {
<PageBody>
<RecoilScope
scopeId="people"
SpecificContext={TableRecoilScopeContext}
CustomRecoilScopeContext={TableRecoilScopeContext}
>
<StyledTableContainer>
<PeopleTable />

View File

@ -78,7 +78,7 @@ export function PersonShow() {
<PageContainer>
<PageTitle title={person.displayName || 'No Name'} />
<PageHeader title={person.firstName ?? ''} Icon={IconUser} hasBackButton>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageFavoriteButton
isFavorite={isFavorite}
onClick={handleFavoriteButtonClick}
@ -101,7 +101,7 @@ export function PersonShow() {
</RecoilScope>
</PageHeader>
<PageBody>
<RecoilScope SpecificContext={ShowPageRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={ShowPageRecoilScopeContext}>
<ShowPageContainer>
<ShowPageLeftContainer>
<ShowPageSummaryCard

View File

@ -7,7 +7,6 @@ import {
IconPhone,
IconUser,
} from '@/ui/icon/index';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { FilterDefinitionByEntity } from '@/ui/view-bar/types/FilterDefinitionByEntity';
import { Person } from '~/generated/graphql';
@ -35,9 +34,8 @@ export const peopleFilters: FilterDefinitionByEntity<Person>[] = [
label: 'Company',
Icon: IconBuildingSkyscraper,
type: 'entity',
entitySelectComponent: (
<FilterDropdownCompanySearchSelect context={TableRecoilScopeContext} />
),
// TODO: replace this with a component that selects the dropdown to use based on the entity type
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
},
{
key: 'phone',

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