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) { export function ActivityAssigneeEditableField({ activity }: OwnProps) {
return ( return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}> <RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<RecoilScope> <RecoilScope>
<EditableField <EditableField
customEditHotkeyScope={{ customEditHotkeyScope={{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@ import { graphqlMocks } from '~/testing/graphqlMocks';
import { mockedPipelineProgressData } from '~/testing/mock-data/pipeline-progress'; import { mockedPipelineProgressData } from '~/testing/mock-data/pipeline-progress';
import { HooksCompanyBoardEffect } from '../components/HooksCompanyBoardEffect'; import { HooksCompanyBoardEffect } from '../components/HooksCompanyBoardEffect';
import { BoardContext } from '../states/contexts/BoardContext';
import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext'; import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
const meta: Meta<typeof CompanyBoardCard> = { const meta: Meta<typeof CompanyBoardCard> = {
@ -24,7 +25,7 @@ const meta: Meta<typeof CompanyBoardCard> = {
(Story, context) => { (Story, context) => {
const [, setBoardCardFields] = useRecoilScopedState( const [, setBoardCardFields] = useRecoilScopedState(
boardCardFieldsScopedState, boardCardFieldsScopedState,
context.parameters.recoilScopeContext, context.parameters.customRecoilScopeContext,
); );
useEffect(() => { useEffect(() => {
@ -32,9 +33,14 @@ const meta: Meta<typeof CompanyBoardCard> = {
}, [setBoardCardFields]); }, [setBoardCardFields]);
return ( return (
<> <RecoilScope CustomRecoilScopeContext={BoardColumnRecoilScopeContext}>
<HooksCompanyBoardEffect /> <BoardContext.Provider
<RecoilScope SpecificContext={BoardColumnRecoilScopeContext}> value={{
BoardRecoilScopeContext:
context.parameters.customRecoilScopeContext,
}}
>
<HooksCompanyBoardEffect />
<BoardCardIdContext.Provider <BoardCardIdContext.Provider
value={mockedPipelineProgressData[1].id} value={mockedPipelineProgressData[1].id}
> >
@ -42,18 +48,18 @@ const meta: Meta<typeof CompanyBoardCard> = {
<Story /> <Story />
</MemoryRouter> </MemoryRouter>
</BoardCardIdContext.Provider> </BoardCardIdContext.Provider>
</RecoilScope> </BoardContext.Provider>
</> </RecoilScope>
); );
}, },
ComponentWithRecoilScopeDecorator, ComponentWithRecoilScopeDecorator,
ComponentDecorator, ComponentDecorator,
], ],
args: { scopeContext: CompanyBoardRecoilScopeContext }, args: {},
argTypes: { scopeContext: { control: false } }, argTypes: {},
parameters: { parameters: {
msw: graphqlMocks, 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 { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions';
import { import {
EntityBoard, EntityBoard,
@ -22,35 +23,43 @@ export const CompanyBoard = ({
onColumnDelete, onColumnDelete,
onEditColumnTitle, onEditColumnTitle,
}: CompanyBoardProps) => { }: 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 } = const { createView, deleteView, submitCurrentView, updateView } =
useBoardViews({ useBoardViews({
objectId: 'company', objectId: 'company',
scopeContext: CompanyBoardRecoilScopeContext, RecoilScopeContext: CompanyBoardRecoilScopeContext,
fieldDefinitions: pipelineAvailableFieldDefinitions, fieldDefinitions: pipelineAvailableFieldDefinitions,
}); });
return ( return (
<> <>
<HooksCompanyBoardEffect /> <BoardContext.Provider
<ViewBarContext.Provider
value={{ value={{
defaultViewName: 'All Opportunities', BoardRecoilScopeContext: CompanyBoardRecoilScopeContext,
onCurrentViewSubmit: submitCurrentView,
onViewCreate: createView,
onViewEdit: updateView,
onViewRemove: deleteView,
}} }}
> >
<EntityBoard <HooksCompanyBoardEffect />
boardOptions={opportunitiesBoardOptions} <ViewBarContext.Provider
onColumnAdd={onColumnAdd} value={{
onColumnDelete={onColumnDelete} defaultViewName: 'All Opportunities',
onEditColumnTitle={onEditColumnTitle} onCurrentViewSubmit: submitCurrentView,
scopeContext={CompanyBoardRecoilScopeContext} onViewCreate: createView,
/> onViewEdit: updateView,
</ViewBarContext.Provider> onViewRemove: deleteView,
<EntityBoardActionBar /> ViewBarRecoilScopeContext: CompanyBoardRecoilScopeContext,
<EntityBoardContextMenu /> }}
>
<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 styled from '@emotion/styled';
import { useRecoilState } from 'recoil'; import { useRecoilState } from 'recoil';
import { BoardCardIdContext } from '@/ui/board/contexts/BoardCardIdContext'; import { BoardCardIdContext } from '@/ui/board/contexts/BoardCardIdContext';
import { useBoardContext } from '@/ui/board/hooks/useBoardContext';
import { useCurrentCardSelected } from '@/ui/board/hooks/useCurrentCardSelected'; import { useCurrentCardSelected } from '@/ui/board/hooks/useCurrentCardSelected';
import { visibleBoardCardFieldsScopedSelector } from '@/ui/board/states/selectors/visibleBoardCardFieldsScopedSelector'; import { visibleBoardCardFieldsScopedSelector } from '@/ui/board/states/selectors/visibleBoardCardFieldsScopedSelector';
import { EntityChipVariant } from '@/ui/chip/components/EntityChip'; import { EntityChipVariant } from '@/ui/chip/components/EntityChip';
@ -19,10 +20,6 @@ import { companyProgressesFamilyState } from '../states/companyProgressesFamilyS
import { CompanyChip } from './CompanyChip'; import { CompanyChip } from './CompanyChip';
type OwnProps = {
scopeContext: Context<string | null>;
};
const StyledBoardCard = styled.div<{ selected: boolean }>` const StyledBoardCard = styled.div<{ selected: boolean }>`
background-color: ${({ theme, selected }) => background-color: ${({ theme, selected }) =>
selected ? theme.accent.quaternary : theme.background.secondary}; selected ? theme.accent.quaternary : theme.background.secondary};
@ -103,7 +100,9 @@ const StyledFieldContainer = styled.div`
width: 100%; width: 100%;
`; `;
export function CompanyBoardCard({ scopeContext }: OwnProps) { export function CompanyBoardCard() {
const { BoardRecoilScopeContext } = useBoardContext();
const { currentCardSelected, setCurrentCardSelected } = const { currentCardSelected, setCurrentCardSelected } =
useCurrentCardSelected(); useCurrentCardSelected();
const boardCardId = useContext(BoardCardIdContext); const boardCardId = useContext(BoardCardIdContext);
@ -115,7 +114,7 @@ export function CompanyBoardCard({ scopeContext }: OwnProps) {
const visibleBoardCardFields = useRecoilScopedValue( const visibleBoardCardFields = useRecoilScopedValue(
visibleBoardCardFieldsScopedSelector, visibleBoardCardFieldsScopedSelector,
scopeContext, BoardRecoilScopeContext,
); );
// boardCardId check can be moved to a wrapper to avoid unnecessary logic above // 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 { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { FilterDropdownEntitySearchSelect } from '@/ui/view-bar/components/FilterDropdownEntitySearchSelect'; 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 { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filterDropdownSearchInputScopedState';
import { filterDropdownSelectedEntityIdScopedState } from '@/ui/view-bar/states/filterDropdownSelectedEntityIdScopedState'; import { filterDropdownSelectedEntityIdScopedState } from '@/ui/view-bar/states/filterDropdownSelectedEntityIdScopedState';
import { useFilteredSearchCompanyQuery } from '../hooks/useFilteredSearchCompanyQuery'; import { useFilteredSearchCompanyQuery } from '../hooks/useFilteredSearchCompanyQuery';
export function FilterDropdownCompanySearchSelect({ export function FilterDropdownCompanySearchSelect() {
context, const { ViewBarRecoilScopeContext } = useViewBarContext();
}: {
context: Context<string | null>;
}) {
const filterDropdownSearchInput = useRecoilScopedValue( const filterDropdownSearchInput = useRecoilScopedValue(
filterDropdownSearchInputScopedState, filterDropdownSearchInputScopedState,
context, ViewBarRecoilScopeContext,
); );
const [filterDropdownSelectedEntityId] = useRecoilScopedState( const [filterDropdownSelectedEntityId] = useRecoilScopedState(
filterDropdownSelectedEntityIdScopedState, filterDropdownSelectedEntityIdScopedState,
context, ViewBarRecoilScopeContext,
); );
const usersForSelect = useFilteredSearchCompanyQuery({ const usersForSelect = useFilteredSearchCompanyQuery({
@ -31,9 +28,6 @@ export function FilterDropdownCompanySearchSelect({
}); });
return ( return (
<FilterDropdownEntitySearchSelect <FilterDropdownEntitySearchSelect entitiesForSelect={usersForSelect} />
entitiesForSelect={usersForSelect}
context={context}
/>
); );
} }

View File

@ -60,7 +60,7 @@ export function CompanyNameEditableField({ company }: OwnProps) {
} }
return ( return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}> <RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<StyledEditableTitleInput <StyledEditableTitleInput
autoComplete="off" autoComplete="off"
onChange={(event) => handleChange(event.target.value)} 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 { setContextMenuEntries } = useCompanyTableContextMenuEntries();
const { setActionBarEntries } = useCompanyTableActionBarEntries(); const { setActionBarEntries } = useCompanyTableActionBarEntries();
function handleImport() {
openCompanySpreadsheetImport();
}
return ( return (
<> <>
<EntityTableEffect <EntityTableEffect
@ -70,10 +66,11 @@ export function CompanyTable() {
onViewCreate: createView, onViewCreate: createView,
onViewEdit: updateView, onViewEdit: updateView,
onViewRemove: deleteView, onViewRemove: deleteView,
onImport: openCompanySpreadsheetImport,
ViewBarRecoilScopeContext: TableRecoilScopeContext,
}} }}
> >
<EntityTable <EntityTable
onImport={handleImport}
updateEntityMutation={({ updateEntityMutation={({
variables, variables,
}: { }: {

View File

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

View File

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

View File

@ -46,7 +46,7 @@ export function PeopleFullNameEditableField({ people }: OwnProps) {
} }
return ( return (
<RecoilScope SpecificContext={FieldRecoilScopeContext}> <RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<DoubleTextInputEdit <DoubleTextInputEdit
firstValuePlaceholder="Empty" firstValuePlaceholder="Empty"
secondValuePlaceholder="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 { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState'; import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState';
import { currentPageLocationState } from '@/ui/utilities/loading-state/states/currentPageLocationState'; 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 { availableFiltersScopedState } from '@/ui/view-bar/states/availableFiltersScopedState';
import { GetPeopleQuery } from '~/generated/graphql'; import { GetPeopleQuery } from '~/generated/graphql';
import { peopleFilters } from '~/pages/people/people-filters'; import { peopleFilters } from '~/pages/people/people-filters';
@ -24,7 +24,7 @@ import { peoplePhoneFamilyState } from '../states/peoplePhoneFamilyState';
export function useSetPeopleEntityTable() { export function useSetPeopleEntityTable() {
const resetTableRowSelection = useResetTableRowSelection(); const resetTableRowSelection = useResetTableRowSelection();
const tableContextScopeId = useContextScopeId(TableRecoilScopeContext); const tableContextScopeId = useRecoilScopeId(TableRecoilScopeContext);
const currentLocation = useLocation().pathname; const currentLocation = useLocation().pathname;

View File

@ -69,10 +69,11 @@ export function PeopleTable() {
onViewCreate: createView, onViewCreate: createView,
onViewEdit: updateView, onViewEdit: updateView,
onViewRemove: deleteView, onViewRemove: deleteView,
onImport: handleImport,
ViewBarRecoilScopeContext: TableRecoilScopeContext,
}} }}
> >
<EntityTable <EntityTable
onImport={handleImport}
updateEntityMutation={({ updateEntityMutation={({
variables, 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, component: FilledActionBar,
decorators: [ decorators: [
(Story) => ( (Story) => (
<RecoilScope SpecificContext={TableRecoilScopeContext}> <RecoilScope CustomRecoilScopeContext={TableRecoilScopeContext}>
<CompanyTableMockMode /> <CompanyTableMockMode />
<MemoryRouter> <MemoryRouter>
<Story /> <Story />

View File

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

View File

@ -10,13 +10,12 @@ import {
type BoardOptionsDropdownProps = Pick< type BoardOptionsDropdownProps = Pick<
BoardOptionsDropdownContentProps, BoardOptionsDropdownContentProps,
'customHotkeyScope' | 'onStageAdd' | 'scopeContext' 'customHotkeyScope' | 'onStageAdd'
>; >;
export function BoardOptionsDropdown({ export function BoardOptionsDropdown({
customHotkeyScope, customHotkeyScope,
onStageAdd, onStageAdd,
scopeContext,
}: BoardOptionsDropdownProps) { }: BoardOptionsDropdownProps) {
return ( return (
<DropdownButton <DropdownButton
@ -25,7 +24,6 @@ export function BoardOptionsDropdown({
<BoardOptionsDropdownContent <BoardOptionsDropdownContent
customHotkeyScope={customHotkeyScope} customHotkeyScope={customHotkeyScope}
onStageAdd={onStageAdd} onStageAdd={onStageAdd}
scopeContext={scopeContext}
/> />
} }
dropdownHotkeyScope={customHotkeyScope} 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 { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil'; import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { BoardContext } from '@/companies/states/contexts/BoardContext';
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader'; import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput'; import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu'; 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 { ThemeColor } from '@/ui/theme/constants/colors';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; 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 { 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 { ViewFieldsVisibilityDropdownSection } from '@/ui/view-bar/components/ViewFieldsVisibilityDropdownSection';
import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView'; import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector'; import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
@ -42,7 +43,6 @@ import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
export type BoardOptionsDropdownContentProps = { export type BoardOptionsDropdownContentProps = {
customHotkeyScope: HotkeyScope; customHotkeyScope: HotkeyScope;
onStageAdd?: (boardColumn: BoardColumnDefinition) => void; onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
scopeContext: Context<string | null>;
}; };
const StyledIconSettings = styled(IconSettings)` const StyledIconSettings = styled(IconSettings)`
@ -61,10 +61,13 @@ type ColumnForCreate = {
export function BoardOptionsDropdownContent({ export function BoardOptionsDropdownContent({
customHotkeyScope, customHotkeyScope,
onStageAdd, onStageAdd,
scopeContext,
}: BoardOptionsDropdownContentProps) { }: BoardOptionsDropdownContentProps) {
const theme = useTheme(); const theme = useTheme();
const scopeId = useContextScopeId(scopeContext);
const BoardRecoilScopeContext =
useContext(BoardContext).BoardRecoilScopeContext;
const boardRecoilScopeId = useRecoilScopeId(BoardRecoilScopeContext);
const stageInputRef = useRef<HTMLInputElement>(null); const stageInputRef = useRef<HTMLInputElement>(null);
const viewEditInputRef = useRef<HTMLInputElement>(null); const viewEditInputRef = useRef<HTMLInputElement>(null);
@ -77,16 +80,19 @@ export function BoardOptionsDropdownContent({
const hiddenBoardCardFields = useRecoilScopedValue( const hiddenBoardCardFields = useRecoilScopedValue(
hiddenBoardCardFieldsScopedSelector, hiddenBoardCardFieldsScopedSelector,
scopeContext, BoardRecoilScopeContext,
); );
const hasHiddenFields = hiddenBoardCardFields.length > 0; const hasHiddenFields = hiddenBoardCardFields.length > 0;
const visibleBoardCardFields = useRecoilScopedValue( const visibleBoardCardFields = useRecoilScopedValue(
visibleBoardCardFieldsScopedSelector, visibleBoardCardFieldsScopedSelector,
scopeContext, BoardRecoilScopeContext,
); );
const hasVisibleFields = visibleBoardCardFields.length > 0; const hasVisibleFields = visibleBoardCardFields.length > 0;
const viewsById = useRecoilScopedValue(viewsByIdScopedSelector, scopeContext); const viewsById = useRecoilScopedValue(
viewsByIdScopedSelector,
BoardRecoilScopeContext, // TODO: replace with ViewBarRecoilScopeContext
);
const viewEditMode = useRecoilValue(viewEditModeState); const viewEditMode = useRecoilValue(viewEditModeState);
const handleStageSubmit = () => { const handleStageSubmit = () => {
@ -107,13 +113,13 @@ export function BoardOptionsDropdownContent({
onStageAdd?.(columnToCreate); onStageAdd?.(columnToCreate);
}; };
const { upsertView } = useUpsertView({ scopeContext }); const { upsertView } = useUpsertView();
const handleViewNameSubmit = useRecoilCallback( const handleViewNameSubmit = useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>
async () => { async () => {
const boardCardFields = await snapshot.getPromise( const boardCardFields = await snapshot.getPromise(
boardCardFieldsScopedState(scopeId), boardCardFieldsScopedState(boardRecoilScopeId),
); );
const isCreateMode = viewEditMode.mode === 'create'; const isCreateMode = viewEditMode.mode === 'create';
const name = viewEditInputRef.current?.value; const name = viewEditInputRef.current?.value;
@ -123,7 +129,7 @@ export function BoardOptionsDropdownContent({
set(savedBoardCardFieldsFamilyState(view.id), boardCardFields); set(savedBoardCardFieldsFamilyState(view.id), boardCardFields);
} }
}, },
[scopeId, upsertView, viewEditMode.mode], [boardRecoilScopeId, upsertView, viewEditMode.mode],
); );
const resetMenu = () => setCurrentMenu(undefined); const resetMenu = () => setCurrentMenu(undefined);
@ -133,7 +139,7 @@ export function BoardOptionsDropdownContent({
setCurrentMenu(menu); setCurrentMenu(menu);
}; };
const { handleFieldVisibilityChange } = useBoardCardFields({ scopeContext }); const { handleFieldVisibilityChange } = useBoardCardFields();
const { closeDropdownButton } = useDropdownButton({ const { closeDropdownButton } = useDropdownButton({
dropdownId: BoardOptionsDropdownKey, 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 { getOperationName } from '@apollo/client/utilities';
import styled from '@emotion/styled'; 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 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; onColumnAdd?: (boardColumn: BoardColumnDefinition) => void;
onColumnDelete?: (boardColumnId: string) => void; onColumnDelete?: (boardColumnId: string) => void;
onEditColumnTitle: (columnId: string, title: string, color: string) => void; onEditColumnTitle: (columnId: string, title: string, color: string) => void;
scopeContext: Context<string | null>;
}; };
const StyledWrapper = styled.div` const StyledWrapper = styled.div`
@ -54,7 +53,6 @@ export function EntityBoard({
onColumnAdd, onColumnAdd,
onColumnDelete, onColumnDelete,
onEditColumnTitle, onEditColumnTitle,
scopeContext,
}: EntityBoardProps) { }: EntityBoardProps) {
const [boardColumns] = useRecoilState(boardColumnsState); const [boardColumns] = useRecoilState(boardColumnsState);
const setCardSelected = useSetCardSelected(); const setCardSelected = useSetCardSelected();
@ -130,14 +128,14 @@ export function EntityBoard({
return (boardColumns?.length ?? 0) > 0 ? ( return (boardColumns?.length ?? 0) > 0 ? (
<StyledWrapper> <StyledWrapper>
<StyledBoardHeader onStageAdd={onColumnAdd} scopeContext={scopeContext} /> <StyledBoardHeader onStageAdd={onColumnAdd} />
<ScrollWrapper> <ScrollWrapper>
<StyledBoard ref={boardRef}> <StyledBoard ref={boardRef}>
<DragDropContext onDragEnd={onDragEnd}> <DragDropContext onDragEnd={onDragEnd}>
{sortedBoardColumns.map((column) => ( {sortedBoardColumns.map((column) => (
<BoardColumnIdContext.Provider value={column.id} key={column.id}> <BoardColumnIdContext.Provider value={column.id} key={column.id}>
<RecoilScope <RecoilScope
SpecificContext={BoardColumnRecoilScopeContext} CustomRecoilScopeContext={BoardColumnRecoilScopeContext}
key={column.id} key={column.id}
> >
<EntityBoardColumn <EntityBoardColumn
@ -145,7 +143,6 @@ export function EntityBoard({
column={column} column={column}
onDelete={onColumnDelete} onDelete={onColumnDelete}
onTitleEdit={onEditColumnTitle} onTitleEdit={onEditColumnTitle}
scopeContext={scopeContext}
/> />
</RecoilScope> </RecoilScope>
</BoardColumnIdContext.Provider> </BoardColumnIdContext.Provider>

View File

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

View File

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

View File

@ -1,5 +1,3 @@
import type { Context } from 'react';
import type { import type {
ViewFieldDefinition, ViewFieldDefinition,
ViewFieldMetadata, ViewFieldMetadata,
@ -10,18 +8,18 @@ import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoi
import { boardCardFieldsScopedState } from '../states/boardCardFieldsScopedState'; import { boardCardFieldsScopedState } from '../states/boardCardFieldsScopedState';
import { boardCardFieldsByKeyScopedSelector } from '../states/selectors/boardCardFieldsByKeyScopedSelector'; import { boardCardFieldsByKeyScopedSelector } from '../states/selectors/boardCardFieldsByKeyScopedSelector';
export const useBoardCardFields = ({ import { useBoardContext } from './useBoardContext';
scopeContext,
}: { export const useBoardCardFields = () => {
scopeContext: Context<string | null>; const { BoardRecoilScopeContext } = useBoardContext();
}) => {
const [boardCardFields, setBoardCardFields] = useRecoilScopedState( const [boardCardFields, setBoardCardFields] = useRecoilScopedState(
boardCardFieldsScopedState, boardCardFieldsScopedState,
scopeContext, BoardRecoilScopeContext,
); );
const boardCardFieldsByKey = useRecoilScopedValue( const boardCardFieldsByKey = useRecoilScopedValue(
boardCardFieldsByKeyScopedSelector, boardCardFieldsByKeyScopedSelector,
scopeContext, BoardRecoilScopeContext,
); );
const handleFieldVisibilityChange = ( 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({ export const canPersistBoardCardFieldsScopedFamilySelector = selectorFamily({
key: 'canPersistBoardCardFieldsScopedFamilySelector', key: 'canPersistBoardCardFieldsScopedFamilySelector',
get: get:
([scopeId, viewId]: [string, string | undefined]) => ({
recoilScopeId,
viewId,
}: {
recoilScopeId: string;
viewId: string | undefined;
}) =>
({ get }) => ({ get }) =>
!isDeeplyEqual( !isDeeplyEqual(
get(savedBoardCardFieldsFamilyState(viewId)), 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 { FilterDefinitionByEntity } from '@/ui/view-bar/types/FilterDefinitionByEntity';
import { SortDefinition } from '@/ui/view-bar/types/SortDefinition'; import { SortDefinition } from '@/ui/view-bar/types/SortDefinition';
@ -6,7 +6,7 @@ import { PipelineProgress } from '~/generated/graphql';
export type BoardOptions = { export type BoardOptions = {
newCardComponent: React.ReactNode; newCardComponent: React.ReactNode;
CardComponent: ComponentType<{ scopeContext: Context<string | null> }>; CardComponent: ComponentType;
filters: FilterDefinitionByEntity<PipelineProgress>[]; filters: FilterDefinitionByEntity<PipelineProgress>[];
sorts: SortDefinition[]; sorts: SortDefinition[];
}; };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import { useRecoilCallback } from 'recoil'; 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 { numberOfTableRowsState } from '../states/numberOfTableRowsState';
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
@ -11,7 +11,7 @@ import { useSetSoftFocusPosition } from './useSetSoftFocusPosition';
// TODO: stories // TODO: stories
export function useMoveSoftFocus() { export function useMoveSoftFocus() {
const tableScopeId = useContextScopeId(TableRecoilScopeContext); const tableScopeId = useRecoilScopeId(TableRecoilScopeContext);
const setSoftFocusPosition = useSetSoftFocusPosition(); const setSoftFocusPosition = useSetSoftFocusPosition();
const moveUp = useRecoilCallback( 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 { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableEntitiesFamilyState } from '@/ui/table/states/tableEntitiesFamilyState'; import { tableEntitiesFamilyState } from '@/ui/table/states/tableEntitiesFamilyState';
import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState'; 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 { availableFiltersScopedState } from '@/ui/view-bar/states/availableFiltersScopedState';
import { availableSortsScopedState } from '@/ui/view-bar/states/availableSortsScopedState'; import { availableSortsScopedState } from '@/ui/view-bar/states/availableSortsScopedState';
import { FilterDefinition } from '@/ui/view-bar/types/FilterDefinition'; import { FilterDefinition } from '@/ui/view-bar/types/FilterDefinition';
@ -16,7 +16,7 @@ import { numberOfTableRowsState } from '../states/numberOfTableRowsState';
export function useSetEntityTableData() { export function useSetEntityTableData() {
const resetTableRowSelection = useResetTableRowSelection(); const resetTableRowSelection = useResetTableRowSelection();
const tableContextScopeId = useContextScopeId(TableRecoilScopeContext); const tableContextScopeId = useRecoilScopeId(TableRecoilScopeContext);
return useRecoilCallback( return useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>

View File

@ -10,12 +10,10 @@ import { TableOptionsDropdownButton } from './TableOptionsDropdownButton';
import { TableOptionsDropdownContent } from './TableOptionsDropdownContent'; import { TableOptionsDropdownContent } from './TableOptionsDropdownContent';
type TableOptionsDropdownProps = { type TableOptionsDropdownProps = {
onImport?: () => void;
customHotkeyScope: HotkeyScope; customHotkeyScope: HotkeyScope;
}; };
export function TableOptionsDropdown({ export function TableOptionsDropdown({
onImport,
customHotkeyScope, customHotkeyScope,
}: TableOptionsDropdownProps) { }: TableOptionsDropdownProps) {
const resetViewEditMode = useResetRecoilState(viewEditModeState); const resetViewEditMode = useResetRecoilState(viewEditModeState);
@ -25,7 +23,7 @@ export function TableOptionsDropdown({
buttonComponents={<TableOptionsDropdownButton />} buttonComponents={<TableOptionsDropdownButton />}
dropdownHotkeyScope={customHotkeyScope} dropdownHotkeyScope={customHotkeyScope}
dropdownId={TableOptionsDropdownId} dropdownId={TableOptionsDropdownId}
dropdownComponents={<TableOptionsDropdownContent onImport={onImport} />} dropdownComponents={<TableOptionsDropdownContent />}
onClickOutside={resetViewEditMode} 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 styled from '@emotion/styled';
import { useRecoilCallback, useRecoilValue, useResetRecoilState } from 'recoil'; import { useRecoilCallback, useRecoilValue, useResetRecoilState } from 'recoil';
import { Key } from 'ts-key-enum'; 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 { rgba } from '@/ui/theme/constants/colors';
import { textInputStyle } from '@/ui/theme/constants/effects'; import { textInputStyle } from '@/ui/theme/constants/effects';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; 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 { 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 { ViewFieldsVisibilityDropdownSection } from '@/ui/view-bar/components/ViewFieldsVisibilityDropdownSection';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView'; import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
import { currentViewScopedSelector } from '@/ui/view-bar/states/selectors/currentViewScopedSelector'; import { currentViewScopedSelector } from '@/ui/view-bar/states/selectors/currentViewScopedSelector';
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector'; 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 { tableColumnsScopedState } from '../../states/tableColumnsScopedState';
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope'; import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
type TableOptionsDropdownButtonProps = {
onImport?: () => void;
};
type TableOptionsMenu = 'fields'; type TableOptionsMenu = 'fields';
const StyledInputContainer = styled.div` const StyledInputContainer = styled.div`
@ -59,11 +56,10 @@ const StyledViewNameInput = styled.input`
} }
`; `;
export function TableOptionsDropdownContent({ export function TableOptionsDropdownContent() {
onImport, const scopeId = useRecoilScopeId(TableRecoilScopeContext);
}: TableOptionsDropdownButtonProps) {
const scopeId = useContextScopeId(TableRecoilScopeContext);
const { onImport } = useContext(ViewBarContext);
const { closeDropdownButton } = useDropdownButton({ const { closeDropdownButton } = useDropdownButton({
dropdownId: TableOptionsDropdownId, dropdownId: TableOptionsDropdownId,
}); });
@ -95,9 +91,7 @@ export function TableOptionsDropdownContent({
const { handleColumnVisibilityChange } = useTableColumns(); const { handleColumnVisibilityChange } = useTableColumns();
const { upsertView } = useUpsertView({ const { upsertView } = useUpsertView();
scopeContext: TableRecoilScopeContext,
});
const handleViewNameSubmit = useRecoilCallback( const handleViewNameSubmit = useRecoilCallback(
({ set, snapshot }) => ({ 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 { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { TableRecoilScopeContext } from '../../../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../../../states/recoil-scope-contexts/TableRecoilScopeContext';
@ -13,10 +14,16 @@ const meta: Meta<typeof TableOptionsDropdown> = {
component: TableOptionsDropdown, component: TableOptionsDropdown,
decorators: [ decorators: [
(Story) => ( (Story) => (
<RecoilScope SpecificContext={TableRecoilScopeContext}> <RecoilScope CustomRecoilScopeContext={TableRecoilScopeContext}>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}> <ViewBarContext.Provider
<Story /> value={{
</RecoilScope> ViewBarRecoilScopeContext: TableRecoilScopeContext,
}}
>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<Story />
</RecoilScope>
</ViewBarContext.Provider>
</RecoilScope> </RecoilScope>
), ),
ComponentDecorator, ComponentDecorator,

View File

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

View File

@ -1,23 +1,25 @@
import { Context, useRef } from 'react'; import { useRef } from 'react';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { type RecoilScopeContext as RecoilScopeContextType } from '@/types/RecoilScopeContext';
import { RecoilScopeContext } from '../states/RecoilScopeContext'; import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function RecoilScope({ export function RecoilScope({
children, children,
scopeId, scopeId,
SpecificContext, CustomRecoilScopeContext,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
scopeId?: string; scopeId?: string;
SpecificContext?: Context<string | null>; CustomRecoilScopeContext?: RecoilScopeContextType;
}) { }) {
const currentScopeId = useRef(scopeId ?? v4()); const currentScopeId = useRef(scopeId ?? v4());
return SpecificContext ? ( return CustomRecoilScopeContext ? (
<SpecificContext.Provider value={currentScopeId.current}> <CustomRecoilScopeContext.Provider value={currentScopeId.current}>
{children} {children}
</SpecificContext.Provider> </CustomRecoilScopeContext.Provider>
) : ( ) : (
<RecoilScopeContext.Provider value={currentScopeId.current}> <RecoilScopeContext.Provider value={currentScopeId.current}>
{children} {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>( export function useRecoilScopedFamilyState<StateType>(
recoilState: (familyUniqueId: string) => RecoilState<StateType>, recoilState: (familyUniqueId: string) => RecoilState<StateType>,
uniqueIdInRecoilScope: string, uniqueIdInRecoilScope: string,
SpecificContext?: Context<string | null>, CustomRecoilScopeContext?: Context<string | null>,
) { ) {
const recoilScopeId = useContext(SpecificContext ?? RecoilScopeContext); const recoilScopeId = useContext(
CustomRecoilScopeContext ?? RecoilScopeContext,
);
if (!recoilScopeId) if (!recoilScopeId)
throw new Error( throw new Error(

View File

@ -5,9 +5,11 @@ import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function useRecoilScopedState<StateType>( export function useRecoilScopedState<StateType>(
recoilState: (param: string) => RecoilState<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) if (!recoilScopeId)
throw new Error( throw new Error(

View File

@ -5,9 +5,11 @@ import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function useRecoilScopedValue<T>( export function useRecoilScopedValue<T>(
recoilState: (param: string) => RecoilState<T> | RecoilValueReadOnly<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) if (!recoilScopeId)
throw new Error( throw new Error(

View File

@ -1,25 +1,24 @@
import { Context } from 'react';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { availableFiltersScopedState } from '../states/availableFiltersScopedState'; import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
import { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton'; import { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton';
import { SingleEntityFilterDropdownButton } from './SingleEntityFilterDropdownButton'; import { SingleEntityFilterDropdownButton } from './SingleEntityFilterDropdownButton';
type FilterDropdownButtonProps = { type FilterDropdownButtonProps = {
context: Context<string | null>;
hotkeyScope: HotkeyScope; hotkeyScope: HotkeyScope;
}; };
export function FilterDropdownButton({ export function FilterDropdownButton({
hotkeyScope, hotkeyScope,
context,
}: FilterDropdownButtonProps) { }: FilterDropdownButtonProps) {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [availableFilters] = useRecoilScopedState( const [availableFilters] = useRecoilScopedState(
availableFiltersScopedState, availableFiltersScopedState,
context, ViewBarRecoilScopeContext,
); );
const hasOnlyOneEntityFilter = const hasOnlyOneEntityFilter =
@ -30,14 +29,8 @@ export function FilterDropdownButton({
} }
return hasOnlyOneEntityFilter ? ( return hasOnlyOneEntityFilter ? (
<SingleEntityFilterDropdownButton <SingleEntityFilterDropdownButton hotkeyScope={hotkeyScope} />
context={context}
hotkeyScope={hotkeyScope}
/>
) : ( ) : (
<MultipleFiltersDropdownButton <MultipleFiltersDropdownButton hotkeyScope={hotkeyScope} />
context={context}
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 { DatePicker } from '@/ui/input/components/DatePicker';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useUpsertFilter } from '@/ui/view-bar/hooks/useUpsertFilter'; import { useUpsertFilter } from '@/ui/view-bar/hooks/useUpsertFilter';
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState'; import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState';
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState'; import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { isFilterDropdownUnfoldedScopedState } from '../states/isFilterDropdownUnfoldedScopedState'; import { isFilterDropdownUnfoldedScopedState } from '../states/isFilterDropdownUnfoldedScopedState';
export function FilterDropdownDateSearchInput({ export function FilterDropdownDateSearchInput() {
context, const { ViewBarRecoilScopeContext } = useViewBarContext();
}: {
context: Context<string | null>;
}) {
const [filterDefinitionUsedInDropdown] = useRecoilScopedState( const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState, filterDefinitionUsedInDropdownScopedState,
context, ViewBarRecoilScopeContext,
); );
const [selectedOperandInDropdown] = useRecoilScopedState( const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState, selectedOperandInDropdownScopedState,
context, ViewBarRecoilScopeContext,
); );
const [, setIsFilterDropdownUnfolded] = useRecoilScopedState( const [, setIsFilterDropdownUnfolded] = useRecoilScopedState(
isFilterDropdownUnfoldedScopedState, isFilterDropdownUnfoldedScopedState,
DropdownRecoilScopeContext, ViewBarRecoilScopeContext,
); );
const upsertFilter = useUpsertFilter(context); const upsertFilter = useUpsertFilter();
function handleChange(date: Date) { function handleChange(date: Date) {
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return; 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 { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; 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 { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filterDropdownSearchInputScopedState';
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState'; import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
export function FilterDropdownEntitySearchInput({ import { useViewBarContext } from '../hooks/useViewBarContext';
context,
}: { export function FilterDropdownEntitySearchInput() {
context: Context<string | null>; const { ViewBarRecoilScopeContext } = useViewBarContext();
}) {
const [filterDefinitionUsedInDropdown] = useRecoilScopedState( const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState, filterDefinitionUsedInDropdownScopedState,
context, ViewBarRecoilScopeContext,
); );
const [selectedOperandInDropdown] = useRecoilScopedState( const [selectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState, selectedOperandInDropdownScopedState,
context, ViewBarRecoilScopeContext,
); );
const [filterDropdownSearchInput, setFilterDropdownSearchInput] = const [filterDropdownSearchInput, setFilterDropdownSearchInput] =
useRecoilScopedState(filterDropdownSearchInputScopedState, context); useRecoilScopedState(
filterDropdownSearchInputScopedState,
ViewBarRecoilScopeContext,
);
return ( return (
filterDefinitionUsedInDropdown && filterDefinitionUsedInDropdown &&

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
import { Context, useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { produce } from 'immer'; import { produce } from 'immer';
import { LightButton } from '@/ui/button/components/LightButton'; 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 { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { SortDropdownId } from '../constants/SortDropdownId'; import { SortDropdownId } from '../constants/SortDropdownId';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { availableSortsScopedState } from '../states/availableSortsScopedState'; import { availableSortsScopedState } from '../states/availableSortsScopedState';
import { sortsScopedState } from '../states/sortsScopedState'; import { sortsScopedState } from '../states/sortsScopedState';
import { SortDefinition } from '../types/SortDefinition'; import { SortDefinition } from '../types/SortDefinition';
import { SORT_DIRECTIONS, SortDirection } from '../types/SortDirection'; import { SORT_DIRECTIONS, SortDirection } from '../types/SortDirection';
export type SortDropdownButtonProps = { export type SortDropdownButtonProps = {
context: Context<string | null>;
hotkeyScope: HotkeyScope; hotkeyScope: HotkeyScope;
isPrimaryButton?: boolean; isPrimaryButton?: boolean;
}; };
export function SortDropdownButton({ export function SortDropdownButton({ hotkeyScope }: SortDropdownButtonProps) {
hotkeyScope, const { ViewBarRecoilScopeContext } = useViewBarContext();
context,
}: SortDropdownButtonProps) {
const [isSortDirectionMenuUnfolded, setIsSortDirectionMenuUnfolded] = const [isSortDirectionMenuUnfolded, setIsSortDirectionMenuUnfolded] =
useState(false); useState(false);
@ -42,10 +41,13 @@ export function SortDropdownButton({
const [availableSorts] = useRecoilScopedState( const [availableSorts] = useRecoilScopedState(
availableSortsScopedState, availableSortsScopedState,
context, ViewBarRecoilScopeContext,
); );
const [sorts, setSorts] = useRecoilScopedState(sortsScopedState, context); const [sorts, setSorts] = useRecoilScopedState(
sortsScopedState,
ViewBarRecoilScopeContext,
);
const isSortSelected = sorts.length > 0; 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 styled from '@emotion/styled';
import { useRecoilValue, useSetRecoilState } from 'recoil'; import { useRecoilValue, useSetRecoilState } from 'recoil';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
@ -10,8 +10,8 @@ import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/Style
import { IconChevronDown, IconPlus } from '@/ui/icon'; import { IconChevronDown, IconPlus } from '@/ui/icon';
import { MenuItem } from '@/ui/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; 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 { 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 { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState'; import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState'; import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
@ -32,37 +32,51 @@ const StyledContainer = styled.div`
export type UpdateViewButtonGroupProps = { export type UpdateViewButtonGroupProps = {
hotkeyScope: string; hotkeyScope: string;
onViewEditModeChange?: () => void; onViewEditModeChange?: () => void;
scopeContext: Context<string | null>;
}; };
export const UpdateViewButtonGroup = ({ export const UpdateViewButtonGroup = ({
hotkeyScope, hotkeyScope,
onViewEditModeChange, onViewEditModeChange,
scopeContext,
}: UpdateViewButtonGroupProps) => { }: UpdateViewButtonGroupProps) => {
const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const { canPersistViewFields, onCurrentViewSubmit } = const {
useContext(ViewBarContext); canPersistViewFields,
const recoilScopeId = useContextScopeId(scopeContext); onCurrentViewSubmit,
ViewBarRecoilScopeContext,
} = useContext(ViewBarContext);
const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
const currentViewId = useRecoilScopedValue( const currentViewId = useRecoilScopedValue(
currentViewIdScopedState, currentViewIdScopedState,
scopeContext, ViewBarRecoilScopeContext,
); );
const filters = useRecoilScopedValue(filtersScopedState, scopeContext); const filters = useRecoilScopedValue(
filtersScopedState,
ViewBarRecoilScopeContext,
);
const setSavedFilters = useSetRecoilState( const setSavedFilters = useSetRecoilState(
savedFiltersFamilyState(currentViewId), savedFiltersFamilyState(currentViewId),
); );
const canPersistFilters = useRecoilValue( 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 setSavedSorts = useSetRecoilState(savedSortsFamilyState(currentViewId));
const canPersistSorts = useRecoilValue( const canPersistSorts = useRecoilValue(
canPersistSortsScopedFamilySelector([recoilScopeId, currentViewId]), canPersistSortsScopedFamilySelector({
recoilScopeId,
viewId: currentViewId,
}),
); );
const setViewEditMode = useSetRecoilState(viewEditModeState); 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 { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
import { TopBar } from '@/ui/top-bar/TopBar'; import { TopBar } from '@/ui/top-bar/TopBar';
@ -9,21 +9,19 @@ import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
import { FilterDropdownButton } from './FilterDropdownButton'; import { FilterDropdownButton } from './FilterDropdownButton';
import { SortDropdownButton } from './SortDropdownButton'; import { SortDropdownButton } from './SortDropdownButton';
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup'; import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
import ViewBarDetails from './ViewBarDetails'; import { ViewBarDetails } from './ViewBarDetails';
import { ViewsDropdownButton } from './ViewsDropdownButton'; import { ViewsDropdownButton } from './ViewsDropdownButton';
export type ViewBarProps = { export type ViewBarProps = {
className?: string; className?: string;
optionsDropdownButton: ReactNode; optionsDropdownButton: ReactNode;
optionsDropdownKey: string; optionsDropdownKey: string;
scopeContext: Context<string | null>;
}; };
export const ViewBar = ({ export const ViewBar = ({
className, className,
optionsDropdownButton, optionsDropdownButton,
optionsDropdownKey, optionsDropdownKey,
scopeContext,
}: ViewBarProps) => { }: ViewBarProps) => {
const { openDropdownButton: openOptionsDropdownButton } = useDropdownButton({ const { openDropdownButton: openOptionsDropdownButton } = useDropdownButton({
dropdownId: optionsDropdownKey, dropdownId: optionsDropdownKey,
@ -36,7 +34,6 @@ export const ViewBar = ({
<ViewsDropdownButton <ViewsDropdownButton
onViewEditModeChange={openOptionsDropdownButton} onViewEditModeChange={openOptionsDropdownButton}
hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }} hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
scopeContext={scopeContext}
/> />
} }
displayBottomBorder={false} displayBottomBorder={false}
@ -44,10 +41,8 @@ export const ViewBar = ({
<> <>
<FilterDropdownButton <FilterDropdownButton
hotkeyScope={{ scope: FiltersHotkeyScope.FilterDropdownButton }} hotkeyScope={{ scope: FiltersHotkeyScope.FilterDropdownButton }}
context={scopeContext}
/> />
<SortDropdownButton <SortDropdownButton
context={scopeContext}
hotkeyScope={{ scope: FiltersHotkeyScope.FilterDropdownButton }} hotkeyScope={{ scope: FiltersHotkeyScope.FilterDropdownButton }}
isPrimaryButton isPrimaryButton
/> />
@ -56,13 +51,11 @@ export const ViewBar = ({
} }
bottomComponent={ bottomComponent={
<ViewBarDetails <ViewBarDetails
context={scopeContext}
hasFilterButton hasFilterButton
rightComponent={ rightComponent={
<UpdateViewButtonGroup <UpdateViewButtonGroup
onViewEditModeChange={openOptionsDropdownButton} onViewEditModeChange={openOptionsDropdownButton}
hotkeyScope={ViewsHotkeyScope.CreateDropdown} 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 styled from '@emotion/styled';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { IconArrowNarrowDown, IconArrowNarrowUp } from '@/ui/icon/index'; 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 { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBarContext } from '../contexts/ViewBarContext'; import { ViewBarContext } from '../contexts/ViewBarContext';
import { useRemoveFilter } from '../hooks/useRemoveFilter'; import { useRemoveFilter } from '../hooks/useRemoveFilter';
@ -24,7 +24,6 @@ import { AddFilterFromDropdownButton } from './AddFilterFromDetailsButton';
import SortOrFilterChip from './SortOrFilterChip'; import SortOrFilterChip from './SortOrFilterChip';
export type ViewBarDetailsProps = { export type ViewBarDetailsProps = {
context: Context<string | null>;
hasFilterButton?: boolean; hasFilterButton?: boolean;
rightComponent?: ReactNode; rightComponent?: ReactNode;
}; };
@ -97,19 +96,23 @@ const StyledAddFilterContainer = styled.div`
z-index: 5; z-index: 5;
`; `;
function ViewBarDetails({ export function ViewBarDetails({
context,
hasFilterButton = false, hasFilterButton = false,
rightComponent, rightComponent,
}: ViewBarDetailsProps) { }: ViewBarDetailsProps) {
const { canPersistViewFields, onViewBarReset } = useContext(ViewBarContext); const { canPersistViewFields, onViewBarReset, ViewBarRecoilScopeContext } =
const recoilScopeId = useContextScopeId(context); useContext(ViewBarContext);
const currentViewId = useRecoilScopedValue(currentViewIdScopedState, context); const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
ViewBarRecoilScopeContext,
);
const [filters, setFilters] = useRecoilScopedState( const [filters, setFilters] = useRecoilScopedState(
filtersScopedState, filtersScopedState,
context, ViewBarRecoilScopeContext,
); );
const savedFilters = useRecoilValue( const savedFilters = useRecoilValue(
@ -120,16 +123,25 @@ function ViewBarDetails({
const [availableFilters] = useRecoilScopedState( const [availableFilters] = useRecoilScopedState(
availableFiltersScopedState, availableFiltersScopedState,
context, ViewBarRecoilScopeContext,
); );
const canPersistFilters = useRecoilValue( 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( const canPersistSorts = useRecoilValue(
canPersistSortsScopedFamilySelector([recoilScopeId, currentViewId]), canPersistSortsScopedFamilySelector({
recoilScopeId,
viewId: currentViewId,
}),
); );
const canPersistView = const canPersistView =
@ -137,7 +149,7 @@ function ViewBarDetails({
const [isViewBarExpanded] = useRecoilScopedState( const [isViewBarExpanded] = useRecoilScopedState(
isViewBarExpandedScopedState, isViewBarExpandedScopedState,
context, ViewBarRecoilScopeContext,
); );
const filtersWithDefinition = filters.map((filter) => { const filtersWithDefinition = filters.map((filter) => {
@ -151,7 +163,8 @@ function ViewBarDetails({
}; };
}); });
const removeFilter = useRemoveFilter(context); const removeFilter = useRemoveFilter();
function handleCancelClick() { function handleCancelClick() {
onViewBarReset?.(); onViewBarReset?.();
setFilters(savedFilters); setFilters(savedFilters);
@ -231,5 +244,3 @@ function ViewBarDetails({
</StyledBar> </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 { useTheme } from '@emotion/react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useRecoilCallback, useSetRecoilState } from 'recoil';
@ -19,9 +19,9 @@ import {
import { MenuItem } from '@/ui/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { MOBILE_VIEWPORT } from '@/ui/theme/constants/theme'; import { MOBILE_VIEWPORT } from '@/ui/theme/constants/theme';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; 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 { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; 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 { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState'; import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState'; import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
@ -72,24 +72,27 @@ const StyledViewName = styled.span`
export type ViewsDropdownButtonProps = { export type ViewsDropdownButtonProps = {
hotkeyScope: HotkeyScope; hotkeyScope: HotkeyScope;
onViewEditModeChange?: () => void; onViewEditModeChange?: () => void;
scopeContext: Context<string | null>;
}; };
export const ViewsDropdownButton = ({ export const ViewsDropdownButton = ({
hotkeyScope, hotkeyScope,
onViewEditModeChange, onViewEditModeChange,
scopeContext,
}: ViewsDropdownButtonProps) => { }: ViewsDropdownButtonProps) => {
const theme = useTheme(); const theme = useTheme();
const { defaultViewName, onViewSelect } = useContext(ViewBarContext); const { defaultViewName, onViewSelect, ViewBarRecoilScopeContext } =
const recoilScopeId = useContextScopeId(scopeContext); useContext(ViewBarContext);
const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
const currentView = useRecoilScopedValue( const currentView = useRecoilScopedValue(
currentViewScopedSelector, currentViewScopedSelector,
scopeContext, ViewBarRecoilScopeContext,
);
const [views] = useRecoilScopedState(
viewsScopedState,
ViewBarRecoilScopeContext,
); );
const [views] = useRecoilScopedState(viewsScopedState, scopeContext);
const { isDropdownButtonOpen, closeDropdownButton, toggleDropdownButton } = const { isDropdownButtonOpen, closeDropdownButton, toggleDropdownButton } =
useDropdownButton({ useDropdownButton({
@ -134,7 +137,7 @@ export const ViewsDropdownButton = ({
closeDropdownButton(); closeDropdownButton();
}; };
const { removeView } = useRemoveView({ scopeContext }); const { removeView } = useRemoveView();
const handleDeleteViewButtonClick = async ( const handleDeleteViewButtonClick = async (
event: MouseEvent<HTMLButtonElement>, event: MouseEvent<HTMLButtonElement>,

View File

@ -1,5 +1,7 @@
import { createContext } from 'react'; import { createContext } from 'react';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import type { View } from '../types/View'; import type { View } from '../types/View';
export const ViewBarContext = createContext<{ export const ViewBarContext = createContext<{
@ -11,4 +13,8 @@ export const ViewBarContext = createContext<{
onViewEdit?: (view: View) => void | Promise<void>; onViewEdit?: (view: View) => void | Promise<void>;
onViewRemove?: (viewId: string) => void | Promise<void>; onViewRemove?: (viewId: string) => void | Promise<void>;
onViewSelect?: (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 { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState'; import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
import { filtersScopedState } from '../states/filtersScopedState'; import { filtersScopedState } from '../states/filtersScopedState';
export function useFilterCurrentlyEdited(context: Context<string | null>) { import { useViewBarContext } from './useViewBarContext';
const [filters] = useRecoilScopedState(filtersScopedState, context);
export function useFilterCurrentlyEdited() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [filters] = useRecoilScopedState(
filtersScopedState,
ViewBarRecoilScopeContext,
);
const [filterDefinitionUsedInDropdown] = useRecoilScopedState( const [filterDefinitionUsedInDropdown] = useRecoilScopedState(
filterDefinitionUsedInDropdownScopedState, filterDefinitionUsedInDropdownScopedState,
context, ViewBarRecoilScopeContext,
); );
return useMemo(() => { 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 { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { ViewBarContext } from '../contexts/ViewBarContext';
import { filtersScopedState } from '../states/filtersScopedState'; import { filtersScopedState } from '../states/filtersScopedState';
export function useRemoveFilter(context: Context<string | null>) { export function useRemoveFilter() {
const [, setFilters] = useRecoilScopedState(filtersScopedState, context); const { ViewBarRecoilScopeContext } = useContext(ViewBarContext);
const [, setFilters] = useRecoilScopedState(
filtersScopedState,
ViewBarRecoilScopeContext,
);
return function removeFilter(filterKey: string) { return function removeFilter(filterKey: string) {
setFilters((filters) => { setFilters((filters) => {

View File

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

View File

@ -1,4 +1,3 @@
import { Context } from 'react';
import { produce } from 'immer'; import { produce } from 'immer';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; 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 { filtersScopedState } from '../states/filtersScopedState';
import { Filter } from '../types/Filter'; import { Filter } from '../types/Filter';
export function useUpsertFilter(context: Context<string | null>) { import { useViewBarContext } from './useViewBarContext';
const [, setFilters] = useRecoilScopedState(filtersScopedState, context);
export function useUpsertFilter() {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [, setFilters] = useRecoilScopedState(
filtersScopedState,
ViewBarRecoilScopeContext,
);
return function upsertFilter(filterToUpsert: Filter) { return function upsertFilter(filterToUpsert: Filter) {
setFilters((filters) => { 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 { useRecoilCallback, useRecoilValue, useResetRecoilState } from 'recoil';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBarContext } from '../contexts/ViewBarContext'; import { ViewBarContext } from '../contexts/ViewBarContext';
import { currentViewIdScopedState } from '../states/currentViewIdScopedState'; import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
@ -16,16 +16,19 @@ import { sortsScopedState } from '../states/sortsScopedState';
import { viewEditModeState } from '../states/viewEditModeState'; import { viewEditModeState } from '../states/viewEditModeState';
import { viewsScopedState } from '../states/viewsScopedState'; import { viewsScopedState } from '../states/viewsScopedState';
export const useUpsertView = ({ export const useUpsertView = () => {
scopeContext, const { onViewCreate, onViewEdit, ViewBarRecoilScopeContext } =
}: { useContext(ViewBarContext);
scopeContext: Context<string | null>; const recoilScopeId = useRecoilScopeId(ViewBarRecoilScopeContext);
}) => {
const { onViewCreate, onViewEdit } = useContext(ViewBarContext);
const recoilScopeId = useContextScopeId(scopeContext);
const filters = useRecoilScopedValue(filtersScopedState, scopeContext); const filters = useRecoilScopedValue(
const sorts = useRecoilScopedValue(sortsScopedState, scopeContext); filtersScopedState,
ViewBarRecoilScopeContext,
);
const sorts = useRecoilScopedValue(
sortsScopedState,
ViewBarRecoilScopeContext,
);
const viewEditMode = useRecoilValue(viewEditModeState); const viewEditMode = useRecoilValue(viewEditModeState);
const resetViewEditMode = useResetRecoilState(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({ export const canPersistFiltersScopedFamilySelector = selectorFamily({
key: 'canPersistFiltersScopedFamilySelector', key: 'canPersistFiltersScopedFamilySelector',
get: get:
([scopeId, viewId]: [string, string | undefined]) => ({
recoilScopeId,
viewId,
}: {
recoilScopeId: string;
viewId: string | undefined;
}) =>
({ get }) => ({ get }) =>
!isDeeplyEqual( !isDeeplyEqual(
get(savedFiltersFamilyState(viewId)), get(savedFiltersFamilyState(viewId)),
get(filtersScopedState(scopeId)), get(filtersScopedState(recoilScopeId)),
), ),
}); });

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import { type Context } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil'; import { useRecoilValue, useSetRecoilState } from 'recoil';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
import { availableBoardCardFieldsScopedState } from '@/ui/board/states/availableBoardCardFieldsScopedState'; import { availableBoardCardFieldsScopedState } from '@/ui/board/states/availableBoardCardFieldsScopedState';
import { boardCardFieldsScopedState } from '@/ui/board/states/boardCardFieldsScopedState'; import { boardCardFieldsScopedState } from '@/ui/board/states/boardCardFieldsScopedState';
import { savedBoardCardFieldsFamilyState } from '@/ui/board/states/savedBoardCardFieldsFamilyState'; import { savedBoardCardFieldsFamilyState } from '@/ui/board/states/savedBoardCardFieldsFamilyState';
@ -35,23 +35,26 @@ const toViewFieldInput = (
export const useBoardViewFields = ({ export const useBoardViewFields = ({
objectId, objectId,
fieldDefinitions, fieldDefinitions,
scopeContext,
skipFetch, skipFetch,
RecoilScopeContext,
}: { }: {
objectId: 'company' | 'person'; objectId: 'company' | 'person';
fieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[]; fieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
scopeContext: Context<string | null>;
skipFetch?: boolean; skipFetch?: boolean;
RecoilScopeContext: RecoilScopeContext;
}) => { }) => {
const currentViewId = useRecoilScopedValue( const currentViewId = useRecoilScopedValue(
currentViewIdScopedState, currentViewIdScopedState,
scopeContext, RecoilScopeContext,
); );
const [availableBoardCardFields, setAvailableBoardCardFields] = const [availableBoardCardFields, setAvailableBoardCardFields] =
useRecoilScopedState(availableBoardCardFieldsScopedState, scopeContext); useRecoilScopedState(
availableBoardCardFieldsScopedState,
RecoilScopeContext,
);
const [boardCardFields, setBoardCardFields] = useRecoilScopedState( const [boardCardFields, setBoardCardFields] = useRecoilScopedState(
boardCardFieldsScopedState, boardCardFieldsScopedState,
scopeContext, RecoilScopeContext,
); );
const setSavedBoardCardFields = useSetRecoilState( const setSavedBoardCardFields = useSetRecoilState(
savedBoardCardFieldsFamilyState(currentViewId), 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 { boardCardFieldsScopedState } from '@/ui/board/states/boardCardFieldsScopedState';
import type { import type {
ViewFieldDefinition, ViewFieldDefinition,
@ -18,41 +17,41 @@ import { useViewSorts } from './useViewSorts';
export const useBoardViews = ({ export const useBoardViews = ({
fieldDefinitions, fieldDefinitions,
objectId, objectId,
scopeContext, RecoilScopeContext,
}: { }: {
fieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[]; fieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
objectId: 'company'; objectId: 'company';
scopeContext: Context<string | null>; RecoilScopeContext: RecoilScopeContext;
}) => { }) => {
const boardCardFields = useRecoilScopedValue( const boardCardFields = useRecoilScopedValue(
boardCardFieldsScopedState, boardCardFieldsScopedState,
scopeContext, RecoilScopeContext,
); );
const filters = useRecoilScopedValue(filtersScopedState, scopeContext); const filters = useRecoilScopedValue(filtersScopedState, RecoilScopeContext);
const sorts = useRecoilScopedValue(sortsScopedState, scopeContext); const sorts = useRecoilScopedValue(sortsScopedState, RecoilScopeContext);
const { createView, deleteView, isFetchingViews, updateView } = useViews({ const { createView, deleteView, isFetchingViews, updateView } = useViews({
objectId, objectId,
onViewCreate: handleViewCreate, onViewCreate: handleViewCreate,
type: ViewType.Pipeline, type: ViewType.Pipeline,
scopeContext, RecoilScopeContext,
}); });
const { createViewFields, persistCardFields } = useBoardViewFields({ const { createViewFields, persistCardFields } = useBoardViewFields({
objectId, objectId,
fieldDefinitions, fieldDefinitions,
scopeContext,
skipFetch: isFetchingViews, skipFetch: isFetchingViews,
RecoilScopeContext,
}); });
const { createViewFilters, persistFilters } = useViewFilters({ const { createViewFilters, persistFilters } = useViewFilters({
scopeContext,
skipFetch: isFetchingViews, skipFetch: isFetchingViews,
RecoilScopeContext,
}); });
const { createViewSorts, persistSorts } = useViewSorts({ const { createViewSorts, persistSorts } = useViewSorts({
scopeContext,
skipFetch: isFetchingViews, skipFetch: isFetchingViews,
RecoilScopeContext,
}); });
async function handleViewCreate(viewId: string) { async function handleViewCreate(viewId: string) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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