2422 refactor scope components to improve dev experience (#2736)

* move scope inside record table

* fix imports

* update mock

* recordTable scope done

* RecordTable done

* fix board

* fix typo

* wip

* filter is working

* sort is working

* Tasks working

* Fix according to PR

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
bosiraphael
2023-11-28 18:24:18 +01:00
committed by GitHub
parent 9d3e000055
commit ade41c916d
60 changed files with 651 additions and 529 deletions

View File

@ -2,10 +2,18 @@ import { isNonEmptyString } from '@sniptt/guards';
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { PageAddButton } from '@/ui/layout/page/PageAddButton'; import { PageAddButton } from '@/ui/layout/page/PageAddButton';
import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter'; import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
export const PageAddTaskButton = () => { type PageAddTaskButtonProps = {
const { selectedFilter } = useFilter(); filterDropdownId: string;
};
export const PageAddTaskButton = ({
filterDropdownId,
}: PageAddTaskButtonProps) => {
const { selectedFilter } = useFilterDropdown({
filterDropdownId: filterDropdownId,
});
const openCreateActivity = useOpenCreateActivityDrawer(); const openCreateActivity = useOpenCreateActivityDrawer();
const handleClick = () => { const handleClick = () => {

View File

@ -13,6 +13,7 @@ import { AddTaskButton } from './AddTaskButton';
import { TaskList } from './TaskList'; import { TaskList } from './TaskList';
type TaskGroupsProps = { type TaskGroupsProps = {
filterDropdownId?: string;
entity?: ActivityTargetableEntity; entity?: ActivityTargetableEntity;
showAddButton?: boolean; showAddButton?: boolean;
}; };
@ -51,13 +52,17 @@ const StyledContainer = styled.div`
flex-direction: column; flex-direction: column;
`; `;
export const TaskGroups = ({ entity, showAddButton }: TaskGroupsProps) => { export const TaskGroups = ({
filterDropdownId,
entity,
showAddButton,
}: TaskGroupsProps) => {
const { const {
todayOrPreviousTasks, todayOrPreviousTasks,
upcomingTasks, upcomingTasks,
unscheduledTasks, unscheduledTasks,
completedTasks, completedTasks,
} = useTasks(entity); } = useTasks({ filterDropdownId: filterDropdownId, entity });
const openCreateActivity = useOpenCreateActivityDrawer(); const openCreateActivity = useOpenCreateActivityDrawer();

View File

@ -5,12 +5,21 @@ import { undefined } from 'zod';
import { Activity } from '@/activities/types/Activity'; import { Activity } from '@/activities/types/Activity';
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity'; import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords'; import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter'; import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { parseDate } from '~/utils/date-utils'; import { parseDate } from '~/utils/date-utils';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
export const useTasks = (entity?: ActivityTargetableEntity) => { type UseTasksProps = {
const { selectedFilter } = useFilter(); filterDropdownId?: string;
entity?: ActivityTargetableEntity;
};
export const useTasks = (props?: UseTasksProps) => {
const { filterDropdownId, entity } = props ?? {};
const { selectedFilter } = useFilterDropdown({
filterDropdownId: filterDropdownId,
});
const { objects: activityTargets } = useFindManyObjectRecords({ const { objects: activityTargets } = useFindManyObjectRecords({
objectNamePlural: 'activityTargets', objectNamePlural: 'activityTargets',

View File

@ -12,7 +12,6 @@ import { RecordBoardContextMenu } from '@/ui/object/record-board/context-menu/co
import { BoardOptionsDropdown } from '@/ui/object/record-board/options/components/BoardOptionsDropdown'; import { BoardOptionsDropdown } from '@/ui/object/record-board/options/components/BoardOptionsDropdown';
import { ViewBar } from '@/views/components/ViewBar'; import { ViewBar } from '@/views/components/ViewBar';
import { useViewFields } from '@/views/hooks/internal/useViewFields'; import { useViewFields } from '@/views/hooks/internal/useViewFields';
import { ViewScope } from '@/views/scopes/ViewScope';
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions'; import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
import { HooksCompanyBoardEffect } from '../../components/HooksCompanyBoardEffect'; import { HooksCompanyBoardEffect } from '../../components/HooksCompanyBoardEffect';
@ -36,41 +35,35 @@ export const CompanyBoard = ({
onColumnDelete, onColumnDelete,
onEditColumnTitle, onEditColumnTitle,
}: CompanyBoardProps) => { }: CompanyBoardProps) => {
const viewScopeId = 'company-board-view'; const viewBarId = 'company-board-view';
const { persistViewFields } = useViewFields(viewScopeId); const { persistViewFields } = useViewFields(viewBarId);
return ( return (
<ViewScope <StyledContainer>
viewScopeId={viewScopeId} <BoardContext.Provider
onViewFieldsChange={() => {}} value={{
onViewFiltersChange={() => {}} BoardRecoilScopeContext: CompanyBoardRecoilScopeContext,
onViewSortsChange={() => {}} onFieldsChange: (fields) => {
> persistViewFields(mapBoardFieldDefinitionsToViewFields(fields));
<StyledContainer> },
<BoardContext.Provider }}
value={{ >
BoardRecoilScopeContext: CompanyBoardRecoilScopeContext, <ViewBar
onFieldsChange: (fields) => { viewBarId={viewBarId}
persistViewFields(mapBoardFieldDefinitionsToViewFields(fields)); optionsDropdownButton={<BoardOptionsDropdown />}
}, optionsDropdownScopeId={BoardOptionsDropdownId}
}} />
> <HooksCompanyBoardEffect viewBarId={viewBarId} />
<ViewBar <RecordBoard
optionsDropdownButton={<BoardOptionsDropdown />} boardOptions={opportunitiesBoardOptions}
optionsDropdownScopeId={BoardOptionsDropdownId} onColumnAdd={onColumnAdd}
/> onColumnDelete={onColumnDelete}
<HooksCompanyBoardEffect /> onEditColumnTitle={onEditColumnTitle}
<RecordBoard />
boardOptions={opportunitiesBoardOptions} <RecordBoardActionBar />
onColumnAdd={onColumnAdd} <RecordBoardContextMenu />
onColumnDelete={onColumnDelete} </BoardContext.Provider>
onEditColumnTitle={onEditColumnTitle} </StyledContainer>
/>
<RecordBoardActionBar />
<RecordBoardContextMenu />
</BoardContext.Provider>
</StyledContainer>
</ViewScope>
); );
}; };

View File

@ -20,7 +20,7 @@ import { isBoardLoadedState } from '@/ui/object/record-board/states/isBoardLoade
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useSetRecoilScopedStateV2'; import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useSetRecoilScopedStateV2';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions'; import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
@ -30,7 +30,13 @@ import { isDefined } from '~/utils/isDefined';
import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds'; import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds';
import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns'; import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns';
export const HooksCompanyBoardEffect = () => { type HooksCompanyBoardEffectProps = {
viewBarId: string;
};
export const HooksCompanyBoardEffect = ({
viewBarId,
}: HooksCompanyBoardEffectProps) => {
const { const {
setAvailableFilterDefinitions, setAvailableFilterDefinitions,
setAvailableSortDefinitions, setAvailableSortDefinitions,
@ -38,13 +44,13 @@ export const HooksCompanyBoardEffect = () => {
setEntityCountInCurrentView, setEntityCountInCurrentView,
setViewObjectMetadataId, setViewObjectMetadataId,
setViewType, setViewType,
} = useView(); } = useViewBar({ viewBarId: viewBarId });
const { const {
currentViewFieldsState, currentViewFieldsState,
currentViewFiltersState, currentViewFiltersState,
currentViewSortsState, currentViewSortsState,
} = useViewScopedStates(); } = useViewScopedStates({ viewScopeId: viewBarId });
const [pipelineSteps, setPipelineSteps] = useState<PipelineStep[]>([]); const [pipelineSteps, setPipelineSteps] = useState<PipelineStep[]>([]);
const [opportunities, setOpportunities] = useState<Opportunity[]>([]); const [opportunities, setOpportunities] = useState<Opportunity[]>([]);

View File

@ -1,5 +1,4 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useRecoilCallback } from 'recoil';
import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata'; import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
@ -7,11 +6,7 @@ import { RecordTable } from '@/ui/object/record-table/components/RecordTable';
import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId'; import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown'; import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown';
import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope';
import { ViewBar } from '@/views/components/ViewBar'; import { ViewBar } from '@/views/components/ViewBar';
import { useViewFields } from '@/views/hooks/internal/useViewFields';
import { ViewScope } from '@/views/scopes/ViewScope';
import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinitionToViewField';
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
@ -45,13 +40,11 @@ export const RecordTableContainer = ({
objectNameSingular: foundObjectMetadataItem?.nameSingular, objectNameSingular: foundObjectMetadataItem?.nameSingular,
}); });
const tableScopeId = objectNamePlural ?? ''; const recordTableId = objectNamePlural ?? '';
const viewScopeId = objectNamePlural ?? ''; const viewBarId = objectNamePlural ?? '';
const { persistViewFields } = useViewFields(viewScopeId);
const { setTableFilters, setTableSorts, setTableColumns } = useRecordTable({ const { setTableFilters, setTableSorts, setTableColumns } = useRecordTable({
recordTableScopeId: tableScopeId, recordTableScopeId: recordTableId,
}); });
const updateEntity = ({ const updateEntity = ({
@ -71,35 +64,31 @@ export const RecordTableContainer = ({
}; };
return ( return (
<ViewScope <StyledContainer>
viewScopeId={viewScopeId} <ViewBar
onViewFieldsChange={(viewFields) => { viewBarId={viewBarId}
setTableColumns( optionsDropdownButton={
mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions), <TableOptionsDropdown recordTableId={recordTableId} />
); }
}} optionsDropdownScopeId={TableOptionsDropdownId}
onViewFiltersChange={(viewFilters) => { onViewFieldsChange={(viewFields) => {
setTableFilters(mapViewFiltersToFilters(viewFilters)); setTableColumns(
}} mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions),
onViewSortsChange={(viewSorts) => { );
setTableSorts(mapViewSortsToSorts(viewSorts)); }}
}} onViewFiltersChange={(viewFilters) => {
> setTableFilters(mapViewFiltersToFilters(viewFilters));
<StyledContainer> }}
<RecordTableScope onViewSortsChange={(viewSorts) => {
recordTableScopeId={tableScopeId} setTableSorts(mapViewSortsToSorts(viewSorts));
onColumnsChange={useRecoilCallback(() => (columns) => { }}
persistViewFields(mapColumnDefinitionsToViewFields(columns)); />
})} <RecordTableEffect recordTableId={recordTableId} viewBarId={viewBarId} />
> <RecordTable
<ViewBar recordTableId={recordTableId}
optionsDropdownButton={<TableOptionsDropdown />} viewBarId={viewBarId}
optionsDropdownScopeId={TableOptionsDropdownId} updateEntityMutation={updateEntity}
/> />
<RecordTableEffect /> </StyledContainer>
<RecordTable updateEntityMutation={updateEntity} />
</RecordTableScope>
</StyledContainer>
</ViewScope>
); );
}; };

View File

@ -5,16 +5,22 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries'; import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries';
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
export const RecordTableEffect = () => { export const RecordTableEffect = ({
recordTableId,
viewBarId,
}: {
recordTableId: string;
viewBarId: string;
}) => {
const { const {
scopeId: objectNamePlural, scopeId: objectNamePlural,
setAvailableTableColumns, setAvailableTableColumns,
setOnEntityCountChange, setOnEntityCountChange,
setObjectMetadataConfig, setObjectMetadataConfig,
} = useRecordTable(); } = useRecordTable({ recordTableScopeId: recordTableId });
const { const {
objectMetadataItem, objectMetadataItem,
@ -34,7 +40,7 @@ export const RecordTableEffect = () => {
setViewType, setViewType,
setViewObjectMetadataId, setViewObjectMetadataId,
setEntityCountInCurrentView, setEntityCountInCurrentView,
} = useView(); } = useViewBar({ viewBarId });
useEffect(() => { useEffect(() => {
if (basePathToShowPage && labelIdentifierFieldMetadataId) { if (basePathToShowPage && labelIdentifierFieldMetadataId) {
@ -80,7 +86,9 @@ export const RecordTableEffect = () => {
]); ]);
const { setActionBarEntries, setContextMenuEntries } = const { setActionBarEntries, setContextMenuEntries } =
useRecordTableContextMenuEntries(); useRecordTableContextMenuEntries({
recordTableScopeId: recordTableId,
});
useEffect(() => { useEffect(() => {
setActionBarEntries?.(); setActionBarEntries?.();

View File

@ -9,19 +9,33 @@ import { IconHeart, IconHeartOff, IconTrash } from '@/ui/display/icon';
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState'; import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState'; import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { RecordTableScopeInternalContext } from '@/ui/object/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector'; import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector';
import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState'; import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
type useRecordTableContextMenuEntriesProps = {
recordTableScopeId?: string;
};
// TODO: refactor this // TODO: refactor this
export const useRecordTableContextMenuEntries = () => { export const useRecordTableContextMenuEntries = (
props?: useRecordTableContextMenuEntriesProps,
) => {
const scopeId = useAvailableScopeIdOrThrow(
RecordTableScopeInternalContext,
props?.recordTableScopeId,
);
const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState); const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState); const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState);
const setTableRowIds = useSetRecoilState(tableRowIdsState); const setTableRowIds = useSetRecoilState(tableRowIdsState);
const selectedRowIds = useRecoilValue(selectedRowIdsSelector); const selectedRowIds = useRecoilValue(selectedRowIdsSelector);
const { scopeId: objectNamePlural, resetTableRowSelection } = const { scopeId: objectNamePlural, resetTableRowSelection } = useRecordTable({
useRecordTable(); recordTableScopeId: scopeId,
});
const { objectMetadataItem: foundObjectMetadataItem } = useObjectMetadataItem( const { objectMetadataItem: foundObjectMetadataItem } = useObjectMetadataItem(
{ {

View File

@ -5,11 +5,11 @@ import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { isFetchingRecordTableDataState } from '@/ui/object/record-table/states/isFetchingRecordTableDataState'; import { isFetchingRecordTableDataState } from '@/ui/object/record-table/states/isFetchingRecordTableDataState';
import { numberOfTableRowsState } from '@/ui/object/record-table/states/numberOfTableRowsState'; import { numberOfTableRowsState } from '@/ui/object/record-table/states/numberOfTableRowsState';
import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState'; import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState';
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
export const useSetRecordTableData = () => { export const useSetRecordTableData = () => {
const { resetTableRowSelection } = useRecordTable(); const { resetTableRowSelection } = useRecordTable();
const { setEntityCountInCurrentView } = useView(); const { setEntityCountInCurrentView } = useViewBar();
return useRecoilCallback( return useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>

View File

@ -4,9 +4,7 @@ import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/c
import { RecordTable } from '@/ui/object/record-table/components/RecordTable'; import { RecordTable } from '@/ui/object/record-table/components/RecordTable';
import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId'; import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId';
import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown'; import { TableOptionsDropdown } from '@/ui/object/record-table/options/components/TableOptionsDropdown';
import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope';
import { ViewBar } from '@/views/components/ViewBar'; import { ViewBar } from '@/views/components/ViewBar';
import { ViewScope } from '@/views/scopes/ViewScope';
const StyledContainer = styled.div` const StyledContainer = styled.div`
display: flex; display: flex;
@ -16,29 +14,27 @@ const StyledContainer = styled.div`
`; `;
export const SignInBackgroundMockContainer = () => { export const SignInBackgroundMockContainer = () => {
const tableScopeId = 'sign-in-background-mock-table'; const recordTableId = 'sign-in-background-mock-table';
const viewScopeId = 'sign-in-background-mock-view'; const viewBarId = 'sign-in-background-mock-view';
return ( return (
<ViewScope <StyledContainer>
viewScopeId={viewScopeId} <ViewBar
onViewFieldsChange={() => {}} viewBarId={viewBarId}
onViewFiltersChange={() => {}} optionsDropdownButton={
onViewSortsChange={() => {}} <TableOptionsDropdown recordTableId={recordTableId} />
> }
<StyledContainer> optionsDropdownScopeId={TableOptionsDropdownId}
<RecordTableScope />
recordTableScopeId={tableScopeId} <SignInBackgroundMockContainerEffect
onColumnsChange={() => {}} recordTableId={recordTableId}
> viewId={viewBarId}
<ViewBar />
optionsDropdownButton={<TableOptionsDropdown />} <RecordTable
optionsDropdownScopeId={TableOptionsDropdownId} recordTableId={recordTableId}
/> viewBarId={viewBarId}
<SignInBackgroundMockContainerEffect /> updateEntityMutation={() => {}}
<RecordTable updateEntityMutation={() => {}} /> />
</RecordTableScope> </StyledContainer>
</StyledContainer>
</ViewScope>
); );
}; };

View File

@ -11,11 +11,19 @@ import {
} from '@/sign-in-background-mock/constants/signInBackgroundMockDefinitions'; } from '@/sign-in-background-mock/constants/signInBackgroundMockDefinitions';
import { signInBackgroundMockViewFields } from '@/sign-in-background-mock/constants/signInBackgroundMockViewFields'; import { signInBackgroundMockViewFields } from '@/sign-in-background-mock/constants/signInBackgroundMockViewFields';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
export const SignInBackgroundMockContainerEffect = () => { type SignInBackgroundMockContainerEffectProps = {
recordTableId: string;
viewId: string;
};
export const SignInBackgroundMockContainerEffect = ({
recordTableId,
viewId,
}: SignInBackgroundMockContainerEffectProps) => {
const { const {
scopeId: objectNamePlural, scopeId: objectNamePlural,
setAvailableTableColumns, setAvailableTableColumns,
@ -23,7 +31,9 @@ export const SignInBackgroundMockContainerEffect = () => {
setRecordTableData, setRecordTableData,
setTableColumns, setTableColumns,
setObjectMetadataConfig, setObjectMetadataConfig,
} = useRecordTable(); } = useRecordTable({
recordTableScopeId: recordTableId,
});
const { objectMetadataItem } = useObjectMetadataItem({ const { objectMetadataItem } = useObjectMetadataItem({
objectNamePlural, objectNamePlural,
@ -36,7 +46,7 @@ export const SignInBackgroundMockContainerEffect = () => {
setViewType, setViewType,
setViewObjectMetadataId, setViewObjectMetadataId,
setEntityCountInCurrentView, setEntityCountInCurrentView,
} = useView(); } = useViewBar({ viewBarId: viewId });
useEffect(() => { useEffect(() => {
setViewObjectMetadataId?.('company-mock-object-metadata-id'); setViewObjectMetadataId?.('company-mock-object-metadata-id');
@ -76,7 +86,9 @@ export const SignInBackgroundMockContainerEffect = () => {
}, [setObjectMetadataConfig]); }, [setObjectMetadataConfig]);
const { setActionBarEntries, setContextMenuEntries } = const { setActionBarEntries, setContextMenuEntries } =
useRecordTableContextMenuEntries(); useRecordTableContextMenuEntries({
recordTableScopeId: recordTableId,
});
useEffect(() => { useEffect(() => {
setActionBarEntries?.(); setActionBarEntries?.();

View File

@ -1,16 +1,24 @@
import { IconPlus } from '@/ui/display/icon'; import { IconPlus } from '@/ui/display/icon';
import { LightButton } from '@/ui/input/button/components/LightButton'; import { LightButton } from '@/ui/input/button/components/LightButton';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter'; import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId'; import { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId';
export const AddObjectFilterFromDetailsButton = () => { type AddObjectFilterFromDetailsButtonProps = {
filterDropdownId?: string;
};
export const AddObjectFilterFromDetailsButton = ({
filterDropdownId,
}: AddObjectFilterFromDetailsButtonProps) => {
const { toggleDropdown } = useDropdown({ const { toggleDropdown } = useDropdown({
dropdownScopeId: ObjectFilterDropdownId, dropdownScopeId: ObjectFilterDropdownId,
}); });
const { resetFilter } = useFilter(); const { resetFilter } = useFilterDropdown({
filterDropdownId: filterDropdownId,
});
const handleClick = () => { const handleClick = () => {
resetFilter(); resetFilter();

View File

@ -1,11 +1,11 @@
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId'; import { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId';
import { useFilter } from '../hooks/useFilter';
export const MultipleFiltersButton = () => { export const MultipleFiltersButton = () => {
const { resetFilter } = useFilter(); const { resetFilter } = useFilterDropdown();
const { isDropdownOpen, toggleDropdown } = useDropdown({ const { isDropdownOpen, toggleDropdown } = useDropdown({
dropdownScopeId: ObjectFilterDropdownId, dropdownScopeId: ObjectFilterDropdownId,

View File

@ -1,6 +1,6 @@
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter'; import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId'; import { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId';
@ -15,7 +15,7 @@ type MultipleFiltersDropdownButtonProps = {
export const MultipleFiltersDropdownButton = ({ export const MultipleFiltersDropdownButton = ({
hotkeyScope, hotkeyScope,
}: MultipleFiltersDropdownButtonProps) => { }: MultipleFiltersDropdownButtonProps) => {
const { resetFilter } = useFilter(); const { resetFilter } = useFilterDropdown();
return ( return (
<DropdownScope dropdownScopeId={ObjectFilterDropdownId}> <DropdownScope dropdownScopeId={ObjectFilterDropdownId}>

View File

@ -1,6 +1,5 @@
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { useFilter } from '../hooks/useFilter';
import { MultipleFiltersDropdownFilterOnFilterChangedEffect } from './MultipleFiltersDropdownFilterOnFilterChangedEffect'; import { MultipleFiltersDropdownFilterOnFilterChangedEffect } from './MultipleFiltersDropdownFilterOnFilterChangedEffect';
import { ObjectFilterDropdownDateSearchInput } from './ObjectFilterDropdownDateSearchInput'; import { ObjectFilterDropdownDateSearchInput } from './ObjectFilterDropdownDateSearchInput';
@ -17,7 +16,7 @@ export const MultipleFiltersDropdownContent = () => {
isObjectFilterDropdownOperandSelectUnfolded, isObjectFilterDropdownOperandSelectUnfolded,
filterDefinitionUsedInDropdown, filterDefinitionUsedInDropdown,
selectedOperandInDropdown, selectedOperandInDropdown,
} = useFilter(); } = useFilterDropdown();
return ( return (
<> <>

View File

@ -1,19 +1,22 @@
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { ObjectFilterDropdownScope } from '@/ui/object/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useFilter } from '../hooks/useFilter';
import { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton'; import { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton';
import { SingleEntityObjectFilterDropdownButton } from './SingleEntityObjectFilterDropdownButton'; import { SingleEntityObjectFilterDropdownButton } from './SingleEntityObjectFilterDropdownButton';
type ObjectFilterDropdownButtonProps = { type ObjectFilterDropdownButtonProps = {
filterDropdownId: string;
hotkeyScope: HotkeyScope; hotkeyScope: HotkeyScope;
}; };
export const ObjectFilterDropdownButton = ({ export const ObjectFilterDropdownButton = ({
filterDropdownId,
hotkeyScope, hotkeyScope,
}: ObjectFilterDropdownButtonProps) => { }: ObjectFilterDropdownButtonProps) => {
const { availableFilterDefinitions } = useFilter(); const { availableFilterDefinitions } = useFilterDropdown({
filterDropdownId: filterDropdownId,
});
const hasOnlyOneEntityFilter = const hasOnlyOneEntityFilter =
availableFilterDefinitions.length === 1 && availableFilterDefinitions.length === 1 &&
availableFilterDefinitions[0].type === 'RELATION'; availableFilterDefinitions[0].type === 'RELATION';
@ -22,9 +25,13 @@ export const ObjectFilterDropdownButton = ({
return <></>; return <></>;
} }
return hasOnlyOneEntityFilter ? ( return (
<SingleEntityObjectFilterDropdownButton hotkeyScope={hotkeyScope} /> <ObjectFilterDropdownScope filterScopeId={filterDropdownId}>
) : ( {hasOnlyOneEntityFilter ? (
<MultipleFiltersDropdownButton hotkeyScope={hotkeyScope} /> <SingleEntityObjectFilterDropdownButton hotkeyScope={hotkeyScope} />
) : (
<MultipleFiltersDropdownButton hotkeyScope={hotkeyScope} />
)}
</ObjectFilterDropdownScope>
); );
}; };

View File

@ -1,6 +1,5 @@
import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker'; import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { useFilter } from '../hooks/useFilter';
export const ObjectFilterDropdownDateSearchInput = () => { export const ObjectFilterDropdownDateSearchInput = () => {
const { const {
@ -8,7 +7,7 @@ export const ObjectFilterDropdownDateSearchInput = () => {
selectedOperandInDropdown, selectedOperandInDropdown,
setIsObjectFilterDropdownUnfolded, setIsObjectFilterDropdownUnfolded,
selectFilter, selectFilter,
} = useFilter(); } = useFilterDropdown();
const handleChange = (date: Date) => { const handleChange = (date: Date) => {
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return; if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;

View File

@ -1,8 +1,7 @@
import { ChangeEvent } from 'react'; import { ChangeEvent } from 'react';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { useFilter } from '../hooks/useFilter';
export const ObjectFilterDropdownEntitySearchInput = () => { export const ObjectFilterDropdownEntitySearchInput = () => {
const { const {
@ -10,7 +9,7 @@ export const ObjectFilterDropdownEntitySearchInput = () => {
selectedOperandInDropdown, selectedOperandInDropdown,
objectFilterDropdownSearchInput, objectFilterDropdownSearchInput,
setObjectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput,
} = useFilter(); } = useFilterDropdown();
return ( return (
filterDefinitionUsedInDropdown && filterDefinitionUsedInDropdown &&

View File

@ -4,10 +4,9 @@ import { EntitiesForMultipleEntitySelect } from '@/ui/input/relation-picker/comp
import { SingleEntitySelectBase } from '@/ui/input/relation-picker/components/SingleEntitySelectBase'; import { SingleEntitySelectBase } from '@/ui/input/relation-picker/components/SingleEntitySelectBase';
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useFilter } from '../hooks/useFilter';
export const ObjectFilterDropdownEntitySearchSelect = ({ export const ObjectFilterDropdownEntitySearchSelect = ({
entitiesForSelect, entitiesForSelect,
}: { }: {
@ -20,7 +19,7 @@ export const ObjectFilterDropdownEntitySearchSelect = ({
objectFilterDropdownSearchInput, objectFilterDropdownSearchInput,
selectedFilter, selectedFilter,
selectFilter, selectFilter,
} = useFilter(); } = useFilterDropdown();
const { closeDropdown } = useDropdown(); const { closeDropdown } = useDropdown();

View File

@ -4,15 +4,14 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery'; import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker'; import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker';
import { ObjectFilterDropdownEntitySearchSelect } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect'; import { ObjectFilterDropdownEntitySearchSelect } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { useFilter } from '../hooks/useFilter';
export const ObjectFilterDropdownEntitySelect = () => { export const ObjectFilterDropdownEntitySelect = () => {
const { const {
filterDefinitionUsedInDropdown, filterDefinitionUsedInDropdown,
objectFilterDropdownSearchInput, objectFilterDropdownSearchInput,
objectFilterDropdownSelectedEntityId, objectFilterDropdownSelectedEntityId,
} = useFilter(); } = useFilterDropdown();
const objectMetadataNameSingular = const objectMetadataNameSingular =
filterDefinitionUsedInDropdown?.relationObjectMetadataNameSingular ?? ''; filterDefinitionUsedInDropdown?.relationObjectMetadataNameSingular ?? '';

View File

@ -2,9 +2,9 @@ import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons';
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { useFilter } from '../hooks/useFilter';
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType'; import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
export const ObjectFilterDropdownFilterSelect = () => { export const ObjectFilterDropdownFilterSelect = () => {
@ -13,7 +13,7 @@ export const ObjectFilterDropdownFilterSelect = () => {
setSelectedOperandInDropdown, setSelectedOperandInDropdown,
setObjectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput,
availableFilterDefinitions, availableFilterDefinitions,
} = useFilter(); } = useFilterDropdown();
const { icons } = useLazyLoadIcons(); const { icons } = useLazyLoadIcons();

View File

@ -1,15 +1,14 @@
import { ChangeEvent } from 'react'; import { ChangeEvent } from 'react';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { useFilter } from '../hooks/useFilter';
export const ObjectFilterDropdownNumberSearchInput = () => { export const ObjectFilterDropdownNumberSearchInput = () => {
const { const {
selectedOperandInDropdown, selectedOperandInDropdown,
filterDefinitionUsedInDropdown, filterDefinitionUsedInDropdown,
selectFilter, selectFilter,
} = useFilter(); } = useFilterDropdown();
return ( return (
filterDefinitionUsedInDropdown && filterDefinitionUsedInDropdown &&

View File

@ -1,7 +1,7 @@
import { IconChevronDown } from '@/ui/display/icon'; import { IconChevronDown } from '@/ui/display/icon';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader'; import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { useFilter } from '../hooks/useFilter';
import { getOperandLabel } from '../utils/getOperandLabel'; import { getOperandLabel } from '../utils/getOperandLabel';
export const ObjectFilterDropdownOperandButton = () => { export const ObjectFilterDropdownOperandButton = () => {
@ -9,7 +9,7 @@ export const ObjectFilterDropdownOperandButton = () => {
selectedOperandInDropdown, selectedOperandInDropdown,
setIsObjectFilterDropdownOperandSelectUnfolded, setIsObjectFilterDropdownOperandSelectUnfolded,
isObjectFilterDropdownOperandSelectUnfolded, isObjectFilterDropdownOperandSelectUnfolded,
} = useFilter(); } = useFilterDropdown();
if (isObjectFilterDropdownOperandSelectUnfolded) { if (isObjectFilterDropdownOperandSelectUnfolded) {
return null; return null;

View File

@ -1,8 +1,8 @@
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useFilter } from '../hooks/useFilter';
import { getOperandLabel } from '../utils/getOperandLabel'; import { getOperandLabel } from '../utils/getOperandLabel';
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType'; import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
@ -14,7 +14,7 @@ export const ObjectFilterDropdownOperandSelect = () => {
setIsObjectFilterDropdownOperandSelectUnfolded, setIsObjectFilterDropdownOperandSelectUnfolded,
selectedFilter, selectedFilter,
selectFilter, selectFilter,
} = useFilter(); } = useFilterDropdown();
const operandsForFilterType = getOperandsForFilterType( const operandsForFilterType = getOperandsForFilterType(
filterDefinitionUsedInDropdown?.type, filterDefinitionUsedInDropdown?.type,

View File

@ -1,8 +1,7 @@
import { ChangeEvent } from 'react'; import { ChangeEvent } from 'react';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { useFilter } from '../hooks/useFilter';
export const ObjectFilterDropdownTextSearchInput = () => { export const ObjectFilterDropdownTextSearchInput = () => {
const { const {
@ -12,7 +11,7 @@ export const ObjectFilterDropdownTextSearchInput = () => {
setObjectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput,
selectedFilter, selectedFilter,
selectFilter, selectFilter,
} = useFilter(); } = useFilterDropdown();
return ( return (
filterDefinitionUsedInDropdown && filterDefinitionUsedInDropdown &&

View File

@ -5,10 +5,10 @@ import { IconChevronDown } from '@/ui/display/icon/index';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useFilter } from '../hooks/useFilter';
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType'; import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
import { GenericEntityFilterChip } from './GenericEntityFilterChip'; import { GenericEntityFilterChip } from './GenericEntityFilterChip';
@ -25,7 +25,7 @@ export const SingleEntityObjectFilterDropdownButton = ({
selectedFilter, selectedFilter,
setFilterDefinitionUsedInDropdown, setFilterDefinitionUsedInDropdown,
setSelectedOperandInDropdown, setSelectedOperandInDropdown,
} = useFilter(); } = useFilterDropdown();
const availableFilter = availableFilterDefinitions[0]; const availableFilter = availableFilterDefinitions[0];

View File

@ -1,22 +1,21 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useFilterDropdownStates } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdownStates';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { useScopeInternalContextOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow';
import { ObjectFilterDropdownScopeInternalContext } from '../scopes/scope-internal-context/ObjectFilterDropdownScopeInternalContext'; import { ObjectFilterDropdownScopeInternalContext } from '../scopes/scope-internal-context/ObjectFilterDropdownScopeInternalContext';
import { Filter } from '../types/Filter'; import { Filter } from '../types/Filter';
import { useFilterStates } from './useFilterStates'; type UseFilterDropdownProps = {
filterDropdownId?: string;
type UseFilterProps = {
filterScopeId?: string;
}; };
export const useFilter = (props?: UseFilterProps) => { export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
const scopeId = useAvailableScopeIdOrThrow( const scopeId = useAvailableScopeIdOrThrow(
ObjectFilterDropdownScopeInternalContext, ObjectFilterDropdownScopeInternalContext,
props?.filterScopeId, props?.filterDropdownId,
); );
const { const {
availableFilterDefinitions, availableFilterDefinitions,
setAvailableFilterDefinitions, setAvailableFilterDefinitions,
@ -34,11 +33,9 @@ export const useFilter = (props?: UseFilterProps) => {
setSelectedFilter, setSelectedFilter,
selectedOperandInDropdown, selectedOperandInDropdown,
setSelectedOperandInDropdown, setSelectedOperandInDropdown,
} = useFilterStates(scopeId); onFilterSelect,
setOnFilterSelect,
const { onFilterSelect } = useScopeInternalContextOrThrow( } = useFilterDropdownStates(scopeId);
ObjectFilterDropdownScopeInternalContext,
);
const selectFilter = useCallback( const selectFilter = useCallback(
(filter: Filter) => { (filter: Filter) => {
@ -82,5 +79,7 @@ export const useFilter = (props?: UseFilterProps) => {
setSelectedOperandInDropdown, setSelectedOperandInDropdown,
selectFilter, selectFilter,
resetFilter, resetFilter,
onFilterSelect,
setOnFilterSelect,
}; };
}; };

View File

@ -1,3 +1,4 @@
import { onFilterSelectScopedState } from '@/ui/object/object-filter-dropdown/states/onFilterSelectScopedState';
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2'; import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState'; import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState';
@ -9,7 +10,7 @@ import { objectFilterDropdownSelectedEntityIdScopedState } from '../states/objec
import { selectedFilterScopedState } from '../states/selectedFilterScopedState'; import { selectedFilterScopedState } from '../states/selectedFilterScopedState';
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState'; import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
export const useFilterStates = (scopeId: string) => { export const useFilterDropdownStates = (scopeId: string) => {
const [availableFilterDefinitions, setAvailableFilterDefinitions] = const [availableFilterDefinitions, setAvailableFilterDefinitions] =
useRecoilScopedStateV2(availableFilterDefinitionsScopedState, scopeId); useRecoilScopedStateV2(availableFilterDefinitionsScopedState, scopeId);
@ -46,6 +47,11 @@ export const useFilterStates = (scopeId: string) => {
const [selectedOperandInDropdown, setSelectedOperandInDropdown] = const [selectedOperandInDropdown, setSelectedOperandInDropdown] =
useRecoilScopedStateV2(selectedOperandInDropdownScopedState, scopeId); useRecoilScopedStateV2(selectedOperandInDropdownScopedState, scopeId);
const [onFilterSelect, setOnFilterSelect] = useRecoilScopedStateV2(
onFilterSelectScopedState,
scopeId,
);
return { return {
availableFilterDefinitions, availableFilterDefinitions,
setAvailableFilterDefinitions, setAvailableFilterDefinitions,
@ -63,5 +69,7 @@ export const useFilterStates = (scopeId: string) => {
setSelectedFilter, setSelectedFilter,
selectedOperandInDropdown, selectedOperandInDropdown,
setSelectedOperandInDropdown, setSelectedOperandInDropdown,
onFilterSelect,
setOnFilterSelect,
}; };
}; };

View File

@ -1,33 +1,20 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { FilterDefinition } from '@/ui/object/object-filter-dropdown/types/FilterDefinition';
import { Filter } from '../types/Filter';
import { ObjectFilterDropdownScopeInitEffect } from './init-effect/ObjectFilterDropdownScopeInitEffect';
import { ObjectFilterDropdownScopeInternalContext } from './scope-internal-context/ObjectFilterDropdownScopeInternalContext'; import { ObjectFilterDropdownScopeInternalContext } from './scope-internal-context/ObjectFilterDropdownScopeInternalContext';
type ObjectFilterDropdownScopeProps = { type ObjectFilterDropdownScopeProps = {
children: ReactNode; children: ReactNode;
filterScopeId: string; filterScopeId: string;
availableFilterDefinitions?: FilterDefinition[];
onFilterSelect?: (filter: Filter) => void;
}; };
export const ObjectFilterDropdownScope = ({ export const ObjectFilterDropdownScope = ({
children, children,
filterScopeId, filterScopeId,
availableFilterDefinitions,
onFilterSelect,
}: ObjectFilterDropdownScopeProps) => { }: ObjectFilterDropdownScopeProps) => {
return ( return (
<ObjectFilterDropdownScopeInternalContext.Provider <ObjectFilterDropdownScopeInternalContext.Provider
value={{ scopeId: filterScopeId, onFilterSelect }} value={{ scopeId: filterScopeId }}
> >
<ObjectFilterDropdownScopeInitEffect
filterScopeId={filterScopeId}
availableFilterDefinitions={availableFilterDefinitions}
/>
{children} {children}
</ObjectFilterDropdownScopeInternalContext.Provider> </ObjectFilterDropdownScopeInternalContext.Provider>
); );

View File

@ -1,25 +0,0 @@
import { useEffect } from 'react';
import { FilterDefinition } from '@/ui/object/object-filter-dropdown/types/FilterDefinition';
import { useFilterStates } from '../../hooks/useFilterStates';
type ObjectFilterDropdownScopeInitEffectProps = {
filterScopeId: string;
availableFilterDefinitions?: FilterDefinition[];
};
export const ObjectFilterDropdownScopeInitEffect = ({
filterScopeId,
availableFilterDefinitions,
}: ObjectFilterDropdownScopeInitEffectProps) => {
const { setAvailableFilterDefinitions } = useFilterStates(filterScopeId);
useEffect(() => {
if (availableFilterDefinitions) {
setAvailableFilterDefinitions(availableFilterDefinitions);
}
}, [availableFilterDefinitions, setAvailableFilterDefinitions]);
return <></>;
};

View File

@ -1,11 +1,7 @@
import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey'; import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey';
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
import { Filter } from '../../types/Filter'; type ObjectFilterDropdownScopeInternalContextProps = ScopedStateKey;
type ObjectFilterDropdownScopeInternalContextProps = ScopedStateKey & {
onFilterSelect?: (sort: Filter) => void;
};
export const ObjectFilterDropdownScopeInternalContext = export const ObjectFilterDropdownScopeInternalContext =
createScopeInternalContext<ObjectFilterDropdownScopeInternalContextProps>(); createScopeInternalContext<ObjectFilterDropdownScopeInternalContextProps>();

View File

@ -0,0 +1,10 @@
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
import { Filter } from '../types/Filter';
export const onFilterSelectScopedState = createScopedState<
((filter: Filter) => void) | undefined
>({
key: 'onFilterSelectScopedState',
defaultValue: undefined,
});

View File

@ -10,19 +10,21 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useSortDropdown } from '@/ui/object/object-sort-dropdown/hooks/useSortDropdown';
import { ObjectSortDropdownScope } from '@/ui/object/object-sort-dropdown/scopes/ObjectSortDropdownScope';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { ObjectSortDropdownId } from '../constants/ObjectSortDropdownId'; import { ObjectSortDropdownId } from '../constants/ObjectSortDropdownId';
import { useObjectSortDropdown } from '../hooks/useObjectSortDropdown';
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 ObjectSortDropdownButtonProps = { export type ObjectSortDropdownButtonProps = {
sortDropdownId: string;
hotkeyScope: HotkeyScope; hotkeyScope: HotkeyScope;
isPrimaryButton?: boolean;
}; };
export const ObjectSortDropdownButton = ({ export const ObjectSortDropdownButton = ({
sortDropdownId,
hotkeyScope, hotkeyScope,
}: ObjectSortDropdownButtonProps) => { }: ObjectSortDropdownButtonProps) => {
const [isSortDirectionMenuUnfolded, setIsSortDirectionMenuUnfolded] = const [isSortDirectionMenuUnfolded, setIsSortDirectionMenuUnfolded] =
@ -36,8 +38,9 @@ export const ObjectSortDropdownButton = ({
setSelectedSortDirection('asc'); setSelectedSortDirection('asc');
}, []); }, []);
const { availableSortDefinitions, onSortSelect, isSortSelected } = const { isSortSelected } = useSortDropdown({
useObjectSortDropdown(); sortDropdownId: sortDropdownId,
});
const { toggleDropdown } = useDropdown({ const { toggleDropdown } = useDropdown({
dropdownScopeId: ObjectSortDropdownId, dropdownScopeId: ObjectSortDropdownId,
@ -48,6 +51,10 @@ export const ObjectSortDropdownButton = ({
resetState(); resetState();
}; };
const { availableSortDefinitions, onSortSelect } = useSortDropdown({
sortDropdownId: sortDropdownId,
});
const handleAddSort = (selectedSortDefinition: SortDefinition) => { const handleAddSort = (selectedSortDefinition: SortDefinition) => {
toggleDropdown(); toggleDropdown();
onSortSelect?.({ onSortSelect?.({
@ -64,60 +71,64 @@ export const ObjectSortDropdownButton = ({
const { icons } = useLazyLoadIcons(); const { icons } = useLazyLoadIcons();
return ( return (
<DropdownScope dropdownScopeId={ObjectSortDropdownId}> <ObjectSortDropdownScope sortScopeId={sortDropdownId}>
<Dropdown <DropdownScope dropdownScopeId={ObjectSortDropdownId}>
dropdownHotkeyScope={hotkeyScope} <Dropdown
dropdownOffset={{ y: 8 }} dropdownHotkeyScope={hotkeyScope}
clickableComponent={ dropdownOffset={{ y: 8 }}
<LightButton clickableComponent={
title="Sort" <LightButton
active={isSortSelected} title="Sort"
onClick={handleButtonClick} active={isSortSelected}
/> onClick={handleButtonClick}
} />
dropdownComponents={ }
<> dropdownComponents={
{isSortDirectionMenuUnfolded ? ( <>
<DropdownMenuItemsContainer> {isSortDirectionMenuUnfolded ? (
{SORT_DIRECTIONS.map((sortOrder, index) => (
<MenuItem
key={index}
onClick={() => {
setSelectedSortDirection(sortOrder);
setIsSortDirectionMenuUnfolded(false);
}}
text={sortOrder === 'asc' ? 'Ascending' : 'Descending'}
/>
))}
</DropdownMenuItemsContainer>
) : (
<>
<DropdownMenuHeader
EndIcon={IconChevronDown}
onClick={() => setIsSortDirectionMenuUnfolded(true)}
>
{selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'}
</DropdownMenuHeader>
<DropdownMenuSeparator />
<DropdownMenuItemsContainer> <DropdownMenuItemsContainer>
{[...availableSortDefinitions] {SORT_DIRECTIONS.map((sortOrder, index) => (
.sort((a, b) => a.label.localeCompare(b.label)) <MenuItem
.map((availableSortDefinition, index) => ( key={index}
<MenuItem onClick={() => {
testId={`select-sort-${index}`} setSelectedSortDirection(sortOrder);
key={index} setIsSortDirectionMenuUnfolded(false);
onClick={() => handleAddSort(availableSortDefinition)} }}
LeftIcon={icons[availableSortDefinition.iconName]} text={sortOrder === 'asc' ? 'Ascending' : 'Descending'}
text={availableSortDefinition.label} />
/> ))}
))}
</DropdownMenuItemsContainer> </DropdownMenuItemsContainer>
</> ) : (
)} <>
</> <DropdownMenuHeader
} EndIcon={IconChevronDown}
onClose={handleDropdownButtonClose} onClick={() => setIsSortDirectionMenuUnfolded(true)}
/> >
</DropdownScope> {selectedSortDirection === 'asc'
? 'Ascending'
: 'Descending'}
</DropdownMenuHeader>
<DropdownMenuSeparator />
<DropdownMenuItemsContainer>
{[...availableSortDefinitions]
.sort((a, b) => a.label.localeCompare(b.label))
.map((availableSortDefinition, index) => (
<MenuItem
testId={`select-sort-${index}`}
key={index}
onClick={() => handleAddSort(availableSortDefinition)}
LeftIcon={icons[availableSortDefinition.iconName]}
text={availableSortDefinition.label}
/>
))}
</DropdownMenuItemsContainer>
</>
)}
</>
}
onClose={handleDropdownButtonClose}
/>
</DropdownScope>
</ObjectSortDropdownScope>
); );
}; };

View File

@ -1,36 +1,33 @@
import { useSortDropdownStates } from '@/ui/object/object-sort-dropdown/hooks/useSortDropdownStates';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { useScopeInternalContextOrThrow } from '../../../utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow';
import { ObjectSortDropdownScopeInternalContext } from '../scopes/scope-internal-context/ObjectSortDropdownScopeInternalContext'; import { ObjectSortDropdownScopeInternalContext } from '../scopes/scope-internal-context/ObjectSortDropdownScopeInternalContext';
import { useObjectSortDropdownStates } from './useObjectSortDropdownStates';
type UseSortProps = { type UseSortProps = {
sortScopeId?: string; sortDropdownId?: string;
}; };
export const useObjectSortDropdown = (props?: UseSortProps) => { export const useSortDropdown = (props?: UseSortProps) => {
const scopeId = useAvailableScopeIdOrThrow( const scopeId = useAvailableScopeIdOrThrow(
ObjectSortDropdownScopeInternalContext, ObjectSortDropdownScopeInternalContext,
props?.sortScopeId, props?.sortDropdownId,
); );
const { const {
availableSortDefinitions, availableSortDefinitions,
setAvailableSortDefinitions, setAvailableSortDefinitions,
isSortSelected, isSortSelected,
setIsSortSelected, setIsSortSelected,
} = useObjectSortDropdownStates(scopeId); onSortSelect,
setOnSortSelect,
const { onSortSelect } = useScopeInternalContextOrThrow( } = useSortDropdownStates(scopeId);
ObjectSortDropdownScopeInternalContext,
);
return { return {
onSortSelect,
scopeId, scopeId,
availableSortDefinitions, availableSortDefinitions,
isSortSelected, isSortSelected,
setIsSortSelected, setIsSortSelected,
setAvailableSortDefinitions, setAvailableSortDefinitions,
onSortSelect,
setOnSortSelect,
}; };
}; };

View File

@ -1,9 +1,10 @@
import { onSortSelectScopedState } from '@/ui/object/object-sort-dropdown/states/onSortSelectScopedState';
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2'; import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState'; import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState';
import { isSortSelectedScopedState } from '../states/isSortSelectedScopedState'; import { isSortSelectedScopedState } from '../states/isSortSelectedScopedState';
export const useObjectSortDropdownStates = (scopeId: string) => { export const useSortDropdownStates = (scopeId: string) => {
const [availableSortDefinitions, setAvailableSortDefinitions] = const [availableSortDefinitions, setAvailableSortDefinitions] =
useRecoilScopedStateV2(availableSortDefinitionsScopedState, scopeId); useRecoilScopedStateV2(availableSortDefinitionsScopedState, scopeId);
@ -12,10 +13,17 @@ export const useObjectSortDropdownStates = (scopeId: string) => {
scopeId, scopeId,
); );
const [onSortSelect, setOnSortSelect] = useRecoilScopedStateV2(
onSortSelectScopedState,
scopeId,
);
return { return {
availableSortDefinitions, availableSortDefinitions,
setAvailableSortDefinitions, setAvailableSortDefinitions,
isSortSelected, isSortSelected,
setIsSortSelected, setIsSortSelected,
onSortSelect,
setOnSortSelect,
}; };
}; };

View File

@ -1,32 +1,20 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Sort } from '../types/Sort';
import { SortDefinition } from '../types/SortDefinition';
import { ObjectSortDropdownScopeInitEffect } from './init-effect/ObjectSortDropdownScopeInitEffect';
import { ObjectSortDropdownScopeInternalContext } from './scope-internal-context/ObjectSortDropdownScopeInternalContext'; import { ObjectSortDropdownScopeInternalContext } from './scope-internal-context/ObjectSortDropdownScopeInternalContext';
type ObjectSortDropdownScopeProps = { type ObjectSortDropdownScopeProps = {
children: ReactNode; children: ReactNode;
sortScopeId: string; sortScopeId: string;
availableSortDefinitions?: SortDefinition[];
onSortSelect?: (sort: Sort) => void | Promise<void>;
}; };
export const ObjectSortDropdownScope = ({ export const ObjectSortDropdownScope = ({
children, children,
sortScopeId, sortScopeId,
availableSortDefinitions,
onSortSelect,
}: ObjectSortDropdownScopeProps) => { }: ObjectSortDropdownScopeProps) => {
return ( return (
<ObjectSortDropdownScopeInternalContext.Provider <ObjectSortDropdownScopeInternalContext.Provider
value={{ scopeId: sortScopeId, onSortSelect }} value={{ scopeId: sortScopeId }}
> >
<ObjectSortDropdownScopeInitEffect
sortScopeId={sortScopeId}
availableSortDefinitions={availableSortDefinitions}
/>
{children} {children}
</ObjectSortDropdownScopeInternalContext.Provider> </ObjectSortDropdownScopeInternalContext.Provider>
); );

View File

@ -1,26 +0,0 @@
import { useEffect } from 'react';
import { SortDefinition } from '@/ui/object/object-sort-dropdown/types/SortDefinition';
import { useObjectSortDropdownStates } from '../../hooks/useObjectSortDropdownStates';
type ObjectSortDropdownScopeInitEffectProps = {
sortScopeId: string;
availableSortDefinitions?: SortDefinition[];
};
export const ObjectSortDropdownScopeInitEffect = ({
sortScopeId,
availableSortDefinitions,
}: ObjectSortDropdownScopeInitEffectProps) => {
const { setAvailableSortDefinitions } =
useObjectSortDropdownStates(sortScopeId);
useEffect(() => {
if (availableSortDefinitions) {
setAvailableSortDefinitions(availableSortDefinitions);
}
}, [availableSortDefinitions, setAvailableSortDefinitions]);
return <></>;
};

View File

@ -0,0 +1,10 @@
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
import { Sort } from '../types/Sort';
export const onSortSelectScopedState = createScopedState<
((sort: Sort) => void) | undefined
>({
key: 'onSortSelectScopedState',
defaultValue: undefined,
});

View File

@ -14,6 +14,11 @@ export const turnSortsIntoOrderBy = (
createdAt: 'DescNullsFirst', createdAt: 'DescNullsFirst',
}; };
} }
if (!fields.length) {
return {};
}
return { return {
[fields[0].name]: 'DescNullsFirst', [fields[0].name]: 'DescNullsFirst',
}; };

View File

@ -1,4 +1,4 @@
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
import { Dropdown } from '../../../../layout/dropdown/components/Dropdown'; import { Dropdown } from '../../../../layout/dropdown/components/Dropdown';
import { DropdownScope } from '../../../../layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '../../../../layout/dropdown/scopes/DropdownScope';
@ -19,7 +19,7 @@ type BoardOptionsDropdownProps = Pick<
export const BoardOptionsDropdown = ({ export const BoardOptionsDropdown = ({
onStageAdd, onStageAdd,
}: BoardOptionsDropdownProps) => { }: BoardOptionsDropdownProps) => {
const { setViewEditMode } = useView(); const { setViewEditMode } = useViewBar();
return ( return (
<DropdownScope dropdownScopeId={BoardOptionsDropdownId}> <DropdownScope dropdownScopeId={BoardOptionsDropdownId}>

View File

@ -26,7 +26,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection'; import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
import { useBoardCardFields } from '../../hooks/useBoardCardFields'; import { useBoardCardFields } from '../../hooks/useBoardCardFields';
import { boardColumnsState } from '../../states/boardColumnsState'; import { boardColumnsState } from '../../states/boardColumnsState';
@ -52,7 +52,7 @@ type ColumnForCreate = {
export const BoardOptionsDropdownContent = ({ export const BoardOptionsDropdownContent = ({
onStageAdd, onStageAdd,
}: BoardOptionsDropdownContentProps) => { }: BoardOptionsDropdownContentProps) => {
const { setViewEditMode, handleViewNameSubmit } = useView(); const { setViewEditMode, handleViewNameSubmit } = useViewBar();
const { viewEditModeState, currentViewSelector } = useViewScopedStates(); const { viewEditModeState, currentViewSelector } = useViewScopedStates();
const { BoardRecoilScopeContext } = useContext(BoardContext); const { BoardRecoilScopeContext } = useContext(BoardContext);

View File

@ -1,10 +1,14 @@
import { useRef } from 'react'; import { useRef } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useRecoilCallback } from 'recoil';
import { RecordTableInternalEffect } from '@/ui/object/record-table/components/RecordTableInternalEffect'; import { RecordTableInternalEffect } from '@/ui/object/record-table/components/RecordTableInternalEffect';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { RecordTableScope } from '@/ui/object/record-table/scopes/RecordTableScope';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { useViewFields } from '@/views/hooks/internal/useViewFields';
import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinitionToViewField';
import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHookContext'; import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHookContext';
@ -71,34 +75,50 @@ const StyledTableContainer = styled.div`
`; `;
type RecordTableProps = { type RecordTableProps = {
recordTableId: string;
viewBarId: string;
updateEntityMutation: (params: any) => void; updateEntityMutation: (params: any) => void;
}; };
export const RecordTable = ({ updateEntityMutation }: RecordTableProps) => { export const RecordTable = ({
recordTableId,
viewBarId,
updateEntityMutation,
}: RecordTableProps) => {
const tableBodyRef = useRef<HTMLDivElement>(null); const tableBodyRef = useRef<HTMLDivElement>(null);
const { resetTableRowSelection, setRowSelectedState } = useRecordTable(); const { resetTableRowSelection, setRowSelectedState } = useRecordTable({
recordTableScopeId: recordTableId,
});
const { persistViewFields } = useViewFields(viewBarId);
return ( return (
<ScrollWrapper> <RecordTableScope
<EntityUpdateMutationContext.Provider value={updateEntityMutation}> recordTableScopeId={recordTableId}
<StyledTableWithHeader> onColumnsChange={useRecoilCallback(() => (columns) => {
<StyledTableContainer> persistViewFields(mapColumnDefinitionsToViewFields(columns));
<div ref={tableBodyRef}> })}
<StyledTable className="entity-table-cell"> >
<RecordTableHeader /> <ScrollWrapper>
<RecordTableBody /> <EntityUpdateMutationContext.Provider value={updateEntityMutation}>
</StyledTable> <StyledTableWithHeader>
<DragSelect <StyledTableContainer>
dragSelectable={tableBodyRef} <div ref={tableBodyRef}>
onDragSelectionStart={resetTableRowSelection} <StyledTable className="entity-table-cell">
onDragSelectionChange={setRowSelectedState} <RecordTableHeader />
/> <RecordTableBody />
</div> </StyledTable>
<RecordTableInternalEffect tableBodyRef={tableBodyRef} /> <DragSelect
</StyledTableContainer> dragSelectable={tableBodyRef}
</StyledTableWithHeader> onDragSelectionStart={resetTableRowSelection}
</EntityUpdateMutationContext.Provider> onDragSelectionChange={setRowSelectedState}
</ScrollWrapper> />
</div>
<RecordTableInternalEffect tableBodyRef={tableBodyRef} />
</StyledTableContainer>
</StyledTableWithHeader>
</EntityUpdateMutationContext.Provider>
</ScrollWrapper>
</RecordTableScope>
); );
}; };

View File

@ -1,32 +1,39 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil'; import { useRecoilValue } from 'recoil';
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata'; import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { RecordTableScopeInternalContext } from '@/ui/object/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { useMoveViewColumns } from '@/views/hooks/useMoveViewColumns'; import { useMoveViewColumns } from '@/views/hooks/useMoveViewColumns';
import { useView } from '@/views/hooks/useView';
import { savedTableColumnsFamilyState } from '../states/savedTableColumnsFamilyState';
import { ColumnDefinition } from '../types/ColumnDefinition'; import { ColumnDefinition } from '../types/ColumnDefinition';
import { useRecordTableScopedStates } from './internal/useRecordTableScopedStates'; import { useRecordTableScopedStates } from './internal/useRecordTableScopedStates';
export const useTableColumns = () => { type useRecordTableProps = {
const { onColumnsChange, setTableColumns } = useRecordTable(); recordTableScopeId?: string;
};
export const useTableColumns = (props?: useRecordTableProps) => {
const scopeId = useAvailableScopeIdOrThrow(
RecordTableScopeInternalContext,
props?.recordTableScopeId,
);
const { onColumnsChange, setTableColumns } = useRecordTable({
recordTableScopeId: scopeId,
});
const { const {
availableTableColumnsState, availableTableColumnsState,
tableColumnsState, tableColumnsState,
visibleTableColumnsSelector, visibleTableColumnsSelector,
} = useRecordTableScopedStates(); } = useRecordTableScopedStates({
customRecordTableScopeId: scopeId,
});
const availableTableColumns = useRecoilValue(availableTableColumnsState); const availableTableColumns = useRecoilValue(availableTableColumnsState);
const { currentViewId } = useView();
const setSavedTableColumns = useSetRecoilState(
savedTableColumnsFamilyState(currentViewId),
);
const tableColumns = useRecoilValue(tableColumnsState); const tableColumns = useRecoilValue(tableColumnsState);
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector); const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
@ -34,12 +41,11 @@ export const useTableColumns = () => {
const handleColumnsChange = useCallback( const handleColumnsChange = useCallback(
async (columns: ColumnDefinition<FieldMetadata>[]) => { async (columns: ColumnDefinition<FieldMetadata>[]) => {
setSavedTableColumns(columns);
setTableColumns(columns); setTableColumns(columns);
await onColumnsChange?.(columns); await onColumnsChange?.(columns);
}, },
[onColumnsChange, setSavedTableColumns, setTableColumns], [onColumnsChange, setTableColumns],
); );
const handleColumnVisibilityChange = useCallback( const handleColumnVisibilityChange = useCallback(

View File

@ -1,6 +1,6 @@
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId'; import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId';
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope'; import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
@ -10,10 +10,12 @@ import { TableOptionsDropdownContent } from './TableOptionsDropdownContent';
export const TableOptionsDropdown = ({ export const TableOptionsDropdown = ({
onImport, onImport,
recordTableId,
}: { }: {
onImport?: () => void; onImport?: () => void;
recordTableId: string;
}) => { }) => {
const { setViewEditMode } = useView(); const { setViewEditMode } = useViewBar();
return ( return (
<DropdownScope dropdownScopeId={TableOptionsDropdownId}> <DropdownScope dropdownScopeId={TableOptionsDropdownId}>
@ -21,7 +23,12 @@ export const TableOptionsDropdown = ({
clickableComponent={<TableOptionsDropdownButton />} clickableComponent={<TableOptionsDropdownButton />}
dropdownHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }} dropdownHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }}
dropdownOffset={{ y: 8 }} dropdownOffset={{ y: 8 }}
dropdownComponents={<TableOptionsDropdownContent onImport={onImport} />} dropdownComponents={
<TableOptionsDropdownContent
onImport={onImport}
recordTableId={recordTableId}
/>
}
onClickOutside={() => setViewEditMode('none')} onClickOutside={() => setViewEditMode('none')}
/> />
</DropdownScope> </DropdownScope>

View File

@ -13,7 +13,7 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection'; import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
import { useRecordTableScopedStates } from '../../hooks/internal/useRecordTableScopedStates'; import { useRecordTableScopedStates } from '../../hooks/internal/useRecordTableScopedStates';
import { useTableColumns } from '../../hooks/useTableColumns'; import { useTableColumns } from '../../hooks/useTableColumns';
@ -23,10 +23,12 @@ type TableOptionsMenu = 'fields';
export const TableOptionsDropdownContent = ({ export const TableOptionsDropdownContent = ({
onImport, onImport,
recordTableId,
}: { }: {
onImport?: () => void; onImport?: () => void;
recordTableId: string;
}) => { }) => {
const { setViewEditMode, handleViewNameSubmit } = useView(); const { setViewEditMode, handleViewNameSubmit } = useViewBar();
const { viewEditModeState, currentViewSelector } = useViewScopedStates(); const { viewEditModeState, currentViewSelector } = useViewScopedStates();
const viewEditMode = useRecoilValue(viewEditModeState); const viewEditMode = useRecoilValue(viewEditModeState);
@ -40,13 +42,14 @@ export const TableOptionsDropdownContent = ({
const viewEditInputRef = useRef<HTMLInputElement>(null); const viewEditInputRef = useRef<HTMLInputElement>(null);
const { hiddenTableColumnsSelector, visibleTableColumnsSelector } = const { hiddenTableColumnsSelector, visibleTableColumnsSelector } =
useRecordTableScopedStates(); useRecordTableScopedStates({ customRecordTableScopeId: recordTableId });
const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector); const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector);
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector); const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
const { handleColumnVisibilityChange, handleColumnReorder } = const { handleColumnVisibilityChange, handleColumnReorder } = useTableColumns(
useTableColumns(); { recordTableScopeId: recordTableId },
);
const handleSelectMenu = (option: TableOptionsMenu) => { const handleSelectMenu = (option: TableOptionsMenu) => {
const name = viewEditInputRef.current?.value; const name = viewEditInputRef.current?.value;

View File

@ -1,13 +0,0 @@
import { atomFamily } from 'recoil';
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
import { ColumnDefinition } from '../types/ColumnDefinition';
export const savedTableColumnsFamilyState = atomFamily<
ColumnDefinition<FieldMetadata>[],
string | undefined
>({
key: 'savedTableColumnsFamilyState',
default: [],
});

View File

@ -1,19 +0,0 @@
import { selectorFamily } from 'recoil';
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
import { ColumnDefinition } from '../../types/ColumnDefinition';
import { savedTableColumnsFamilyState } from '../savedTableColumnsFamilyState';
export const savedTableColumnsByKeyFamilySelector = selectorFamily({
key: 'savedTableColumnsByKeyFamilySelector',
get:
(viewId: string | undefined) =>
({ get }) =>
get(savedTableColumnsFamilyState(viewId)).reduce<
Record<string, ColumnDefinition<FieldMetadata>>
>(
(result, column) => ({ ...result, [column.fieldMetadataId]: column }),
{},
),
});

View File

@ -9,7 +9,7 @@ import { ButtonGroup } from '@/ui/input/button/components/ButtonGroup';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useView } from '@/views/hooks/useView'; import { useViewBar } from '@/views/hooks/useViewBar';
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates'; import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
@ -29,7 +29,7 @@ export const UpdateViewButtonGroup = ({
onViewEditModeChange, onViewEditModeChange,
}: UpdateViewButtonGroupProps) => { }: UpdateViewButtonGroupProps) => {
const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const { updateCurrentView, setViewEditMode } = useView(); const { updateCurrentView, setViewEditMode } = useViewBar();
const { canPersistFiltersSelector, canPersistSortsSelector } = const { canPersistFiltersSelector, canPersistSortsSelector } =
useViewScopedStates(); useViewScopedStates();

View File

@ -1,16 +1,18 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { useRecoilValue } from 'recoil';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { TopBar } from '@/ui/layout/top-bar/TopBar'; import { TopBar } from '@/ui/layout/top-bar/TopBar';
import { ObjectFilterDropdownButton } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownButton'; import { ObjectFilterDropdownButton } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownButton';
import { ObjectFilterDropdownScope } from '@/ui/object/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
import { FiltersHotkeyScope } from '@/ui/object/object-filter-dropdown/types/FiltersHotkeyScope'; import { FiltersHotkeyScope } from '@/ui/object/object-filter-dropdown/types/FiltersHotkeyScope';
import { ObjectSortDropdownButton } from '@/ui/object/object-sort-dropdown/components/ObjectSortDropdownButton'; import { ObjectSortDropdownButton } from '@/ui/object/object-sort-dropdown/components/ObjectSortDropdownButton';
import { ObjectSortDropdownScope } from '@/ui/object/object-sort-dropdown/scopes/ObjectSortDropdownScope'; import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewScope } from '@/views/scopes/ViewScope';
import { ViewField } from '@/views/types/ViewField';
import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewSort } from '@/views/types/ViewSort';
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
import { useView } from '../hooks/useView';
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope'; import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup'; import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
@ -19,82 +21,91 @@ import { ViewBarEffect } from './ViewBarEffect';
import { ViewsDropdownButton } from './ViewsDropdownButton'; import { ViewsDropdownButton } from './ViewsDropdownButton';
export type ViewBarProps = { export type ViewBarProps = {
viewBarId: string;
className?: string; className?: string;
optionsDropdownButton: ReactNode; optionsDropdownButton: ReactNode;
optionsDropdownScopeId: string; optionsDropdownScopeId: string;
onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>;
onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>;
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
}; };
export const ViewBar = ({ export const ViewBar = ({
viewBarId,
className, className,
optionsDropdownButton, optionsDropdownButton,
optionsDropdownScopeId, optionsDropdownScopeId,
onViewFieldsChange,
onViewFiltersChange,
onViewSortsChange,
}: ViewBarProps) => { }: ViewBarProps) => {
const { openDropdown: openOptionsDropdownButton } = useDropdown({ const { openDropdown: openOptionsDropdownButton } = useDropdown({
dropdownScopeId: optionsDropdownScopeId, dropdownScopeId: optionsDropdownScopeId,
}); });
const { upsertViewSort, upsertViewFilter } = useView(); const { upsertViewSort, upsertViewFilter } = useViewBar({
viewBarId: viewBarId,
});
const { availableFilterDefinitionsState, availableSortDefinitionsState } = const filterDropdownId = 'view-filter';
useViewScopedStates(); const sortDropdownId = 'view-sort';
const availableFilterDefinitions = useRecoilValue(
availableFilterDefinitionsState,
);
const availableSortDefinitions = useRecoilValue(
availableSortDefinitionsState,
);
return ( return (
<ObjectFilterDropdownScope <ViewScope
filterScopeId="view-filter" viewScopeId={viewBarId}
availableFilterDefinitions={availableFilterDefinitions} onViewFieldsChange={onViewFieldsChange}
onFilterSelect={upsertViewFilter} onViewFiltersChange={onViewFiltersChange}
onViewSortsChange={onViewSortsChange}
> >
<ObjectSortDropdownScope <ViewBarEffect />
sortScopeId="view-sort" <ViewBarFilterEffect
availableSortDefinitions={availableSortDefinitions} filterDropdownId={filterDropdownId}
onFilterSelect={upsertViewFilter}
/>
<ViewBarSortEffect
sortDropdownId={sortDropdownId}
onSortSelect={upsertViewSort} onSortSelect={upsertViewSort}
> />
<ViewBarEffect />
<TopBar <TopBar
className={className} className={className}
leftComponent={ leftComponent={
<ViewsDropdownButton <ViewsDropdownButton
onViewEditModeChange={openOptionsDropdownButton} onViewEditModeChange={openOptionsDropdownButton}
hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }} hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
optionsDropdownScopeId={optionsDropdownScopeId} optionsDropdownScopeId={optionsDropdownScopeId}
/>
}
displayBottomBorder={false}
rightComponent={
<>
<ObjectFilterDropdownButton
filterDropdownId={filterDropdownId}
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
}}
/> />
} <ObjectSortDropdownButton
displayBottomBorder={false} sortDropdownId={sortDropdownId}
rightComponent={ hotkeyScope={{
<> scope: FiltersHotkeyScope.ObjectSortDropdownButton,
<ObjectFilterDropdownButton }}
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
}}
/>
<ObjectSortDropdownButton
hotkeyScope={{
scope: FiltersHotkeyScope.ObjectSortDropdownButton,
}}
isPrimaryButton
/>
{optionsDropdownButton}
</>
}
bottomComponent={
<ViewBarDetails
hasFilterButton
rightComponent={
<UpdateViewButtonGroup
onViewEditModeChange={openOptionsDropdownButton}
hotkeyScope={ViewsHotkeyScope.CreateDropdown}
/>
}
/> />
} {optionsDropdownButton}
/> </>
</ObjectSortDropdownScope> }
</ObjectFilterDropdownScope> bottomComponent={
<ViewBarDetails
filterDropdownId={filterDropdownId}
hasFilterButton
rightComponent={
<UpdateViewButtonGroup
onViewEditModeChange={openOptionsDropdownButton}
hotkeyScope={ViewsHotkeyScope.CreateDropdown}
/>
}
/>
}
/>
</ViewScope>
); );
}; };

View File

@ -6,15 +6,16 @@ import { IconArrowDown, IconArrowUp } from '@/ui/display/icon/index';
import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons'; import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons';
import { AddObjectFilterFromDetailsButton } from '@/ui/object/object-filter-dropdown/components/AddObjectFilterFromDetailsButton'; import { AddObjectFilterFromDetailsButton } from '@/ui/object/object-filter-dropdown/components/AddObjectFilterFromDetailsButton';
import { getOperandLabelShort } from '@/ui/object/object-filter-dropdown/utils/getOperandLabel'; import { getOperandLabelShort } from '@/ui/object/object-filter-dropdown/utils/getOperandLabel';
import { useViewBar } from '@/views/hooks/useViewBar';
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates'; import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
import { useView } from '../hooks/useView';
import SortOrFilterChip from './SortOrFilterChip'; import SortOrFilterChip from './SortOrFilterChip';
export type ViewBarDetailsProps = { export type ViewBarDetailsProps = {
hasFilterButton?: boolean; hasFilterButton?: boolean;
rightComponent?: ReactNode; rightComponent?: ReactNode;
filterDropdownId?: string;
}; };
const StyledBar = styled.div` const StyledBar = styled.div`
@ -88,6 +89,7 @@ const StyledAddFilterContainer = styled.div`
export const ViewBarDetails = ({ export const ViewBarDetails = ({
hasFilterButton = false, hasFilterButton = false,
rightComponent, rightComponent,
filterDropdownId,
}: ViewBarDetailsProps) => { }: ViewBarDetailsProps) => {
const { const {
currentViewSortsState, currentViewSortsState,
@ -104,7 +106,7 @@ export const ViewBarDetails = ({
const canPersistSorts = useRecoilValue(canPersistSortsSelector); const canPersistSorts = useRecoilValue(canPersistSortsSelector);
const isViewBarExpanded = useRecoilValue(isViewBarExpandedState); const isViewBarExpanded = useRecoilValue(isViewBarExpandedState);
const { resetViewBar, removeViewSort, removeViewFilter } = useView(); const { resetViewBar, removeViewSort, removeViewFilter } = useViewBar();
const canPersistView = canPersistFilters || canPersistSorts; const canPersistView = canPersistFilters || canPersistSorts;
@ -161,7 +163,9 @@ export const ViewBarDetails = ({
</StyledChipcontainer> </StyledChipcontainer>
{hasFilterButton && ( {hasFilterButton && (
<StyledAddFilterContainer> <StyledAddFilterContainer>
<AddObjectFilterFromDetailsButton /> <AddObjectFilterFromDetailsButton
filterDropdownId={filterDropdownId}
/>
</StyledAddFilterContainer> </StyledAddFilterContainer>
)} )}
</StyledFilterContainer> </StyledFilterContainer>

View File

@ -5,11 +5,11 @@ import { useRecoilCallback, useRecoilValue } from 'recoil';
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords'; import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults'; import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useViewBar } from '@/views/hooks/useViewBar';
import { GraphQLView } from '@/views/types/GraphQLView'; import { GraphQLView } from '@/views/types/GraphQLView';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates'; import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
import { useView } from '../hooks/useView';
import { getViewScopedStatesFromSnapshot } from '../utils/getViewScopedStatesFromSnapshot'; import { getViewScopedStatesFromSnapshot } from '../utils/getViewScopedStatesFromSnapshot';
export const ViewBarEffect = () => { export const ViewBarEffect = () => {
@ -20,7 +20,7 @@ export const ViewBarEffect = () => {
loadViewFields, loadViewFields,
loadViewFilters, loadViewFilters,
loadViewSorts, loadViewSorts,
} = useView(); } = useViewBar();
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const currentViewIdFromUrl = searchParams.get('view'); const currentViewIdFromUrl = searchParams.get('view');

View File

@ -0,0 +1,41 @@
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { Filter } from '@/ui/object/object-filter-dropdown/types/Filter';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
type ViewBarFilterEffectProps = {
filterDropdownId: string;
onFilterSelect?: ((filter: Filter) => void) | undefined;
};
export const ViewBarFilterEffect = ({
filterDropdownId,
onFilterSelect,
}: ViewBarFilterEffectProps) => {
const { availableFilterDefinitionsState } = useViewScopedStates();
const availableFilterDefinitions = useRecoilValue(
availableFilterDefinitionsState,
);
const { setAvailableFilterDefinitions, setOnFilterSelect } =
useFilterDropdown({ filterDropdownId: filterDropdownId });
useEffect(() => {
if (availableFilterDefinitions) {
setAvailableFilterDefinitions(availableFilterDefinitions);
}
if (onFilterSelect) {
setOnFilterSelect(() => onFilterSelect);
}
}, [
availableFilterDefinitions,
onFilterSelect,
setAvailableFilterDefinitions,
setOnFilterSelect,
]);
return <></>;
};

View File

@ -0,0 +1,42 @@
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { useSortDropdown } from '@/ui/object/object-sort-dropdown/hooks/useSortDropdown';
import { Sort } from '@/ui/object/object-sort-dropdown/types/Sort';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
type ViewBarSortEffectProps = {
sortDropdownId: string;
onSortSelect?: ((sort: Sort) => void) | undefined;
};
export const ViewBarSortEffect = ({
sortDropdownId,
onSortSelect,
}: ViewBarSortEffectProps) => {
const { availableSortDefinitionsState } = useViewScopedStates();
const availableSortDefinitions = useRecoilValue(
availableSortDefinitionsState,
);
const { setAvailableSortDefinitions, setOnSortSelect } = useSortDropdown({
sortDropdownId,
});
useEffect(() => {
if (availableSortDefinitions) {
setAvailableSortDefinitions(availableSortDefinitions);
}
if (onSortSelect) {
setOnSortSelect(() => onSortSelect);
}
}, [
availableSortDefinitions,
onSortSelect,
setAvailableSortDefinitions,
setOnSortSelect,
]);
return <></>;
};

View File

@ -19,11 +19,11 @@ import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/navigation/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 { useViewBar } from '@/views/hooks/useViewBar';
import { assertNotNull } from '~/utils/assert'; import { assertNotNull } from '~/utils/assert';
import { ViewsDropdownId } from '../constants/ViewsDropdownId'; import { ViewsDropdownId } from '../constants/ViewsDropdownId';
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates'; import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
import { useView } from '../hooks/useView';
const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)` const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
font-weight: ${({ theme }) => theme.font.weight.regular}; font-weight: ${({ theme }) => theme.font.weight.regular};
@ -68,7 +68,7 @@ export const ViewsDropdownButton = ({
optionsDropdownScopeId, optionsDropdownScopeId,
}: ViewsDropdownButtonProps) => { }: ViewsDropdownButtonProps) => {
const theme = useTheme(); const theme = useTheme();
const { removeView, changeViewInUrl } = useView(); const { removeView, changeViewInUrl } = useViewBar();
const { viewsState, currentViewSelector, entityCountInCurrentViewState } = const { viewsState, currentViewSelector, entityCountInCurrentViewState } =
useViewScopedStates(); useViewScopedStates();
@ -79,7 +79,7 @@ export const ViewsDropdownButton = ({
entityCountInCurrentViewState, entityCountInCurrentViewState,
); );
const { setViewEditMode, setCurrentViewId, loadView } = useView(); const { setViewEditMode, setCurrentViewId, loadView } = useViewBar();
const { const {
isDropdownOpen: isViewsDropdownOpen, isDropdownOpen: isViewsDropdownOpen,

View File

@ -23,7 +23,7 @@ export const useViewFilters = (viewScopeId: string) => {
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();
const { currentViewFiltersState } = useViewScopedStates({ const { currentViewFiltersState } = useViewScopedStates({
customViewScopeId: viewScopeId, viewScopeId: viewScopeId,
}); });
const persistViewFilters = useRecoilCallback( const persistViewFilters = useRecoilCallback(

View File

@ -8,12 +8,12 @@ import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/Vi
import { currentViewIdScopedState } from '../../states/currentViewIdScopedState'; import { currentViewIdScopedState } from '../../states/currentViewIdScopedState';
import { getViewScopedStates } from '../../utils/internal/getViewScopedStates'; import { getViewScopedStates } from '../../utils/internal/getViewScopedStates';
export const useViewScopedStates = (args?: { customViewScopeId?: string }) => { export const useViewScopedStates = (args?: { viewScopeId?: string }) => {
const { customViewScopeId } = args ?? {}; const { viewScopeId } = args ?? {};
const scopeId = useAvailableScopeIdOrThrow( const scopeId = useAvailableScopeIdOrThrow(
ViewScopeInternalContext, ViewScopeInternalContext,
customViewScopeId, viewScopeId,
); );
// View // View

View File

@ -22,7 +22,7 @@ export const useViewSorts = (viewScopeId: string) => {
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();
const { currentViewSortsState } = useViewScopedStates({ const { currentViewSortsState } = useViewScopedStates({
customViewScopeId: viewScopeId, viewScopeId: viewScopeId,
}); });
const persistViewSorts = useRecoilCallback( const persistViewSorts = useRecoilCallback(

View File

@ -25,13 +25,13 @@ import { useViewScopedStates } from './internal/useViewScopedStates';
import { useViewSorts } from './internal/useViewSorts'; import { useViewSorts } from './internal/useViewSorts';
type UseViewProps = { type UseViewProps = {
viewScopeId?: string; viewBarId?: string;
}; };
export const useView = (props?: UseViewProps) => { export const useViewBar = (props?: UseViewProps) => {
const scopeId = useAvailableScopeIdOrThrow( const scopeId = useAvailableScopeIdOrThrow(
ViewScopeInternalContext, ViewScopeInternalContext,
props?.viewScopeId, props?.viewBarId,
); );
const { const {
@ -46,7 +46,7 @@ export const useView = (props?: UseViewProps) => {
viewObjectMetadataIdState, viewObjectMetadataIdState,
viewTypeState, viewTypeState,
} = useViewScopedStates({ } = useViewScopedStates({
customViewScopeId: scopeId, viewScopeId: scopeId,
}); });
const { persistViewSorts, upsertViewSort, removeViewSort } = const { persistViewSorts, upsertViewSort, removeViewSort } =

View File

@ -11,7 +11,6 @@ import { PageHeader } from '@/ui/layout/page/PageHeader';
import { TabList } from '@/ui/layout/tab/components/TabList'; import { TabList } from '@/ui/layout/tab/components/TabList';
import { TopBar } from '@/ui/layout/top-bar/TopBar'; import { TopBar } from '@/ui/layout/top-bar/TopBar';
import { ObjectFilterDropdownButton } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownButton'; import { ObjectFilterDropdownButton } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownButton';
import { ObjectFilterDropdownScope } from '@/ui/object/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { TasksEffect } from './TasksEffect'; import { TasksEffect } from './TasksEffect';
@ -45,38 +44,36 @@ export const Tasks = () => {
}, },
]; ];
const filterDropdownId = 'tasks-assignee-filter';
return ( return (
<PageContainer> <PageContainer>
<RecoilScope CustomRecoilScopeContext={TasksRecoilScopeContext}> <RecoilScope CustomRecoilScopeContext={TasksRecoilScopeContext}>
<ObjectFilterDropdownScope filterScopeId="tasks-filter-scope"> <TasksEffect filterDropdownId={filterDropdownId} />
<TasksEffect /> <PageHeader title="Tasks" Icon={IconCheckbox}>
<PageHeader title="Tasks" Icon={IconCheckbox}> <PageAddTaskButton filterDropdownId={filterDropdownId} />
<PageAddTaskButton /> </PageHeader>
</PageHeader> <PageBody>
<PageBody> <StyledTasksContainer>
<StyledTasksContainer> <TopBar
<TopBar leftComponent={
leftComponent={ <StyledTabListContainer>
<StyledTabListContainer> <TabList context={TasksRecoilScopeContext} tabs={TASK_TABS} />
<TabList </StyledTabListContainer>
context={TasksRecoilScopeContext} }
tabs={TASK_TABS} rightComponent={
/> <ObjectFilterDropdownButton
</StyledTabListContainer> filterDropdownId={filterDropdownId}
} key="tasks-filter-dropdown-button"
rightComponent={ hotkeyScope={{
<ObjectFilterDropdownButton scope: RelationPickerHotkeyScope.RelationPicker,
key="tasks-filter-dropdown-button" }}
hotkeyScope={{ />
scope: RelationPickerHotkeyScope.RelationPicker, }
}} />
/> <TaskGroups filterDropdownId={filterDropdownId} />
} </StyledTasksContainer>
/> </PageBody>
<TaskGroups />
</StyledTasksContainer>
</PageBody>
</ObjectFilterDropdownScope>
</RecoilScope> </RecoilScope>
</PageContainer> </PageContainer>
); );

View File

@ -2,14 +2,21 @@ import { useEffect } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useFilter } from '@/ui/object/object-filter-dropdown/hooks/useFilter'; import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { tasksFilterDefinitions } from './tasks-filter-definitions'; import { tasksFilterDefinitions } from './tasks-filter-definitions';
export const TasksEffect = () => { type TasksEffectProps = {
filterDropdownId: string;
};
export const TasksEffect = ({ filterDropdownId }: TasksEffectProps) => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { setSelectedFilter, setAvailableFilterDefinitions } = useFilter(); const { setSelectedFilter, setAvailableFilterDefinitions } =
useFilterDropdown({
filterDropdownId: filterDropdownId,
});
useEffect(() => { useEffect(() => {
setAvailableFilterDefinitions(tasksFilterDefinitions); setAvailableFilterDefinitions(tasksFilterDefinitions);