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:
@ -2,10 +2,18 @@ import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||
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 = () => {
|
||||
const { selectedFilter } = useFilter();
|
||||
type PageAddTaskButtonProps = {
|
||||
filterDropdownId: string;
|
||||
};
|
||||
|
||||
export const PageAddTaskButton = ({
|
||||
filterDropdownId,
|
||||
}: PageAddTaskButtonProps) => {
|
||||
const { selectedFilter } = useFilterDropdown({
|
||||
filterDropdownId: filterDropdownId,
|
||||
});
|
||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||
|
||||
const handleClick = () => {
|
||||
|
||||
@ -13,6 +13,7 @@ import { AddTaskButton } from './AddTaskButton';
|
||||
import { TaskList } from './TaskList';
|
||||
|
||||
type TaskGroupsProps = {
|
||||
filterDropdownId?: string;
|
||||
entity?: ActivityTargetableEntity;
|
||||
showAddButton?: boolean;
|
||||
};
|
||||
@ -51,13 +52,17 @@ const StyledContainer = styled.div`
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
export const TaskGroups = ({ entity, showAddButton }: TaskGroupsProps) => {
|
||||
export const TaskGroups = ({
|
||||
filterDropdownId,
|
||||
entity,
|
||||
showAddButton,
|
||||
}: TaskGroupsProps) => {
|
||||
const {
|
||||
todayOrPreviousTasks,
|
||||
upcomingTasks,
|
||||
unscheduledTasks,
|
||||
completedTasks,
|
||||
} = useTasks(entity);
|
||||
} = useTasks({ filterDropdownId: filterDropdownId, entity });
|
||||
|
||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||
|
||||
|
||||
@ -5,12 +5,21 @@ import { undefined } from 'zod';
|
||||
import { Activity } from '@/activities/types/Activity';
|
||||
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
|
||||
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 { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useTasks = (entity?: ActivityTargetableEntity) => {
|
||||
const { selectedFilter } = useFilter();
|
||||
type UseTasksProps = {
|
||||
filterDropdownId?: string;
|
||||
entity?: ActivityTargetableEntity;
|
||||
};
|
||||
|
||||
export const useTasks = (props?: UseTasksProps) => {
|
||||
const { filterDropdownId, entity } = props ?? {};
|
||||
|
||||
const { selectedFilter } = useFilterDropdown({
|
||||
filterDropdownId: filterDropdownId,
|
||||
});
|
||||
|
||||
const { objects: activityTargets } = useFindManyObjectRecords({
|
||||
objectNamePlural: 'activityTargets',
|
||||
|
||||
@ -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 { ViewBar } from '@/views/components/ViewBar';
|
||||
import { useViewFields } from '@/views/hooks/internal/useViewFields';
|
||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
||||
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
|
||||
|
||||
import { HooksCompanyBoardEffect } from '../../components/HooksCompanyBoardEffect';
|
||||
@ -36,41 +35,35 @@ export const CompanyBoard = ({
|
||||
onColumnDelete,
|
||||
onEditColumnTitle,
|
||||
}: CompanyBoardProps) => {
|
||||
const viewScopeId = 'company-board-view';
|
||||
const viewBarId = 'company-board-view';
|
||||
|
||||
const { persistViewFields } = useViewFields(viewScopeId);
|
||||
const { persistViewFields } = useViewFields(viewBarId);
|
||||
|
||||
return (
|
||||
<ViewScope
|
||||
viewScopeId={viewScopeId}
|
||||
onViewFieldsChange={() => {}}
|
||||
onViewFiltersChange={() => {}}
|
||||
onViewSortsChange={() => {}}
|
||||
>
|
||||
<StyledContainer>
|
||||
<BoardContext.Provider
|
||||
value={{
|
||||
BoardRecoilScopeContext: CompanyBoardRecoilScopeContext,
|
||||
onFieldsChange: (fields) => {
|
||||
persistViewFields(mapBoardFieldDefinitionsToViewFields(fields));
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ViewBar
|
||||
optionsDropdownButton={<BoardOptionsDropdown />}
|
||||
optionsDropdownScopeId={BoardOptionsDropdownId}
|
||||
/>
|
||||
<HooksCompanyBoardEffect />
|
||||
<RecordBoard
|
||||
boardOptions={opportunitiesBoardOptions}
|
||||
onColumnAdd={onColumnAdd}
|
||||
onColumnDelete={onColumnDelete}
|
||||
onEditColumnTitle={onEditColumnTitle}
|
||||
/>
|
||||
<RecordBoardActionBar />
|
||||
<RecordBoardContextMenu />
|
||||
</BoardContext.Provider>
|
||||
</StyledContainer>
|
||||
</ViewScope>
|
||||
<StyledContainer>
|
||||
<BoardContext.Provider
|
||||
value={{
|
||||
BoardRecoilScopeContext: CompanyBoardRecoilScopeContext,
|
||||
onFieldsChange: (fields) => {
|
||||
persistViewFields(mapBoardFieldDefinitionsToViewFields(fields));
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ViewBar
|
||||
viewBarId={viewBarId}
|
||||
optionsDropdownButton={<BoardOptionsDropdown />}
|
||||
optionsDropdownScopeId={BoardOptionsDropdownId}
|
||||
/>
|
||||
<HooksCompanyBoardEffect viewBarId={viewBarId} />
|
||||
<RecordBoard
|
||||
boardOptions={opportunitiesBoardOptions}
|
||||
onColumnAdd={onColumnAdd}
|
||||
onColumnDelete={onColumnDelete}
|
||||
onEditColumnTitle={onEditColumnTitle}
|
||||
/>
|
||||
<RecordBoardActionBar />
|
||||
<RecordBoardContextMenu />
|
||||
</BoardContext.Provider>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -20,7 +20,7 @@ import { isBoardLoadedState } from '@/ui/object/record-board/states/isBoardLoade
|
||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||
import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useSetRecoilScopedStateV2';
|
||||
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 { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions';
|
||||
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||
@ -30,7 +30,13 @@ import { isDefined } from '~/utils/isDefined';
|
||||
import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds';
|
||||
import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns';
|
||||
|
||||
export const HooksCompanyBoardEffect = () => {
|
||||
type HooksCompanyBoardEffectProps = {
|
||||
viewBarId: string;
|
||||
};
|
||||
|
||||
export const HooksCompanyBoardEffect = ({
|
||||
viewBarId,
|
||||
}: HooksCompanyBoardEffectProps) => {
|
||||
const {
|
||||
setAvailableFilterDefinitions,
|
||||
setAvailableSortDefinitions,
|
||||
@ -38,13 +44,13 @@ export const HooksCompanyBoardEffect = () => {
|
||||
setEntityCountInCurrentView,
|
||||
setViewObjectMetadataId,
|
||||
setViewType,
|
||||
} = useView();
|
||||
} = useViewBar({ viewBarId: viewBarId });
|
||||
|
||||
const {
|
||||
currentViewFieldsState,
|
||||
currentViewFiltersState,
|
||||
currentViewSortsState,
|
||||
} = useViewScopedStates();
|
||||
} = useViewScopedStates({ viewScopeId: viewBarId });
|
||||
|
||||
const [pipelineSteps, setPipelineSteps] = useState<PipelineStep[]>([]);
|
||||
const [opportunities, setOpportunities] = useState<Opportunity[]>([]);
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata';
|
||||
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 { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||
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 { 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 { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
||||
@ -45,13 +40,11 @@ export const RecordTableContainer = ({
|
||||
objectNameSingular: foundObjectMetadataItem?.nameSingular,
|
||||
});
|
||||
|
||||
const tableScopeId = objectNamePlural ?? '';
|
||||
const viewScopeId = objectNamePlural ?? '';
|
||||
|
||||
const { persistViewFields } = useViewFields(viewScopeId);
|
||||
const recordTableId = objectNamePlural ?? '';
|
||||
const viewBarId = objectNamePlural ?? '';
|
||||
|
||||
const { setTableFilters, setTableSorts, setTableColumns } = useRecordTable({
|
||||
recordTableScopeId: tableScopeId,
|
||||
recordTableScopeId: recordTableId,
|
||||
});
|
||||
|
||||
const updateEntity = ({
|
||||
@ -71,35 +64,31 @@ export const RecordTableContainer = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<ViewScope
|
||||
viewScopeId={viewScopeId}
|
||||
onViewFieldsChange={(viewFields) => {
|
||||
setTableColumns(
|
||||
mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions),
|
||||
);
|
||||
}}
|
||||
onViewFiltersChange={(viewFilters) => {
|
||||
setTableFilters(mapViewFiltersToFilters(viewFilters));
|
||||
}}
|
||||
onViewSortsChange={(viewSorts) => {
|
||||
setTableSorts(mapViewSortsToSorts(viewSorts));
|
||||
}}
|
||||
>
|
||||
<StyledContainer>
|
||||
<RecordTableScope
|
||||
recordTableScopeId={tableScopeId}
|
||||
onColumnsChange={useRecoilCallback(() => (columns) => {
|
||||
persistViewFields(mapColumnDefinitionsToViewFields(columns));
|
||||
})}
|
||||
>
|
||||
<ViewBar
|
||||
optionsDropdownButton={<TableOptionsDropdown />}
|
||||
optionsDropdownScopeId={TableOptionsDropdownId}
|
||||
/>
|
||||
<RecordTableEffect />
|
||||
<RecordTable updateEntityMutation={updateEntity} />
|
||||
</RecordTableScope>
|
||||
</StyledContainer>
|
||||
</ViewScope>
|
||||
<StyledContainer>
|
||||
<ViewBar
|
||||
viewBarId={viewBarId}
|
||||
optionsDropdownButton={
|
||||
<TableOptionsDropdown recordTableId={recordTableId} />
|
||||
}
|
||||
optionsDropdownScopeId={TableOptionsDropdownId}
|
||||
onViewFieldsChange={(viewFields) => {
|
||||
setTableColumns(
|
||||
mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions),
|
||||
);
|
||||
}}
|
||||
onViewFiltersChange={(viewFilters) => {
|
||||
setTableFilters(mapViewFiltersToFilters(viewFilters));
|
||||
}}
|
||||
onViewSortsChange={(viewSorts) => {
|
||||
setTableSorts(mapViewSortsToSorts(viewSorts));
|
||||
}}
|
||||
/>
|
||||
<RecordTableEffect recordTableId={recordTableId} viewBarId={viewBarId} />
|
||||
<RecordTable
|
||||
recordTableId={recordTableId}
|
||||
viewBarId={viewBarId}
|
||||
updateEntityMutation={updateEntity}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -5,16 +5,22 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries';
|
||||
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
|
||||
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';
|
||||
|
||||
export const RecordTableEffect = () => {
|
||||
export const RecordTableEffect = ({
|
||||
recordTableId,
|
||||
viewBarId,
|
||||
}: {
|
||||
recordTableId: string;
|
||||
viewBarId: string;
|
||||
}) => {
|
||||
const {
|
||||
scopeId: objectNamePlural,
|
||||
setAvailableTableColumns,
|
||||
setOnEntityCountChange,
|
||||
setObjectMetadataConfig,
|
||||
} = useRecordTable();
|
||||
} = useRecordTable({ recordTableScopeId: recordTableId });
|
||||
|
||||
const {
|
||||
objectMetadataItem,
|
||||
@ -34,7 +40,7 @@ export const RecordTableEffect = () => {
|
||||
setViewType,
|
||||
setViewObjectMetadataId,
|
||||
setEntityCountInCurrentView,
|
||||
} = useView();
|
||||
} = useViewBar({ viewBarId });
|
||||
|
||||
useEffect(() => {
|
||||
if (basePathToShowPage && labelIdentifierFieldMetadataId) {
|
||||
@ -80,7 +86,9 @@ export const RecordTableEffect = () => {
|
||||
]);
|
||||
|
||||
const { setActionBarEntries, setContextMenuEntries } =
|
||||
useRecordTableContextMenuEntries();
|
||||
useRecordTableContextMenuEntries({
|
||||
recordTableScopeId: recordTableId,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setActionBarEntries?.();
|
||||
|
||||
@ -9,19 +9,33 @@ import { IconHeart, IconHeartOff, IconTrash } from '@/ui/display/icon';
|
||||
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
|
||||
import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState';
|
||||
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 { 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
|
||||
export const useRecordTableContextMenuEntries = () => {
|
||||
export const useRecordTableContextMenuEntries = (
|
||||
props?: useRecordTableContextMenuEntriesProps,
|
||||
) => {
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
RecordTableScopeInternalContext,
|
||||
props?.recordTableScopeId,
|
||||
);
|
||||
|
||||
const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
|
||||
const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState);
|
||||
|
||||
const setTableRowIds = useSetRecoilState(tableRowIdsState);
|
||||
const selectedRowIds = useRecoilValue(selectedRowIdsSelector);
|
||||
|
||||
const { scopeId: objectNamePlural, resetTableRowSelection } =
|
||||
useRecordTable();
|
||||
const { scopeId: objectNamePlural, resetTableRowSelection } = useRecordTable({
|
||||
recordTableScopeId: scopeId,
|
||||
});
|
||||
|
||||
const { objectMetadataItem: foundObjectMetadataItem } = useObjectMetadataItem(
|
||||
{
|
||||
|
||||
@ -5,11 +5,11 @@ import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
|
||||
import { isFetchingRecordTableDataState } from '@/ui/object/record-table/states/isFetchingRecordTableDataState';
|
||||
import { numberOfTableRowsState } from '@/ui/object/record-table/states/numberOfTableRowsState';
|
||||
import { tableRowIdsState } from '@/ui/object/record-table/states/tableRowIdsState';
|
||||
import { useView } from '@/views/hooks/useView';
|
||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||
|
||||
export const useSetRecordTableData = () => {
|
||||
const { resetTableRowSelection } = useRecordTable();
|
||||
const { setEntityCountInCurrentView } = useView();
|
||||
const { setEntityCountInCurrentView } = useViewBar();
|
||||
|
||||
return useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
|
||||
@ -4,9 +4,7 @@ import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/c
|
||||
import { RecordTable } from '@/ui/object/record-table/components/RecordTable';
|
||||
import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId';
|
||||
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 { ViewScope } from '@/views/scopes/ViewScope';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
@ -16,29 +14,27 @@ const StyledContainer = styled.div`
|
||||
`;
|
||||
|
||||
export const SignInBackgroundMockContainer = () => {
|
||||
const tableScopeId = 'sign-in-background-mock-table';
|
||||
const viewScopeId = 'sign-in-background-mock-view';
|
||||
const recordTableId = 'sign-in-background-mock-table';
|
||||
const viewBarId = 'sign-in-background-mock-view';
|
||||
|
||||
return (
|
||||
<ViewScope
|
||||
viewScopeId={viewScopeId}
|
||||
onViewFieldsChange={() => {}}
|
||||
onViewFiltersChange={() => {}}
|
||||
onViewSortsChange={() => {}}
|
||||
>
|
||||
<StyledContainer>
|
||||
<RecordTableScope
|
||||
recordTableScopeId={tableScopeId}
|
||||
onColumnsChange={() => {}}
|
||||
>
|
||||
<ViewBar
|
||||
optionsDropdownButton={<TableOptionsDropdown />}
|
||||
optionsDropdownScopeId={TableOptionsDropdownId}
|
||||
/>
|
||||
<SignInBackgroundMockContainerEffect />
|
||||
<RecordTable updateEntityMutation={() => {}} />
|
||||
</RecordTableScope>
|
||||
</StyledContainer>
|
||||
</ViewScope>
|
||||
<StyledContainer>
|
||||
<ViewBar
|
||||
viewBarId={viewBarId}
|
||||
optionsDropdownButton={
|
||||
<TableOptionsDropdown recordTableId={recordTableId} />
|
||||
}
|
||||
optionsDropdownScopeId={TableOptionsDropdownId}
|
||||
/>
|
||||
<SignInBackgroundMockContainerEffect
|
||||
recordTableId={recordTableId}
|
||||
viewId={viewBarId}
|
||||
/>
|
||||
<RecordTable
|
||||
recordTableId={recordTableId}
|
||||
viewBarId={viewBarId}
|
||||
updateEntityMutation={() => {}}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@ -11,11 +11,19 @@ import {
|
||||
} from '@/sign-in-background-mock/constants/signInBackgroundMockDefinitions';
|
||||
import { signInBackgroundMockViewFields } from '@/sign-in-background-mock/constants/signInBackgroundMockViewFields';
|
||||
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 { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
|
||||
|
||||
export const SignInBackgroundMockContainerEffect = () => {
|
||||
type SignInBackgroundMockContainerEffectProps = {
|
||||
recordTableId: string;
|
||||
viewId: string;
|
||||
};
|
||||
|
||||
export const SignInBackgroundMockContainerEffect = ({
|
||||
recordTableId,
|
||||
viewId,
|
||||
}: SignInBackgroundMockContainerEffectProps) => {
|
||||
const {
|
||||
scopeId: objectNamePlural,
|
||||
setAvailableTableColumns,
|
||||
@ -23,7 +31,9 @@ export const SignInBackgroundMockContainerEffect = () => {
|
||||
setRecordTableData,
|
||||
setTableColumns,
|
||||
setObjectMetadataConfig,
|
||||
} = useRecordTable();
|
||||
} = useRecordTable({
|
||||
recordTableScopeId: recordTableId,
|
||||
});
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNamePlural,
|
||||
@ -36,7 +46,7 @@ export const SignInBackgroundMockContainerEffect = () => {
|
||||
setViewType,
|
||||
setViewObjectMetadataId,
|
||||
setEntityCountInCurrentView,
|
||||
} = useView();
|
||||
} = useViewBar({ viewBarId: viewId });
|
||||
|
||||
useEffect(() => {
|
||||
setViewObjectMetadataId?.('company-mock-object-metadata-id');
|
||||
@ -76,7 +86,9 @@ export const SignInBackgroundMockContainerEffect = () => {
|
||||
}, [setObjectMetadataConfig]);
|
||||
|
||||
const { setActionBarEntries, setContextMenuEntries } =
|
||||
useRecordTableContextMenuEntries();
|
||||
useRecordTableContextMenuEntries({
|
||||
recordTableScopeId: recordTableId,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setActionBarEntries?.();
|
||||
|
||||
@ -1,16 +1,24 @@
|
||||
import { IconPlus } from '@/ui/display/icon';
|
||||
import { LightButton } from '@/ui/input/button/components/LightButton';
|
||||
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';
|
||||
|
||||
export const AddObjectFilterFromDetailsButton = () => {
|
||||
type AddObjectFilterFromDetailsButtonProps = {
|
||||
filterDropdownId?: string;
|
||||
};
|
||||
|
||||
export const AddObjectFilterFromDetailsButton = ({
|
||||
filterDropdownId,
|
||||
}: AddObjectFilterFromDetailsButtonProps) => {
|
||||
const { toggleDropdown } = useDropdown({
|
||||
dropdownScopeId: ObjectFilterDropdownId,
|
||||
});
|
||||
|
||||
const { resetFilter } = useFilter();
|
||||
const { resetFilter } = useFilterDropdown({
|
||||
filterDropdownId: filterDropdownId,
|
||||
});
|
||||
|
||||
const handleClick = () => {
|
||||
resetFilter();
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
|
||||
import { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId';
|
||||
import { useFilter } from '../hooks/useFilter';
|
||||
|
||||
export const MultipleFiltersButton = () => {
|
||||
const { resetFilter } = useFilter();
|
||||
const { resetFilter } = useFilterDropdown();
|
||||
|
||||
const { isDropdownOpen, toggleDropdown } = useDropdown({
|
||||
dropdownScopeId: ObjectFilterDropdownId,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
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 { ObjectFilterDropdownId } from '../constants/ObjectFilterDropdownId';
|
||||
@ -15,7 +15,7 @@ type MultipleFiltersDropdownButtonProps = {
|
||||
export const MultipleFiltersDropdownButton = ({
|
||||
hotkeyScope,
|
||||
}: MultipleFiltersDropdownButtonProps) => {
|
||||
const { resetFilter } = useFilter();
|
||||
const { resetFilter } = useFilterDropdown();
|
||||
|
||||
return (
|
||||
<DropdownScope dropdownScopeId={ObjectFilterDropdownId}>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
|
||||
import { useFilter } from '../hooks/useFilter';
|
||||
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
|
||||
import { MultipleFiltersDropdownFilterOnFilterChangedEffect } from './MultipleFiltersDropdownFilterOnFilterChangedEffect';
|
||||
import { ObjectFilterDropdownDateSearchInput } from './ObjectFilterDropdownDateSearchInput';
|
||||
@ -17,7 +16,7 @@ export const MultipleFiltersDropdownContent = () => {
|
||||
isObjectFilterDropdownOperandSelectUnfolded,
|
||||
filterDefinitionUsedInDropdown,
|
||||
selectedOperandInDropdown,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -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 { useFilter } from '../hooks/useFilter';
|
||||
|
||||
import { MultipleFiltersDropdownButton } from './MultipleFiltersDropdownButton';
|
||||
import { SingleEntityObjectFilterDropdownButton } from './SingleEntityObjectFilterDropdownButton';
|
||||
|
||||
type ObjectFilterDropdownButtonProps = {
|
||||
filterDropdownId: string;
|
||||
hotkeyScope: HotkeyScope;
|
||||
};
|
||||
|
||||
export const ObjectFilterDropdownButton = ({
|
||||
filterDropdownId,
|
||||
hotkeyScope,
|
||||
}: ObjectFilterDropdownButtonProps) => {
|
||||
const { availableFilterDefinitions } = useFilter();
|
||||
|
||||
const { availableFilterDefinitions } = useFilterDropdown({
|
||||
filterDropdownId: filterDropdownId,
|
||||
});
|
||||
const hasOnlyOneEntityFilter =
|
||||
availableFilterDefinitions.length === 1 &&
|
||||
availableFilterDefinitions[0].type === 'RELATION';
|
||||
@ -22,9 +25,13 @@ export const ObjectFilterDropdownButton = ({
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return hasOnlyOneEntityFilter ? (
|
||||
<SingleEntityObjectFilterDropdownButton hotkeyScope={hotkeyScope} />
|
||||
) : (
|
||||
<MultipleFiltersDropdownButton hotkeyScope={hotkeyScope} />
|
||||
return (
|
||||
<ObjectFilterDropdownScope filterScopeId={filterDropdownId}>
|
||||
{hasOnlyOneEntityFilter ? (
|
||||
<SingleEntityObjectFilterDropdownButton hotkeyScope={hotkeyScope} />
|
||||
) : (
|
||||
<MultipleFiltersDropdownButton hotkeyScope={hotkeyScope} />
|
||||
)}
|
||||
</ObjectFilterDropdownScope>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker';
|
||||
|
||||
import { useFilter } from '../hooks/useFilter';
|
||||
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
|
||||
export const ObjectFilterDropdownDateSearchInput = () => {
|
||||
const {
|
||||
@ -8,7 +7,7 @@ export const ObjectFilterDropdownDateSearchInput = () => {
|
||||
selectedOperandInDropdown,
|
||||
setIsObjectFilterDropdownUnfolded,
|
||||
selectFilter,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
const handleChange = (date: Date) => {
|
||||
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
|
||||
import { useFilter } from '../hooks/useFilter';
|
||||
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
|
||||
export const ObjectFilterDropdownEntitySearchInput = () => {
|
||||
const {
|
||||
@ -10,7 +9,7 @@ export const ObjectFilterDropdownEntitySearchInput = () => {
|
||||
selectedOperandInDropdown,
|
||||
objectFilterDropdownSearchInput,
|
||||
setObjectFilterDropdownSearchInput,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
return (
|
||||
filterDefinitionUsedInDropdown &&
|
||||
|
||||
@ -4,10 +4,9 @@ import { EntitiesForMultipleEntitySelect } from '@/ui/input/relation-picker/comp
|
||||
import { SingleEntitySelectBase } from '@/ui/input/relation-picker/components/SingleEntitySelectBase';
|
||||
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
|
||||
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 { useFilter } from '../hooks/useFilter';
|
||||
|
||||
export const ObjectFilterDropdownEntitySearchSelect = ({
|
||||
entitiesForSelect,
|
||||
}: {
|
||||
@ -20,7 +19,7 @@ export const ObjectFilterDropdownEntitySearchSelect = ({
|
||||
objectFilterDropdownSearchInput,
|
||||
selectedFilter,
|
||||
selectFilter,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
const { closeDropdown } = useDropdown();
|
||||
|
||||
|
||||
@ -4,15 +4,14 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { useFilteredSearchEntityQuery } from '@/search/hooks/useFilteredSearchEntityQuery';
|
||||
import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker';
|
||||
import { ObjectFilterDropdownEntitySearchSelect } from '@/ui/object/object-filter-dropdown/components/ObjectFilterDropdownEntitySearchSelect';
|
||||
|
||||
import { useFilter } from '../hooks/useFilter';
|
||||
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
|
||||
export const ObjectFilterDropdownEntitySelect = () => {
|
||||
const {
|
||||
filterDefinitionUsedInDropdown,
|
||||
objectFilterDropdownSearchInput,
|
||||
objectFilterDropdownSelectedEntityId,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
const objectMetadataNameSingular =
|
||||
filterDefinitionUsedInDropdown?.relationObjectMetadataNameSingular ?? '';
|
||||
|
||||
@ -2,9 +2,9 @@ import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons';
|
||||
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
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 { useFilter } from '../hooks/useFilter';
|
||||
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
||||
|
||||
export const ObjectFilterDropdownFilterSelect = () => {
|
||||
@ -13,7 +13,7 @@ export const ObjectFilterDropdownFilterSelect = () => {
|
||||
setSelectedOperandInDropdown,
|
||||
setObjectFilterDropdownSearchInput,
|
||||
availableFilterDefinitions,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
const { icons } = useLazyLoadIcons();
|
||||
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
|
||||
import { useFilter } from '../hooks/useFilter';
|
||||
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
|
||||
export const ObjectFilterDropdownNumberSearchInput = () => {
|
||||
const {
|
||||
selectedOperandInDropdown,
|
||||
filterDefinitionUsedInDropdown,
|
||||
selectFilter,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
return (
|
||||
filterDefinitionUsedInDropdown &&
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { IconChevronDown } from '@/ui/display/icon';
|
||||
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';
|
||||
|
||||
export const ObjectFilterDropdownOperandButton = () => {
|
||||
@ -9,7 +9,7 @@ export const ObjectFilterDropdownOperandButton = () => {
|
||||
selectedOperandInDropdown,
|
||||
setIsObjectFilterDropdownOperandSelectUnfolded,
|
||||
isObjectFilterDropdownOperandSelectUnfolded,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
if (isObjectFilterDropdownOperandSelectUnfolded) {
|
||||
return null;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
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 { useFilter } from '../hooks/useFilter';
|
||||
import { getOperandLabel } from '../utils/getOperandLabel';
|
||||
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
||||
|
||||
@ -14,7 +14,7 @@ export const ObjectFilterDropdownOperandSelect = () => {
|
||||
setIsObjectFilterDropdownOperandSelectUnfolded,
|
||||
selectedFilter,
|
||||
selectFilter,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
const operandsForFilterType = getOperandsForFilterType(
|
||||
filterDefinitionUsedInDropdown?.type,
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
|
||||
import { useFilter } from '../hooks/useFilter';
|
||||
import { useFilterDropdown } from '@/ui/object/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
|
||||
export const ObjectFilterDropdownTextSearchInput = () => {
|
||||
const {
|
||||
@ -12,7 +11,7 @@ export const ObjectFilterDropdownTextSearchInput = () => {
|
||||
setObjectFilterDropdownSearchInput,
|
||||
selectedFilter,
|
||||
selectFilter,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
return (
|
||||
filterDefinitionUsedInDropdown &&
|
||||
|
||||
@ -5,10 +5,10 @@ import { IconChevronDown } from '@/ui/display/icon/index';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
|
||||
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 { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
|
||||
import { useFilter } from '../hooks/useFilter';
|
||||
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
||||
|
||||
import { GenericEntityFilterChip } from './GenericEntityFilterChip';
|
||||
@ -25,7 +25,7 @@ export const SingleEntityObjectFilterDropdownButton = ({
|
||||
selectedFilter,
|
||||
setFilterDefinitionUsedInDropdown,
|
||||
setSelectedOperandInDropdown,
|
||||
} = useFilter();
|
||||
} = useFilterDropdown();
|
||||
|
||||
const availableFilter = availableFilterDefinitions[0];
|
||||
|
||||
|
||||
@ -1,22 +1,21 @@
|
||||
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 { useScopeInternalContextOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow';
|
||||
|
||||
import { ObjectFilterDropdownScopeInternalContext } from '../scopes/scope-internal-context/ObjectFilterDropdownScopeInternalContext';
|
||||
import { Filter } from '../types/Filter';
|
||||
|
||||
import { useFilterStates } from './useFilterStates';
|
||||
|
||||
type UseFilterProps = {
|
||||
filterScopeId?: string;
|
||||
type UseFilterDropdownProps = {
|
||||
filterDropdownId?: string;
|
||||
};
|
||||
|
||||
export const useFilter = (props?: UseFilterProps) => {
|
||||
export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
ObjectFilterDropdownScopeInternalContext,
|
||||
props?.filterScopeId,
|
||||
props?.filterDropdownId,
|
||||
);
|
||||
|
||||
const {
|
||||
availableFilterDefinitions,
|
||||
setAvailableFilterDefinitions,
|
||||
@ -34,11 +33,9 @@ export const useFilter = (props?: UseFilterProps) => {
|
||||
setSelectedFilter,
|
||||
selectedOperandInDropdown,
|
||||
setSelectedOperandInDropdown,
|
||||
} = useFilterStates(scopeId);
|
||||
|
||||
const { onFilterSelect } = useScopeInternalContextOrThrow(
|
||||
ObjectFilterDropdownScopeInternalContext,
|
||||
);
|
||||
onFilterSelect,
|
||||
setOnFilterSelect,
|
||||
} = useFilterDropdownStates(scopeId);
|
||||
|
||||
const selectFilter = useCallback(
|
||||
(filter: Filter) => {
|
||||
@ -82,5 +79,7 @@ export const useFilter = (props?: UseFilterProps) => {
|
||||
setSelectedOperandInDropdown,
|
||||
selectFilter,
|
||||
resetFilter,
|
||||
onFilterSelect,
|
||||
setOnFilterSelect,
|
||||
};
|
||||
};
|
||||
@ -1,3 +1,4 @@
|
||||
import { onFilterSelectScopedState } from '@/ui/object/object-filter-dropdown/states/onFilterSelectScopedState';
|
||||
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
|
||||
|
||||
import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState';
|
||||
@ -9,7 +10,7 @@ import { objectFilterDropdownSelectedEntityIdScopedState } from '../states/objec
|
||||
import { selectedFilterScopedState } from '../states/selectedFilterScopedState';
|
||||
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
|
||||
|
||||
export const useFilterStates = (scopeId: string) => {
|
||||
export const useFilterDropdownStates = (scopeId: string) => {
|
||||
const [availableFilterDefinitions, setAvailableFilterDefinitions] =
|
||||
useRecoilScopedStateV2(availableFilterDefinitionsScopedState, scopeId);
|
||||
|
||||
@ -46,6 +47,11 @@ export const useFilterStates = (scopeId: string) => {
|
||||
const [selectedOperandInDropdown, setSelectedOperandInDropdown] =
|
||||
useRecoilScopedStateV2(selectedOperandInDropdownScopedState, scopeId);
|
||||
|
||||
const [onFilterSelect, setOnFilterSelect] = useRecoilScopedStateV2(
|
||||
onFilterSelectScopedState,
|
||||
scopeId,
|
||||
);
|
||||
|
||||
return {
|
||||
availableFilterDefinitions,
|
||||
setAvailableFilterDefinitions,
|
||||
@ -63,5 +69,7 @@ export const useFilterStates = (scopeId: string) => {
|
||||
setSelectedFilter,
|
||||
selectedOperandInDropdown,
|
||||
setSelectedOperandInDropdown,
|
||||
onFilterSelect,
|
||||
setOnFilterSelect,
|
||||
};
|
||||
};
|
||||
@ -1,33 +1,20 @@
|
||||
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';
|
||||
|
||||
type ObjectFilterDropdownScopeProps = {
|
||||
children: ReactNode;
|
||||
filterScopeId: string;
|
||||
availableFilterDefinitions?: FilterDefinition[];
|
||||
onFilterSelect?: (filter: Filter) => void;
|
||||
};
|
||||
|
||||
export const ObjectFilterDropdownScope = ({
|
||||
children,
|
||||
filterScopeId,
|
||||
availableFilterDefinitions,
|
||||
onFilterSelect,
|
||||
}: ObjectFilterDropdownScopeProps) => {
|
||||
return (
|
||||
<ObjectFilterDropdownScopeInternalContext.Provider
|
||||
value={{ scopeId: filterScopeId, onFilterSelect }}
|
||||
value={{ scopeId: filterScopeId }}
|
||||
>
|
||||
<ObjectFilterDropdownScopeInitEffect
|
||||
filterScopeId={filterScopeId}
|
||||
availableFilterDefinitions={availableFilterDefinitions}
|
||||
/>
|
||||
{children}
|
||||
</ObjectFilterDropdownScopeInternalContext.Provider>
|
||||
);
|
||||
|
||||
@ -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 <></>;
|
||||
};
|
||||
@ -1,11 +1,7 @@
|
||||
import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey';
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
|
||||
import { Filter } from '../../types/Filter';
|
||||
|
||||
type ObjectFilterDropdownScopeInternalContextProps = ScopedStateKey & {
|
||||
onFilterSelect?: (sort: Filter) => void;
|
||||
};
|
||||
type ObjectFilterDropdownScopeInternalContextProps = ScopedStateKey;
|
||||
|
||||
export const ObjectFilterDropdownScopeInternalContext =
|
||||
createScopeInternalContext<ObjectFilterDropdownScopeInternalContextProps>();
|
||||
|
||||
@ -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,
|
||||
});
|
||||
@ -10,19 +10,21 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
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 { ObjectSortDropdownId } from '../constants/ObjectSortDropdownId';
|
||||
import { useObjectSortDropdown } from '../hooks/useObjectSortDropdown';
|
||||
import { SortDefinition } from '../types/SortDefinition';
|
||||
import { SORT_DIRECTIONS, SortDirection } from '../types/SortDirection';
|
||||
|
||||
export type ObjectSortDropdownButtonProps = {
|
||||
sortDropdownId: string;
|
||||
hotkeyScope: HotkeyScope;
|
||||
isPrimaryButton?: boolean;
|
||||
};
|
||||
|
||||
export const ObjectSortDropdownButton = ({
|
||||
sortDropdownId,
|
||||
hotkeyScope,
|
||||
}: ObjectSortDropdownButtonProps) => {
|
||||
const [isSortDirectionMenuUnfolded, setIsSortDirectionMenuUnfolded] =
|
||||
@ -36,8 +38,9 @@ export const ObjectSortDropdownButton = ({
|
||||
setSelectedSortDirection('asc');
|
||||
}, []);
|
||||
|
||||
const { availableSortDefinitions, onSortSelect, isSortSelected } =
|
||||
useObjectSortDropdown();
|
||||
const { isSortSelected } = useSortDropdown({
|
||||
sortDropdownId: sortDropdownId,
|
||||
});
|
||||
|
||||
const { toggleDropdown } = useDropdown({
|
||||
dropdownScopeId: ObjectSortDropdownId,
|
||||
@ -48,6 +51,10 @@ export const ObjectSortDropdownButton = ({
|
||||
resetState();
|
||||
};
|
||||
|
||||
const { availableSortDefinitions, onSortSelect } = useSortDropdown({
|
||||
sortDropdownId: sortDropdownId,
|
||||
});
|
||||
|
||||
const handleAddSort = (selectedSortDefinition: SortDefinition) => {
|
||||
toggleDropdown();
|
||||
onSortSelect?.({
|
||||
@ -64,60 +71,64 @@ export const ObjectSortDropdownButton = ({
|
||||
const { icons } = useLazyLoadIcons();
|
||||
|
||||
return (
|
||||
<DropdownScope dropdownScopeId={ObjectSortDropdownId}>
|
||||
<Dropdown
|
||||
dropdownHotkeyScope={hotkeyScope}
|
||||
dropdownOffset={{ y: 8 }}
|
||||
clickableComponent={
|
||||
<LightButton
|
||||
title="Sort"
|
||||
active={isSortSelected}
|
||||
onClick={handleButtonClick}
|
||||
/>
|
||||
}
|
||||
dropdownComponents={
|
||||
<>
|
||||
{isSortDirectionMenuUnfolded ? (
|
||||
<DropdownMenuItemsContainer>
|
||||
{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 />
|
||||
<ObjectSortDropdownScope sortScopeId={sortDropdownId}>
|
||||
<DropdownScope dropdownScopeId={ObjectSortDropdownId}>
|
||||
<Dropdown
|
||||
dropdownHotkeyScope={hotkeyScope}
|
||||
dropdownOffset={{ y: 8 }}
|
||||
clickableComponent={
|
||||
<LightButton
|
||||
title="Sort"
|
||||
active={isSortSelected}
|
||||
onClick={handleButtonClick}
|
||||
/>
|
||||
}
|
||||
dropdownComponents={
|
||||
<>
|
||||
{isSortDirectionMenuUnfolded ? (
|
||||
<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}
|
||||
/>
|
||||
))}
|
||||
{SORT_DIRECTIONS.map((sortOrder, index) => (
|
||||
<MenuItem
|
||||
key={index}
|
||||
onClick={() => {
|
||||
setSelectedSortDirection(sortOrder);
|
||||
setIsSortDirectionMenuUnfolded(false);
|
||||
}}
|
||||
text={sortOrder === 'asc' ? 'Ascending' : 'Descending'}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
onClose={handleDropdownButtonClose}
|
||||
/>
|
||||
</DropdownScope>
|
||||
) : (
|
||||
<>
|
||||
<DropdownMenuHeader
|
||||
EndIcon={IconChevronDown}
|
||||
onClick={() => setIsSortDirectionMenuUnfolded(true)}
|
||||
>
|
||||
{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>
|
||||
);
|
||||
};
|
||||
|
||||
@ -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 { useScopeInternalContextOrThrow } from '../../../utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContextOrThrow';
|
||||
import { ObjectSortDropdownScopeInternalContext } from '../scopes/scope-internal-context/ObjectSortDropdownScopeInternalContext';
|
||||
|
||||
import { useObjectSortDropdownStates } from './useObjectSortDropdownStates';
|
||||
|
||||
type UseSortProps = {
|
||||
sortScopeId?: string;
|
||||
sortDropdownId?: string;
|
||||
};
|
||||
|
||||
export const useObjectSortDropdown = (props?: UseSortProps) => {
|
||||
export const useSortDropdown = (props?: UseSortProps) => {
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
ObjectSortDropdownScopeInternalContext,
|
||||
props?.sortScopeId,
|
||||
props?.sortDropdownId,
|
||||
);
|
||||
const {
|
||||
availableSortDefinitions,
|
||||
setAvailableSortDefinitions,
|
||||
isSortSelected,
|
||||
setIsSortSelected,
|
||||
} = useObjectSortDropdownStates(scopeId);
|
||||
|
||||
const { onSortSelect } = useScopeInternalContextOrThrow(
|
||||
ObjectSortDropdownScopeInternalContext,
|
||||
);
|
||||
onSortSelect,
|
||||
setOnSortSelect,
|
||||
} = useSortDropdownStates(scopeId);
|
||||
|
||||
return {
|
||||
onSortSelect,
|
||||
scopeId,
|
||||
availableSortDefinitions,
|
||||
isSortSelected,
|
||||
setIsSortSelected,
|
||||
setAvailableSortDefinitions,
|
||||
onSortSelect,
|
||||
setOnSortSelect,
|
||||
};
|
||||
};
|
||||
@ -1,9 +1,10 @@
|
||||
import { onSortSelectScopedState } from '@/ui/object/object-sort-dropdown/states/onSortSelectScopedState';
|
||||
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
|
||||
|
||||
import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState';
|
||||
import { isSortSelectedScopedState } from '../states/isSortSelectedScopedState';
|
||||
|
||||
export const useObjectSortDropdownStates = (scopeId: string) => {
|
||||
export const useSortDropdownStates = (scopeId: string) => {
|
||||
const [availableSortDefinitions, setAvailableSortDefinitions] =
|
||||
useRecoilScopedStateV2(availableSortDefinitionsScopedState, scopeId);
|
||||
|
||||
@ -12,10 +13,17 @@ export const useObjectSortDropdownStates = (scopeId: string) => {
|
||||
scopeId,
|
||||
);
|
||||
|
||||
const [onSortSelect, setOnSortSelect] = useRecoilScopedStateV2(
|
||||
onSortSelectScopedState,
|
||||
scopeId,
|
||||
);
|
||||
|
||||
return {
|
||||
availableSortDefinitions,
|
||||
setAvailableSortDefinitions,
|
||||
isSortSelected,
|
||||
setIsSortSelected,
|
||||
onSortSelect,
|
||||
setOnSortSelect,
|
||||
};
|
||||
};
|
||||
@ -1,32 +1,20 @@
|
||||
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';
|
||||
|
||||
type ObjectSortDropdownScopeProps = {
|
||||
children: ReactNode;
|
||||
sortScopeId: string;
|
||||
availableSortDefinitions?: SortDefinition[];
|
||||
onSortSelect?: (sort: Sort) => void | Promise<void>;
|
||||
};
|
||||
|
||||
export const ObjectSortDropdownScope = ({
|
||||
children,
|
||||
sortScopeId,
|
||||
availableSortDefinitions,
|
||||
onSortSelect,
|
||||
}: ObjectSortDropdownScopeProps) => {
|
||||
return (
|
||||
<ObjectSortDropdownScopeInternalContext.Provider
|
||||
value={{ scopeId: sortScopeId, onSortSelect }}
|
||||
value={{ scopeId: sortScopeId }}
|
||||
>
|
||||
<ObjectSortDropdownScopeInitEffect
|
||||
sortScopeId={sortScopeId}
|
||||
availableSortDefinitions={availableSortDefinitions}
|
||||
/>
|
||||
{children}
|
||||
</ObjectSortDropdownScopeInternalContext.Provider>
|
||||
);
|
||||
|
||||
@ -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 <></>;
|
||||
};
|
||||
@ -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,
|
||||
});
|
||||
@ -14,6 +14,11 @@ export const turnSortsIntoOrderBy = (
|
||||
createdAt: 'DescNullsFirst',
|
||||
};
|
||||
}
|
||||
|
||||
if (!fields.length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
[fields[0].name]: 'DescNullsFirst',
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useView } from '@/views/hooks/useView';
|
||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||
|
||||
import { Dropdown } from '../../../../layout/dropdown/components/Dropdown';
|
||||
import { DropdownScope } from '../../../../layout/dropdown/scopes/DropdownScope';
|
||||
@ -19,7 +19,7 @@ type BoardOptionsDropdownProps = Pick<
|
||||
export const BoardOptionsDropdown = ({
|
||||
onStageAdd,
|
||||
}: BoardOptionsDropdownProps) => {
|
||||
const { setViewEditMode } = useView();
|
||||
const { setViewEditMode } = useViewBar();
|
||||
|
||||
return (
|
||||
<DropdownScope dropdownScopeId={BoardOptionsDropdownId}>
|
||||
|
||||
@ -26,7 +26,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
|
||||
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 { boardColumnsState } from '../../states/boardColumnsState';
|
||||
@ -52,7 +52,7 @@ type ColumnForCreate = {
|
||||
export const BoardOptionsDropdownContent = ({
|
||||
onStageAdd,
|
||||
}: BoardOptionsDropdownContentProps) => {
|
||||
const { setViewEditMode, handleViewNameSubmit } = useView();
|
||||
const { setViewEditMode, handleViewNameSubmit } = useViewBar();
|
||||
const { viewEditModeState, currentViewSelector } = useViewScopedStates();
|
||||
const { BoardRecoilScopeContext } = useContext(BoardContext);
|
||||
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import { useRef } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { RecordTableInternalEffect } from '@/ui/object/record-table/components/RecordTableInternalEffect';
|
||||
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 { 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';
|
||||
|
||||
@ -71,34 +75,50 @@ const StyledTableContainer = styled.div`
|
||||
`;
|
||||
|
||||
type RecordTableProps = {
|
||||
recordTableId: string;
|
||||
viewBarId: string;
|
||||
updateEntityMutation: (params: any) => void;
|
||||
};
|
||||
|
||||
export const RecordTable = ({ updateEntityMutation }: RecordTableProps) => {
|
||||
export const RecordTable = ({
|
||||
recordTableId,
|
||||
viewBarId,
|
||||
updateEntityMutation,
|
||||
}: RecordTableProps) => {
|
||||
const tableBodyRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const { resetTableRowSelection, setRowSelectedState } = useRecordTable();
|
||||
const { resetTableRowSelection, setRowSelectedState } = useRecordTable({
|
||||
recordTableScopeId: recordTableId,
|
||||
});
|
||||
const { persistViewFields } = useViewFields(viewBarId);
|
||||
|
||||
return (
|
||||
<ScrollWrapper>
|
||||
<EntityUpdateMutationContext.Provider value={updateEntityMutation}>
|
||||
<StyledTableWithHeader>
|
||||
<StyledTableContainer>
|
||||
<div ref={tableBodyRef}>
|
||||
<StyledTable className="entity-table-cell">
|
||||
<RecordTableHeader />
|
||||
<RecordTableBody />
|
||||
</StyledTable>
|
||||
<DragSelect
|
||||
dragSelectable={tableBodyRef}
|
||||
onDragSelectionStart={resetTableRowSelection}
|
||||
onDragSelectionChange={setRowSelectedState}
|
||||
/>
|
||||
</div>
|
||||
<RecordTableInternalEffect tableBodyRef={tableBodyRef} />
|
||||
</StyledTableContainer>
|
||||
</StyledTableWithHeader>
|
||||
</EntityUpdateMutationContext.Provider>
|
||||
</ScrollWrapper>
|
||||
<RecordTableScope
|
||||
recordTableScopeId={recordTableId}
|
||||
onColumnsChange={useRecoilCallback(() => (columns) => {
|
||||
persistViewFields(mapColumnDefinitionsToViewFields(columns));
|
||||
})}
|
||||
>
|
||||
<ScrollWrapper>
|
||||
<EntityUpdateMutationContext.Provider value={updateEntityMutation}>
|
||||
<StyledTableWithHeader>
|
||||
<StyledTableContainer>
|
||||
<div ref={tableBodyRef}>
|
||||
<StyledTable className="entity-table-cell">
|
||||
<RecordTableHeader />
|
||||
<RecordTableBody />
|
||||
</StyledTable>
|
||||
<DragSelect
|
||||
dragSelectable={tableBodyRef}
|
||||
onDragSelectionStart={resetTableRowSelection}
|
||||
onDragSelectionChange={setRowSelectedState}
|
||||
/>
|
||||
</div>
|
||||
<RecordTableInternalEffect tableBodyRef={tableBodyRef} />
|
||||
</StyledTableContainer>
|
||||
</StyledTableWithHeader>
|
||||
</EntityUpdateMutationContext.Provider>
|
||||
</ScrollWrapper>
|
||||
</RecordTableScope>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,32 +1,39 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||
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 { useView } from '@/views/hooks/useView';
|
||||
|
||||
import { savedTableColumnsFamilyState } from '../states/savedTableColumnsFamilyState';
|
||||
import { ColumnDefinition } from '../types/ColumnDefinition';
|
||||
|
||||
import { useRecordTableScopedStates } from './internal/useRecordTableScopedStates';
|
||||
|
||||
export const useTableColumns = () => {
|
||||
const { onColumnsChange, setTableColumns } = useRecordTable();
|
||||
type useRecordTableProps = {
|
||||
recordTableScopeId?: string;
|
||||
};
|
||||
|
||||
export const useTableColumns = (props?: useRecordTableProps) => {
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
RecordTableScopeInternalContext,
|
||||
props?.recordTableScopeId,
|
||||
);
|
||||
const { onColumnsChange, setTableColumns } = useRecordTable({
|
||||
recordTableScopeId: scopeId,
|
||||
});
|
||||
|
||||
const {
|
||||
availableTableColumnsState,
|
||||
tableColumnsState,
|
||||
visibleTableColumnsSelector,
|
||||
} = useRecordTableScopedStates();
|
||||
} = useRecordTableScopedStates({
|
||||
customRecordTableScopeId: scopeId,
|
||||
});
|
||||
|
||||
const availableTableColumns = useRecoilValue(availableTableColumnsState);
|
||||
|
||||
const { currentViewId } = useView();
|
||||
|
||||
const setSavedTableColumns = useSetRecoilState(
|
||||
savedTableColumnsFamilyState(currentViewId),
|
||||
);
|
||||
|
||||
const tableColumns = useRecoilValue(tableColumnsState);
|
||||
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
|
||||
|
||||
@ -34,12 +41,11 @@ export const useTableColumns = () => {
|
||||
|
||||
const handleColumnsChange = useCallback(
|
||||
async (columns: ColumnDefinition<FieldMetadata>[]) => {
|
||||
setSavedTableColumns(columns);
|
||||
setTableColumns(columns);
|
||||
|
||||
await onColumnsChange?.(columns);
|
||||
},
|
||||
[onColumnsChange, setSavedTableColumns, setTableColumns],
|
||||
[onColumnsChange, setTableColumns],
|
||||
);
|
||||
|
||||
const handleColumnVisibilityChange = useCallback(
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
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 { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
|
||||
@ -10,10 +10,12 @@ import { TableOptionsDropdownContent } from './TableOptionsDropdownContent';
|
||||
|
||||
export const TableOptionsDropdown = ({
|
||||
onImport,
|
||||
recordTableId,
|
||||
}: {
|
||||
onImport?: () => void;
|
||||
recordTableId: string;
|
||||
}) => {
|
||||
const { setViewEditMode } = useView();
|
||||
const { setViewEditMode } = useViewBar();
|
||||
|
||||
return (
|
||||
<DropdownScope dropdownScopeId={TableOptionsDropdownId}>
|
||||
@ -21,7 +23,12 @@ export const TableOptionsDropdown = ({
|
||||
clickableComponent={<TableOptionsDropdownButton />}
|
||||
dropdownHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }}
|
||||
dropdownOffset={{ y: 8 }}
|
||||
dropdownComponents={<TableOptionsDropdownContent onImport={onImport} />}
|
||||
dropdownComponents={
|
||||
<TableOptionsDropdownContent
|
||||
onImport={onImport}
|
||||
recordTableId={recordTableId}
|
||||
/>
|
||||
}
|
||||
onClickOutside={() => setViewEditMode('none')}
|
||||
/>
|
||||
</DropdownScope>
|
||||
|
||||
@ -13,7 +13,7 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
|
||||
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 { useTableColumns } from '../../hooks/useTableColumns';
|
||||
@ -23,10 +23,12 @@ type TableOptionsMenu = 'fields';
|
||||
|
||||
export const TableOptionsDropdownContent = ({
|
||||
onImport,
|
||||
recordTableId,
|
||||
}: {
|
||||
onImport?: () => void;
|
||||
recordTableId: string;
|
||||
}) => {
|
||||
const { setViewEditMode, handleViewNameSubmit } = useView();
|
||||
const { setViewEditMode, handleViewNameSubmit } = useViewBar();
|
||||
const { viewEditModeState, currentViewSelector } = useViewScopedStates();
|
||||
|
||||
const viewEditMode = useRecoilValue(viewEditModeState);
|
||||
@ -40,13 +42,14 @@ export const TableOptionsDropdownContent = ({
|
||||
const viewEditInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const { hiddenTableColumnsSelector, visibleTableColumnsSelector } =
|
||||
useRecordTableScopedStates();
|
||||
useRecordTableScopedStates({ customRecordTableScopeId: recordTableId });
|
||||
|
||||
const hiddenTableColumns = useRecoilValue(hiddenTableColumnsSelector);
|
||||
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector);
|
||||
|
||||
const { handleColumnVisibilityChange, handleColumnReorder } =
|
||||
useTableColumns();
|
||||
const { handleColumnVisibilityChange, handleColumnReorder } = useTableColumns(
|
||||
{ recordTableScopeId: recordTableId },
|
||||
);
|
||||
|
||||
const handleSelectMenu = (option: TableOptionsMenu) => {
|
||||
const name = viewEditInputRef.current?.value;
|
||||
|
||||
@ -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: [],
|
||||
});
|
||||
@ -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 }),
|
||||
{},
|
||||
),
|
||||
});
|
||||
@ -9,7 +9,7 @@ import { ButtonGroup } from '@/ui/input/button/components/ButtonGroup';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
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';
|
||||
|
||||
@ -29,7 +29,7 @@ export const UpdateViewButtonGroup = ({
|
||||
onViewEditModeChange,
|
||||
}: UpdateViewButtonGroupProps) => {
|
||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||
const { updateCurrentView, setViewEditMode } = useView();
|
||||
const { updateCurrentView, setViewEditMode } = useViewBar();
|
||||
const { canPersistFiltersSelector, canPersistSortsSelector } =
|
||||
useViewScopedStates();
|
||||
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { TopBar } from '@/ui/layout/top-bar/TopBar';
|
||||
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 { 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 { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
|
||||
@ -19,82 +21,91 @@ import { ViewBarEffect } from './ViewBarEffect';
|
||||
import { ViewsDropdownButton } from './ViewsDropdownButton';
|
||||
|
||||
export type ViewBarProps = {
|
||||
viewBarId: string;
|
||||
className?: string;
|
||||
optionsDropdownButton: ReactNode;
|
||||
optionsDropdownScopeId: string;
|
||||
onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>;
|
||||
onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>;
|
||||
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
|
||||
};
|
||||
|
||||
export const ViewBar = ({
|
||||
viewBarId,
|
||||
className,
|
||||
optionsDropdownButton,
|
||||
optionsDropdownScopeId,
|
||||
onViewFieldsChange,
|
||||
onViewFiltersChange,
|
||||
onViewSortsChange,
|
||||
}: ViewBarProps) => {
|
||||
const { openDropdown: openOptionsDropdownButton } = useDropdown({
|
||||
dropdownScopeId: optionsDropdownScopeId,
|
||||
});
|
||||
const { upsertViewSort, upsertViewFilter } = useView();
|
||||
const { upsertViewSort, upsertViewFilter } = useViewBar({
|
||||
viewBarId: viewBarId,
|
||||
});
|
||||
|
||||
const { availableFilterDefinitionsState, availableSortDefinitionsState } =
|
||||
useViewScopedStates();
|
||||
|
||||
const availableFilterDefinitions = useRecoilValue(
|
||||
availableFilterDefinitionsState,
|
||||
);
|
||||
const availableSortDefinitions = useRecoilValue(
|
||||
availableSortDefinitionsState,
|
||||
);
|
||||
const filterDropdownId = 'view-filter';
|
||||
const sortDropdownId = 'view-sort';
|
||||
|
||||
return (
|
||||
<ObjectFilterDropdownScope
|
||||
filterScopeId="view-filter"
|
||||
availableFilterDefinitions={availableFilterDefinitions}
|
||||
onFilterSelect={upsertViewFilter}
|
||||
<ViewScope
|
||||
viewScopeId={viewBarId}
|
||||
onViewFieldsChange={onViewFieldsChange}
|
||||
onViewFiltersChange={onViewFiltersChange}
|
||||
onViewSortsChange={onViewSortsChange}
|
||||
>
|
||||
<ObjectSortDropdownScope
|
||||
sortScopeId="view-sort"
|
||||
availableSortDefinitions={availableSortDefinitions}
|
||||
<ViewBarEffect />
|
||||
<ViewBarFilterEffect
|
||||
filterDropdownId={filterDropdownId}
|
||||
onFilterSelect={upsertViewFilter}
|
||||
/>
|
||||
<ViewBarSortEffect
|
||||
sortDropdownId={sortDropdownId}
|
||||
onSortSelect={upsertViewSort}
|
||||
>
|
||||
<ViewBarEffect />
|
||||
<TopBar
|
||||
className={className}
|
||||
leftComponent={
|
||||
<ViewsDropdownButton
|
||||
onViewEditModeChange={openOptionsDropdownButton}
|
||||
hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
|
||||
optionsDropdownScopeId={optionsDropdownScopeId}
|
||||
/>
|
||||
|
||||
<TopBar
|
||||
className={className}
|
||||
leftComponent={
|
||||
<ViewsDropdownButton
|
||||
onViewEditModeChange={openOptionsDropdownButton}
|
||||
hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
|
||||
optionsDropdownScopeId={optionsDropdownScopeId}
|
||||
/>
|
||||
}
|
||||
displayBottomBorder={false}
|
||||
rightComponent={
|
||||
<>
|
||||
<ObjectFilterDropdownButton
|
||||
filterDropdownId={filterDropdownId}
|
||||
hotkeyScope={{
|
||||
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
displayBottomBorder={false}
|
||||
rightComponent={
|
||||
<>
|
||||
<ObjectFilterDropdownButton
|
||||
hotkeyScope={{
|
||||
scope: FiltersHotkeyScope.ObjectFilterDropdownButton,
|
||||
}}
|
||||
/>
|
||||
<ObjectSortDropdownButton
|
||||
hotkeyScope={{
|
||||
scope: FiltersHotkeyScope.ObjectSortDropdownButton,
|
||||
}}
|
||||
isPrimaryButton
|
||||
/>
|
||||
{optionsDropdownButton}
|
||||
</>
|
||||
}
|
||||
bottomComponent={
|
||||
<ViewBarDetails
|
||||
hasFilterButton
|
||||
rightComponent={
|
||||
<UpdateViewButtonGroup
|
||||
onViewEditModeChange={openOptionsDropdownButton}
|
||||
hotkeyScope={ViewsHotkeyScope.CreateDropdown}
|
||||
/>
|
||||
}
|
||||
<ObjectSortDropdownButton
|
||||
sortDropdownId={sortDropdownId}
|
||||
hotkeyScope={{
|
||||
scope: FiltersHotkeyScope.ObjectSortDropdownButton,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</ObjectSortDropdownScope>
|
||||
</ObjectFilterDropdownScope>
|
||||
{optionsDropdownButton}
|
||||
</>
|
||||
}
|
||||
bottomComponent={
|
||||
<ViewBarDetails
|
||||
filterDropdownId={filterDropdownId}
|
||||
hasFilterButton
|
||||
rightComponent={
|
||||
<UpdateViewButtonGroup
|
||||
onViewEditModeChange={openOptionsDropdownButton}
|
||||
hotkeyScope={ViewsHotkeyScope.CreateDropdown}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</ViewScope>
|
||||
);
|
||||
};
|
||||
|
||||
@ -6,15 +6,16 @@ import { IconArrowDown, IconArrowUp } from '@/ui/display/icon/index';
|
||||
import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons';
|
||||
import { AddObjectFilterFromDetailsButton } from '@/ui/object/object-filter-dropdown/components/AddObjectFilterFromDetailsButton';
|
||||
import { getOperandLabelShort } from '@/ui/object/object-filter-dropdown/utils/getOperandLabel';
|
||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||
|
||||
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
|
||||
import { useView } from '../hooks/useView';
|
||||
|
||||
import SortOrFilterChip from './SortOrFilterChip';
|
||||
|
||||
export type ViewBarDetailsProps = {
|
||||
hasFilterButton?: boolean;
|
||||
rightComponent?: ReactNode;
|
||||
filterDropdownId?: string;
|
||||
};
|
||||
|
||||
const StyledBar = styled.div`
|
||||
@ -88,6 +89,7 @@ const StyledAddFilterContainer = styled.div`
|
||||
export const ViewBarDetails = ({
|
||||
hasFilterButton = false,
|
||||
rightComponent,
|
||||
filterDropdownId,
|
||||
}: ViewBarDetailsProps) => {
|
||||
const {
|
||||
currentViewSortsState,
|
||||
@ -104,7 +106,7 @@ export const ViewBarDetails = ({
|
||||
const canPersistSorts = useRecoilValue(canPersistSortsSelector);
|
||||
const isViewBarExpanded = useRecoilValue(isViewBarExpandedState);
|
||||
|
||||
const { resetViewBar, removeViewSort, removeViewFilter } = useView();
|
||||
const { resetViewBar, removeViewSort, removeViewFilter } = useViewBar();
|
||||
|
||||
const canPersistView = canPersistFilters || canPersistSorts;
|
||||
|
||||
@ -161,7 +163,9 @@ export const ViewBarDetails = ({
|
||||
</StyledChipcontainer>
|
||||
{hasFilterButton && (
|
||||
<StyledAddFilterContainer>
|
||||
<AddObjectFilterFromDetailsButton />
|
||||
<AddObjectFilterFromDetailsButton
|
||||
filterDropdownId={filterDropdownId}
|
||||
/>
|
||||
</StyledAddFilterContainer>
|
||||
)}
|
||||
</StyledFilterContainer>
|
||||
|
||||
@ -5,11 +5,11 @@ import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
||||
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
|
||||
import { useView } from '../hooks/useView';
|
||||
import { getViewScopedStatesFromSnapshot } from '../utils/getViewScopedStatesFromSnapshot';
|
||||
|
||||
export const ViewBarEffect = () => {
|
||||
@ -20,7 +20,7 @@ export const ViewBarEffect = () => {
|
||||
loadViewFields,
|
||||
loadViewFilters,
|
||||
loadViewSorts,
|
||||
} = useView();
|
||||
} = useViewBar();
|
||||
|
||||
const [searchParams] = useSearchParams();
|
||||
const currentViewIdFromUrl = searchParams.get('view');
|
||||
|
||||
41
front/src/modules/views/components/ViewBarFilterEffect.tsx
Normal file
41
front/src/modules/views/components/ViewBarFilterEffect.tsx
Normal 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 <></>;
|
||||
};
|
||||
42
front/src/modules/views/components/ViewBarSortEffect.tsx
Normal file
42
front/src/modules/views/components/ViewBarSortEffect.tsx
Normal 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 <></>;
|
||||
};
|
||||
@ -19,11 +19,11 @@ import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import { MOBILE_VIEWPORT } from '@/ui/theme/constants/theme';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||
import { assertNotNull } from '~/utils/assert';
|
||||
|
||||
import { ViewsDropdownId } from '../constants/ViewsDropdownId';
|
||||
import { useViewScopedStates } from '../hooks/internal/useViewScopedStates';
|
||||
import { useView } from '../hooks/useView';
|
||||
|
||||
const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||
@ -68,7 +68,7 @@ export const ViewsDropdownButton = ({
|
||||
optionsDropdownScopeId,
|
||||
}: ViewsDropdownButtonProps) => {
|
||||
const theme = useTheme();
|
||||
const { removeView, changeViewInUrl } = useView();
|
||||
const { removeView, changeViewInUrl } = useViewBar();
|
||||
|
||||
const { viewsState, currentViewSelector, entityCountInCurrentViewState } =
|
||||
useViewScopedStates();
|
||||
@ -79,7 +79,7 @@ export const ViewsDropdownButton = ({
|
||||
entityCountInCurrentViewState,
|
||||
);
|
||||
|
||||
const { setViewEditMode, setCurrentViewId, loadView } = useView();
|
||||
const { setViewEditMode, setCurrentViewId, loadView } = useViewBar();
|
||||
|
||||
const {
|
||||
isDropdownOpen: isViewsDropdownOpen,
|
||||
|
||||
@ -23,7 +23,7 @@ export const useViewFilters = (viewScopeId: string) => {
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const { currentViewFiltersState } = useViewScopedStates({
|
||||
customViewScopeId: viewScopeId,
|
||||
viewScopeId: viewScopeId,
|
||||
});
|
||||
|
||||
const persistViewFilters = useRecoilCallback(
|
||||
|
||||
@ -8,12 +8,12 @@ import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/Vi
|
||||
import { currentViewIdScopedState } from '../../states/currentViewIdScopedState';
|
||||
import { getViewScopedStates } from '../../utils/internal/getViewScopedStates';
|
||||
|
||||
export const useViewScopedStates = (args?: { customViewScopeId?: string }) => {
|
||||
const { customViewScopeId } = args ?? {};
|
||||
export const useViewScopedStates = (args?: { viewScopeId?: string }) => {
|
||||
const { viewScopeId } = args ?? {};
|
||||
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
ViewScopeInternalContext,
|
||||
customViewScopeId,
|
||||
viewScopeId,
|
||||
);
|
||||
|
||||
// View
|
||||
|
||||
@ -22,7 +22,7 @@ export const useViewSorts = (viewScopeId: string) => {
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const { currentViewSortsState } = useViewScopedStates({
|
||||
customViewScopeId: viewScopeId,
|
||||
viewScopeId: viewScopeId,
|
||||
});
|
||||
|
||||
const persistViewSorts = useRecoilCallback(
|
||||
|
||||
@ -25,13 +25,13 @@ import { useViewScopedStates } from './internal/useViewScopedStates';
|
||||
import { useViewSorts } from './internal/useViewSorts';
|
||||
|
||||
type UseViewProps = {
|
||||
viewScopeId?: string;
|
||||
viewBarId?: string;
|
||||
};
|
||||
|
||||
export const useView = (props?: UseViewProps) => {
|
||||
export const useViewBar = (props?: UseViewProps) => {
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
ViewScopeInternalContext,
|
||||
props?.viewScopeId,
|
||||
props?.viewBarId,
|
||||
);
|
||||
|
||||
const {
|
||||
@ -46,7 +46,7 @@ export const useView = (props?: UseViewProps) => {
|
||||
viewObjectMetadataIdState,
|
||||
viewTypeState,
|
||||
} = useViewScopedStates({
|
||||
customViewScopeId: scopeId,
|
||||
viewScopeId: scopeId,
|
||||
});
|
||||
|
||||
const { persistViewSorts, upsertViewSort, removeViewSort } =
|
||||
@ -11,7 +11,6 @@ import { PageHeader } from '@/ui/layout/page/PageHeader';
|
||||
import { TabList } from '@/ui/layout/tab/components/TabList';
|
||||
import { TopBar } from '@/ui/layout/top-bar/TopBar';
|
||||
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 { TasksEffect } from './TasksEffect';
|
||||
@ -45,38 +44,36 @@ export const Tasks = () => {
|
||||
},
|
||||
];
|
||||
|
||||
const filterDropdownId = 'tasks-assignee-filter';
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<RecoilScope CustomRecoilScopeContext={TasksRecoilScopeContext}>
|
||||
<ObjectFilterDropdownScope filterScopeId="tasks-filter-scope">
|
||||
<TasksEffect />
|
||||
<PageHeader title="Tasks" Icon={IconCheckbox}>
|
||||
<PageAddTaskButton />
|
||||
</PageHeader>
|
||||
<PageBody>
|
||||
<StyledTasksContainer>
|
||||
<TopBar
|
||||
leftComponent={
|
||||
<StyledTabListContainer>
|
||||
<TabList
|
||||
context={TasksRecoilScopeContext}
|
||||
tabs={TASK_TABS}
|
||||
/>
|
||||
</StyledTabListContainer>
|
||||
}
|
||||
rightComponent={
|
||||
<ObjectFilterDropdownButton
|
||||
key="tasks-filter-dropdown-button"
|
||||
hotkeyScope={{
|
||||
scope: RelationPickerHotkeyScope.RelationPicker,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<TaskGroups />
|
||||
</StyledTasksContainer>
|
||||
</PageBody>
|
||||
</ObjectFilterDropdownScope>
|
||||
<TasksEffect filterDropdownId={filterDropdownId} />
|
||||
<PageHeader title="Tasks" Icon={IconCheckbox}>
|
||||
<PageAddTaskButton filterDropdownId={filterDropdownId} />
|
||||
</PageHeader>
|
||||
<PageBody>
|
||||
<StyledTasksContainer>
|
||||
<TopBar
|
||||
leftComponent={
|
||||
<StyledTabListContainer>
|
||||
<TabList context={TasksRecoilScopeContext} tabs={TASK_TABS} />
|
||||
</StyledTabListContainer>
|
||||
}
|
||||
rightComponent={
|
||||
<ObjectFilterDropdownButton
|
||||
filterDropdownId={filterDropdownId}
|
||||
key="tasks-filter-dropdown-button"
|
||||
hotkeyScope={{
|
||||
scope: RelationPickerHotkeyScope.RelationPicker,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<TaskGroups filterDropdownId={filterDropdownId} />
|
||||
</StyledTasksContainer>
|
||||
</PageBody>
|
||||
</RecoilScope>
|
||||
</PageContainer>
|
||||
);
|
||||
|
||||
@ -2,14 +2,21 @@ import { useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
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 { tasksFilterDefinitions } from './tasks-filter-definitions';
|
||||
|
||||
export const TasksEffect = () => {
|
||||
type TasksEffectProps = {
|
||||
filterDropdownId: string;
|
||||
};
|
||||
|
||||
export const TasksEffect = ({ filterDropdownId }: TasksEffectProps) => {
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
const { setSelectedFilter, setAvailableFilterDefinitions } = useFilter();
|
||||
const { setSelectedFilter, setAvailableFilterDefinitions } =
|
||||
useFilterDropdown({
|
||||
filterDropdownId: filterDropdownId,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setAvailableFilterDefinitions(tasksFilterDefinitions);
|
||||
|
||||
Reference in New Issue
Block a user