Complete Fix view work (#2272)
* Fix views * Make view sorts and view filters functional * Complete Company table view fix * Fix model creation * Start fixing board * Complete work
This commit is contained in:
@ -4,17 +4,13 @@ import { PageAddButton } from '@/ui/layout/page/PageAddButton';
|
|||||||
import { ActivityType } from '~/generated/graphql';
|
import { ActivityType } from '~/generated/graphql';
|
||||||
|
|
||||||
export const PageAddTaskButton = () => {
|
export const PageAddTaskButton = () => {
|
||||||
const { selectedFilters } = useFilter();
|
const { selectedFilter } = useFilter();
|
||||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||||
|
|
||||||
const assigneeIdFilter = selectedFilters.find(
|
|
||||||
(filter) => filter.key === 'assigneeId',
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
openCreateActivity({
|
openCreateActivity({
|
||||||
type: ActivityType.Task,
|
type: ActivityType.Task,
|
||||||
assigneeId: assigneeIdFilter?.value,
|
assigneeId: selectedFilter?.value,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -17,12 +17,14 @@ export const useCurrentUserTaskCount = () => {
|
|||||||
completedAt: { equals: null },
|
completedAt: { equals: null },
|
||||||
...(currentUser
|
...(currentUser
|
||||||
? turnFilterIntoWhereClause({
|
? turnFilterIntoWhereClause({
|
||||||
key: 'assigneeId',
|
fieldId: 'assigneeId',
|
||||||
type: 'entity',
|
|
||||||
value: currentUser.id,
|
value: currentUser.id,
|
||||||
operand: ViewFilterOperand.Is,
|
operand: ViewFilterOperand.Is,
|
||||||
displayValue: currentUser.displayName,
|
displayValue: currentUser.displayName,
|
||||||
displayAvatarUrl: currentUser.avatarUrl ?? undefined,
|
displayAvatarUrl: currentUser.avatarUrl ?? undefined,
|
||||||
|
definition: {
|
||||||
|
type: 'entity',
|
||||||
|
},
|
||||||
})
|
})
|
||||||
: {}),
|
: {}),
|
||||||
},
|
},
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { ActivityType, useGetActivitiesQuery } from '~/generated/graphql';
|
|||||||
import { parseDate } from '~/utils/date-utils';
|
import { parseDate } from '~/utils/date-utils';
|
||||||
|
|
||||||
export const useTasks = (entity?: ActivityTargetableEntity) => {
|
export const useTasks = (entity?: ActivityTargetableEntity) => {
|
||||||
const { selectedFilters } = useFilter();
|
const { selectedFilter } = useFilter();
|
||||||
|
|
||||||
const whereFilters = entity
|
const whereFilters = entity
|
||||||
? {
|
? {
|
||||||
@ -20,12 +20,7 @@ export const useTasks = (entity?: ActivityTargetableEntity) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: Object.assign(
|
: Object.assign({}, turnFilterIntoWhereClause(selectedFilter));
|
||||||
{},
|
|
||||||
...selectedFilters.map((filter) => {
|
|
||||||
return turnFilterIntoWhereClause(filter);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data: completeTasksData } = useGetActivitiesQuery({
|
const { data: completeTasksData } = useGetActivitiesQuery({
|
||||||
variables: {
|
variables: {
|
||||||
@ -35,7 +30,7 @@ export const useTasks = (entity?: ActivityTargetableEntity) => {
|
|||||||
...whereFilters,
|
...whereFilters,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
skip: !entity && selectedFilters.length === 0,
|
skip: !entity && !selectedFilter,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: incompleteTaskData } = useGetActivitiesQuery({
|
const { data: incompleteTaskData } = useGetActivitiesQuery({
|
||||||
@ -46,7 +41,7 @@ export const useTasks = (entity?: ActivityTargetableEntity) => {
|
|||||||
...whereFilters,
|
...whereFilters,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
skip: !entity && selectedFilters.length === 0,
|
skip: !entity && !selectedFilter,
|
||||||
});
|
});
|
||||||
|
|
||||||
const todayOrPreviousTasks = incompleteTaskData?.findManyActivities.filter(
|
const todayOrPreviousTasks = incompleteTaskData?.findManyActivities.filter(
|
||||||
|
|||||||
@ -1,15 +1,29 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { BoardContext } from '@/companies/states/contexts/BoardContext';
|
import { BoardContext } from '@/companies/states/contexts/BoardContext';
|
||||||
|
import { BoardOptionsDropdown } from '@/ui/layout/board/components/BoardOptionsDropdown';
|
||||||
|
import { BoardOptionsDropdownId } from '@/ui/layout/board/components/constants/BoardOptionsDropdownId';
|
||||||
import {
|
import {
|
||||||
EntityBoard,
|
EntityBoard,
|
||||||
EntityBoardProps,
|
EntityBoardProps,
|
||||||
} from '@/ui/layout/board/components/EntityBoard';
|
} from '@/ui/layout/board/components/EntityBoard';
|
||||||
import { EntityBoardActionBar } from '@/ui/layout/board/components/EntityBoardActionBar';
|
import { EntityBoardActionBar } from '@/ui/layout/board/components/EntityBoardActionBar';
|
||||||
import { EntityBoardContextMenu } from '@/ui/layout/board/components/EntityBoardContextMenu';
|
import { EntityBoardContextMenu } from '@/ui/layout/board/components/EntityBoardContextMenu';
|
||||||
|
import { ViewBar } from '@/views/components/ViewBar';
|
||||||
|
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';
|
||||||
import { CompanyBoardRecoilScopeContext } from '../../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
|
import { CompanyBoardRecoilScopeContext } from '../../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
|
||||||
|
|
||||||
|
const StyledContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
type CompanyBoardProps = Pick<
|
type CompanyBoardProps = Pick<
|
||||||
EntityBoardProps,
|
EntityBoardProps,
|
||||||
'onColumnAdd' | 'onColumnDelete' | 'onEditColumnTitle'
|
'onColumnAdd' | 'onColumnDelete' | 'onEditColumnTitle'
|
||||||
@ -20,24 +34,30 @@ export const CompanyBoard = ({
|
|||||||
onColumnDelete,
|
onColumnDelete,
|
||||||
onEditColumnTitle,
|
onEditColumnTitle,
|
||||||
}: CompanyBoardProps) => {
|
}: CompanyBoardProps) => {
|
||||||
|
const viewScopeId = 'company-board-view';
|
||||||
return (
|
return (
|
||||||
<>
|
<ViewScope viewScopeId={viewScopeId}>
|
||||||
<BoardContext.Provider
|
<StyledContainer>
|
||||||
value={{
|
<BoardContext.Provider
|
||||||
BoardRecoilScopeContext: CompanyBoardRecoilScopeContext,
|
value={{
|
||||||
}}
|
BoardRecoilScopeContext: CompanyBoardRecoilScopeContext,
|
||||||
>
|
}}
|
||||||
<HooksCompanyBoardEffect />
|
>
|
||||||
|
<ViewBar
|
||||||
<EntityBoard
|
optionsDropdownButton={<BoardOptionsDropdown />}
|
||||||
boardOptions={opportunitiesBoardOptions}
|
optionsDropdownScopeId={BoardOptionsDropdownId}
|
||||||
onColumnAdd={onColumnAdd}
|
/>
|
||||||
onColumnDelete={onColumnDelete}
|
<HooksCompanyBoardEffect />
|
||||||
onEditColumnTitle={onEditColumnTitle}
|
<EntityBoard
|
||||||
/>
|
boardOptions={opportunitiesBoardOptions}
|
||||||
<EntityBoardActionBar />
|
onColumnAdd={onColumnAdd}
|
||||||
<EntityBoardContextMenu />
|
onColumnDelete={onColumnDelete}
|
||||||
</BoardContext.Provider>
|
onEditColumnTitle={onEditColumnTitle}
|
||||||
</>
|
/>
|
||||||
|
<EntityBoardActionBar />
|
||||||
|
<EntityBoardContextMenu />
|
||||||
|
</BoardContext.Provider>
|
||||||
|
</StyledContainer>
|
||||||
|
</ViewScope>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,12 +2,19 @@ import { useEffect, useMemo } from 'react';
|
|||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions';
|
||||||
import { turnFilterIntoWhereClause } from '@/ui/data/filter/utils/turnFilterIntoWhereClause';
|
import { turnFilterIntoWhereClause } from '@/ui/data/filter/utils/turnFilterIntoWhereClause';
|
||||||
import { useBoardActionBarEntries } from '@/ui/layout/board/hooks/useBoardActionBarEntries';
|
import { useBoardActionBarEntries } from '@/ui/layout/board/hooks/useBoardActionBarEntries';
|
||||||
|
import { useBoardContext } from '@/ui/layout/board/hooks/useBoardContext';
|
||||||
import { useBoardContextMenuEntries } from '@/ui/layout/board/hooks/useBoardContextMenuEntries';
|
import { useBoardContextMenuEntries } from '@/ui/layout/board/hooks/useBoardContextMenuEntries';
|
||||||
|
import { availableBoardCardFieldsScopedState } from '@/ui/layout/board/states/availableBoardCardFieldsScopedState';
|
||||||
|
import { boardCardFieldsScopedState } from '@/ui/layout/board/states/boardCardFieldsScopedState';
|
||||||
import { isBoardLoadedState } from '@/ui/layout/board/states/isBoardLoadedState';
|
import { isBoardLoadedState } from '@/ui/layout/board/states/isBoardLoadedState';
|
||||||
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { useViewInternalStates } from '@/views/hooks/useViewInternalStates';
|
import { useViewGetStates } from '@/views/hooks/useViewGetStates';
|
||||||
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
|
import { viewFieldsToBoardFieldDefinitions } from '@/views/utils/viewFieldsToBoardFieldDefinitions';
|
||||||
import {
|
import {
|
||||||
Pipeline,
|
Pipeline,
|
||||||
PipelineProgressableType,
|
PipelineProgressableType,
|
||||||
@ -22,20 +29,30 @@ import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns';
|
|||||||
|
|
||||||
export const HooksCompanyBoardEffect = () => {
|
export const HooksCompanyBoardEffect = () => {
|
||||||
const {
|
const {
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
|
setAvailableFieldDefinitions,
|
||||||
setEntityCountInCurrentView,
|
setEntityCountInCurrentView,
|
||||||
|
setViewObjectId,
|
||||||
|
setViewType,
|
||||||
} = useView();
|
} = useView();
|
||||||
|
|
||||||
const { currentViewFilters } = useViewInternalStates();
|
const { currentViewFilters, currentViewFields } = useViewGetStates();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setAvailableFilters(opportunitiesBoardOptions.filters);
|
|
||||||
setAvailableSorts?.(opportunitiesBoardOptions.sorts);
|
|
||||||
}, [setAvailableFilters, setAvailableSorts]);
|
|
||||||
|
|
||||||
const [, setIsBoardLoaded] = useRecoilState(isBoardLoadedState);
|
const [, setIsBoardLoaded] = useRecoilState(isBoardLoadedState);
|
||||||
|
|
||||||
|
const { BoardRecoilScopeContext } = useBoardContext();
|
||||||
|
|
||||||
|
const [, setBoardCardFields] = useRecoilScopedState(
|
||||||
|
boardCardFieldsScopedState,
|
||||||
|
BoardRecoilScopeContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [, setAvailableBoardCardFields] = useRecoilScopedState(
|
||||||
|
availableBoardCardFieldsScopedState,
|
||||||
|
BoardRecoilScopeContext,
|
||||||
|
);
|
||||||
|
|
||||||
const updateCompanyBoard = useUpdateCompanyBoard();
|
const updateCompanyBoard = useUpdateCompanyBoard();
|
||||||
|
|
||||||
const { data: pipelineData, loading: loadingGetPipelines } =
|
const { data: pipelineData, loading: loadingGetPipelines } =
|
||||||
@ -51,6 +68,21 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
|
|
||||||
const pipeline = pipelineData?.findManyPipeline[0] as Pipeline | undefined;
|
const pipeline = pipelineData?.findManyPipeline[0] as Pipeline | undefined;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setAvailableFilterDefinitions(opportunitiesBoardOptions.filterDefinitions);
|
||||||
|
setAvailableSortDefinitions?.(opportunitiesBoardOptions.sortDefinitions);
|
||||||
|
setAvailableFieldDefinitions?.(pipelineAvailableFieldDefinitions);
|
||||||
|
}, [
|
||||||
|
setAvailableFieldDefinitions,
|
||||||
|
setAvailableFilterDefinitions,
|
||||||
|
setAvailableSortDefinitions,
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setViewObjectId?.('company');
|
||||||
|
setViewType?.(ViewType.Kanban);
|
||||||
|
}, [setViewObjectId, setViewType]);
|
||||||
|
|
||||||
const pipelineStageIds = pipeline?.pipelineStages
|
const pipelineStageIds = pipeline?.pipelineStages
|
||||||
?.map((pipelineStage) => pipelineStage.id)
|
?.map((pipelineStage) => pipelineStage.id)
|
||||||
.flat();
|
.flat();
|
||||||
@ -107,6 +139,7 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
if (!loading && pipeline && pipelineProgresses && companiesData) {
|
if (!loading && pipeline && pipelineProgresses && companiesData) {
|
||||||
setActionBarEntries();
|
setActionBarEntries();
|
||||||
setContextMenuEntries();
|
setContextMenuEntries();
|
||||||
|
setAvailableBoardCardFields(pipelineAvailableFieldDefinitions);
|
||||||
updateCompanyBoard(pipeline, pipelineProgresses, companiesData.companies);
|
updateCompanyBoard(pipeline, pipelineProgresses, companiesData.companies);
|
||||||
setEntityCountInCurrentView(companiesData.companies.length);
|
setEntityCountInCurrentView(companiesData.companies.length);
|
||||||
}
|
}
|
||||||
@ -120,7 +153,19 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
setContextMenuEntries,
|
setContextMenuEntries,
|
||||||
searchParams,
|
searchParams,
|
||||||
setEntityCountInCurrentView,
|
setEntityCountInCurrentView,
|
||||||
|
setAvailableBoardCardFields,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentViewFields) {
|
||||||
|
setBoardCardFields(
|
||||||
|
viewFieldsToBoardFieldDefinitions(
|
||||||
|
currentViewFields,
|
||||||
|
pipelineAvailableFieldDefinitions,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [currentViewFields, setBoardCardFields]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,40 +8,59 @@ import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyT
|
|||||||
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
|
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
|
||||||
import { DataTable } from '@/ui/data/data-table/components/DataTable';
|
import { DataTable } from '@/ui/data/data-table/components/DataTable';
|
||||||
import { DataTableEffect } from '@/ui/data/data-table/components/DataTableEffect';
|
import { DataTableEffect } from '@/ui/data/data-table/components/DataTableEffect';
|
||||||
|
import { TableOptionsDropdownId } from '@/ui/data/data-table/constants/TableOptionsDropdownId';
|
||||||
import { TableContext } from '@/ui/data/data-table/contexts/TableContext';
|
import { TableContext } from '@/ui/data/data-table/contexts/TableContext';
|
||||||
import { useUpsertDataTableItem } from '@/ui/data/data-table/hooks/useUpsertDataTableItem';
|
import { useUpsertDataTableItem } from '@/ui/data/data-table/hooks/useUpsertDataTableItem';
|
||||||
import { TableOptionsDropdown } from '@/ui/data/data-table/options/components/TableOptionsDropdown';
|
import { TableOptionsDropdown } from '@/ui/data/data-table/options/components/TableOptionsDropdown';
|
||||||
import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumnsScopedState';
|
import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumnsScopedState';
|
||||||
|
import { tableFiltersScopedState } from '@/ui/data/data-table/states/tableFiltersScopedState';
|
||||||
|
import { tableSortsScopedState } from '@/ui/data/data-table/states/tableSortsScopedState';
|
||||||
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 { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
import { ViewScope } from '@/views/scopes/ViewScope';
|
||||||
import { columnDefinitionsToViewFields } from '@/views/utils/columnDefinitionToViewField';
|
import { columnDefinitionsToViewFields } from '@/views/utils/columnDefinitionToViewField';
|
||||||
import { viewFieldsToColumnDefinitions } from '@/views/utils/viewFieldsToColumnDefinitions';
|
import { viewFieldsToColumnDefinitions } from '@/views/utils/viewFieldsToColumnDefinitions';
|
||||||
|
import { viewFiltersToFilters } from '@/views/utils/viewFiltersToFilters';
|
||||||
|
import { viewSortsToSorts } from '@/views/utils/viewSortsToSorts';
|
||||||
import {
|
import {
|
||||||
UpdateOneCompanyMutationVariables,
|
UpdateOneCompanyMutationVariables,
|
||||||
useGetCompaniesQuery,
|
useGetCompaniesQuery,
|
||||||
useGetWorkspaceMembersLazyQuery,
|
useGetWorkspaceMembersLazyQuery,
|
||||||
useUpdateOneCompanyMutation,
|
useUpdateOneCompanyMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
import { companyAvailableFilters } from '~/pages/companies/companies-filters';
|
import { companyTableFilterDefinitions } from '~/pages/companies/constants/companyTableFilterDefinitions';
|
||||||
import { companyAvailableSorts } from '~/pages/companies/companies-sorts';
|
import { companyTableSortDefinitions } from '~/pages/companies/constants/companyTableSortDefinitions';
|
||||||
|
|
||||||
import CompanyTableEffect from './CompanyTableEffect';
|
import CompanyTableEffect from './CompanyTableEffect';
|
||||||
|
|
||||||
|
const StyledContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
`;
|
||||||
|
|
||||||
export const CompanyTable = () => {
|
export const CompanyTable = () => {
|
||||||
const tableViewScopeId = 'company-table';
|
const viewScopeId = 'company-table-view';
|
||||||
|
const tableScopeId = 'companies';
|
||||||
const setTableColumns = useSetRecoilState(
|
const setTableColumns = useSetRecoilState(
|
||||||
tableColumnsScopedState('companies'),
|
tableColumnsScopedState(tableScopeId),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setTableFilters = useSetRecoilState(
|
||||||
|
tableFiltersScopedState(tableScopeId),
|
||||||
|
);
|
||||||
|
|
||||||
|
const setTableSorts = useSetRecoilState(tableSortsScopedState(tableScopeId));
|
||||||
|
|
||||||
const [updateEntityMutation] = useUpdateOneCompanyMutation();
|
const [updateEntityMutation] = useUpdateOneCompanyMutation();
|
||||||
const upsertDataTableItem = useUpsertDataTableItem();
|
const upsertDataTableItem = useUpsertDataTableItem();
|
||||||
|
|
||||||
const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery();
|
const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery();
|
||||||
const { persistViewFields } = useViewFields(tableViewScopeId);
|
const { persistViewFields } = useViewFields(viewScopeId);
|
||||||
const { setCurrentViewFields, currentViewId } = useView({
|
const { setCurrentViewFields } = useView({
|
||||||
viewScopeId: tableViewScopeId,
|
viewScopeId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { setContextMenuEntries } = useCompanyTableContextMenuEntries();
|
const { setContextMenuEntries } = useCompanyTableContextMenuEntries();
|
||||||
@ -79,16 +98,9 @@ export const CompanyTable = () => {
|
|||||||
const { openCompanySpreadsheetImport: onImport } =
|
const { openCompanySpreadsheetImport: onImport } =
|
||||||
useSpreadsheetCompanyImport();
|
useSpreadsheetCompanyImport();
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewScope
|
<ViewScope
|
||||||
viewScopeId={tableViewScopeId}
|
viewScopeId={viewScopeId}
|
||||||
onViewFieldsChange={(viewFields) => {
|
onViewFieldsChange={(viewFields) => {
|
||||||
setTableColumns(
|
setTableColumns(
|
||||||
viewFieldsToColumnDefinitions(
|
viewFieldsToColumnDefinitions(
|
||||||
@ -97,7 +109,12 @@ export const CompanyTable = () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onViewFiltersChange={() => {}}
|
onViewFiltersChange={(viewFilters) => {
|
||||||
|
setTableFilters(viewFiltersToFilters(viewFilters));
|
||||||
|
}}
|
||||||
|
onViewSortsChange={(viewSorts) => {
|
||||||
|
setTableSorts(viewSortsToSorts(viewSorts));
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<TableContext.Provider
|
<TableContext.Provider
|
||||||
@ -110,7 +127,7 @@ export const CompanyTable = () => {
|
|||||||
>
|
>
|
||||||
<ViewBar
|
<ViewBar
|
||||||
optionsDropdownButton={<TableOptionsDropdown onImport={onImport} />}
|
optionsDropdownButton={<TableOptionsDropdown onImport={onImport} />}
|
||||||
optionsDropdownScopeId="table-dropdown-option"
|
optionsDropdownScopeId={TableOptionsDropdownId}
|
||||||
/>
|
/>
|
||||||
<CompanyTableEffect />
|
<CompanyTableEffect />
|
||||||
<DataTableEffect
|
<DataTableEffect
|
||||||
@ -119,8 +136,8 @@ export const CompanyTable = () => {
|
|||||||
getRequestOptimisticEffectDefinition={
|
getRequestOptimisticEffectDefinition={
|
||||||
getCompaniesOptimisticEffectDefinition
|
getCompaniesOptimisticEffectDefinition
|
||||||
}
|
}
|
||||||
filterDefinitionArray={companyAvailableFilters}
|
filterDefinitionArray={companyTableFilterDefinitions}
|
||||||
sortDefinitionArray={companyAvailableSorts}
|
sortDefinitionArray={companyTableSortDefinitions}
|
||||||
setContextMenuEntries={setContextMenuEntries}
|
setContextMenuEntries={setContextMenuEntries}
|
||||||
setActionBarEntries={setActionBarEntries}
|
setActionBarEntries={setActionBarEntries}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -6,14 +6,14 @@ import { TableRecoilScopeContext } from '@/ui/data/data-table/states/recoil-scop
|
|||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { ViewType } from '@/views/types/ViewType';
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
import { companyAvailableFilters } from '~/pages/companies/companies-filters';
|
import { companyTableFilterDefinitions } from '~/pages/companies/constants/companyTableFilterDefinitions';
|
||||||
import { companyAvailableSorts } from '~/pages/companies/companies-sorts';
|
import { companyTableSortDefinitions } from '~/pages/companies/constants/companyTableSortDefinitions';
|
||||||
|
|
||||||
const CompanyTableEffect = () => {
|
const CompanyTableEffect = () => {
|
||||||
const {
|
const {
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setAvailableFields,
|
setAvailableFieldDefinitions,
|
||||||
setViewType,
|
setViewType,
|
||||||
setViewObjectId,
|
setViewObjectId,
|
||||||
} = useView();
|
} = useView();
|
||||||
@ -24,26 +24,21 @@ const CompanyTableEffect = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setAvailableSorts?.(companyAvailableSorts);
|
setAvailableSortDefinitions?.(companyTableSortDefinitions);
|
||||||
setAvailableFilters?.(companyAvailableFilters);
|
setAvailableFilterDefinitions?.(companyTableFilterDefinitions);
|
||||||
setAvailableFields?.(companiesAvailableFieldDefinitions);
|
setAvailableFieldDefinitions?.(companiesAvailableFieldDefinitions);
|
||||||
setViewObjectId?.('company');
|
setViewObjectId?.('company');
|
||||||
setViewType?.(ViewType.Table);
|
setViewType?.(ViewType.Table);
|
||||||
|
|
||||||
setAvailableTableColumns(companiesAvailableFieldDefinitions);
|
setAvailableTableColumns(companiesAvailableFieldDefinitions);
|
||||||
}, [
|
}, [
|
||||||
setAvailableFields,
|
setAvailableFieldDefinitions,
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
setAvailableTableColumns,
|
setAvailableTableColumns,
|
||||||
setViewObjectId,
|
setViewObjectId,
|
||||||
setViewType,
|
setViewType,
|
||||||
]);
|
]);
|
||||||
// useEffect(() => {
|
|
||||||
// if (currentViewFields) {
|
|
||||||
// setTableColumns([...currentViewFields].sort((a, b) => a.index - b.index));
|
|
||||||
// }
|
|
||||||
// }, [currentViewFields, setTableColumns]);
|
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// if (currentViewSorts) {
|
// if (currentViewSorts) {
|
||||||
|
|||||||
@ -17,7 +17,6 @@ export const CompanyTableMockDataEffect = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDataTableData(mockedCompaniesData, [], []);
|
setDataTableData(mockedCompaniesData, [], []);
|
||||||
|
|
||||||
setTableColumns(companiesAvailableFieldDefinitions);
|
setTableColumns(companiesAvailableFieldDefinitions);
|
||||||
}, [setDataTableData, setTableColumns]);
|
}, [setDataTableData, setTableColumns]);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { IconBuildingSkyscraper } from '@/ui/display/icon';
|
import { Icon123 } from '@/ui/input/constants/icons';
|
||||||
|
import { useLazyLoadIcons } from '@/ui/input/hooks/useLazyLoadIcons';
|
||||||
import NavItem from '@/ui/navigation/navbar/components/NavItem';
|
import NavItem from '@/ui/navigation/navbar/components/NavItem';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
@ -10,22 +11,26 @@ export const MetadataObjectNavItems = () => {
|
|||||||
const { metadataObjects } = useFindManyMetadataObjects();
|
const { metadataObjects } = useFindManyMetadataObjects();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { icons } = useLazyLoadIcons();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{metadataObjects
|
{metadataObjects
|
||||||
.filter((metadataObject) => !!metadataObject.isActive)
|
.filter((metadataObject) => !!metadataObject.isActive)
|
||||||
.map((metadataObject) => (
|
.filter((metadataObjects) => !metadataObjects.namePlural.endsWith('V2'))
|
||||||
<NavItem
|
.map((metadataObject) => {
|
||||||
key={metadataObject.id}
|
return (
|
||||||
label={capitalize(metadataObject.namePlural)}
|
<NavItem
|
||||||
to={`/objects/${metadataObject.namePlural}`}
|
key={metadataObject.id}
|
||||||
Icon={IconBuildingSkyscraper}
|
label={capitalize(metadataObject.namePlural)}
|
||||||
onClick={() => {
|
to={`/objects/${metadataObject.namePlural}`}
|
||||||
navigate(`/objects/${metadataObject.namePlural}`);
|
Icon={metadataObject.icon ? icons[metadataObject.icon] : Icon123}
|
||||||
}}
|
onClick={() => {
|
||||||
/>
|
navigate(`/objects/${metadataObject.namePlural}`);
|
||||||
))}
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,9 +9,9 @@ import { useMetadataObjectInContext } from '../hooks/useMetadataObjectInContext'
|
|||||||
|
|
||||||
export const ObjectTableEffect = () => {
|
export const ObjectTableEffect = () => {
|
||||||
const {
|
const {
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setAvailableFields,
|
setAvailableFieldDefinitions,
|
||||||
setViewType,
|
setViewType,
|
||||||
setViewObjectId,
|
setViewObjectId,
|
||||||
} = useView();
|
} = useView();
|
||||||
@ -38,22 +38,22 @@ export const ObjectTableEffect = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setAvailableSorts?.([]); // TODO: extract from metadata fields
|
setAvailableSortDefinitions?.([]); // TODO: extract from metadata fields
|
||||||
setAvailableFilters?.([]); // TODO: extract from metadata fields
|
setAvailableFilterDefinitions?.([]); // TODO: extract from metadata fields
|
||||||
setAvailableFields?.(columnDefinitions);
|
setAvailableFieldDefinitions?.(columnDefinitions);
|
||||||
setViewObjectId?.(objectNamePlural);
|
setViewObjectId?.(objectNamePlural);
|
||||||
setViewType?.(ViewType.Table);
|
setViewType?.(ViewType.Table);
|
||||||
|
|
||||||
setAvailableTableColumns(columnDefinitions);
|
setAvailableTableColumns(columnDefinitions);
|
||||||
}, [
|
}, [
|
||||||
setAvailableFields,
|
|
||||||
setAvailableFilters,
|
|
||||||
setAvailableSorts,
|
|
||||||
setAvailableTableColumns,
|
setAvailableTableColumns,
|
||||||
setViewObjectId,
|
setViewObjectId,
|
||||||
setViewType,
|
setViewType,
|
||||||
columnDefinitions,
|
columnDefinitions,
|
||||||
objectNamePlural,
|
objectNamePlural,
|
||||||
|
setAvailableSortDefinitions,
|
||||||
|
setAvailableFilterDefinitions,
|
||||||
|
setAvailableFieldDefinitions,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
|
|||||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||||
import { formatMetadataFieldAsColumnDefinition } from '../utils/formatMetadataFieldAsColumnDefinition';
|
import { formatMetadataFieldAsColumnDefinition } from '../utils/formatMetadataFieldAsColumnDefinition';
|
||||||
import { generateCreateOneObjectMutation } from '../utils/generateCreateOneObjectMutation';
|
import { generateCreateOneObjectMutation } from '../utils/generateCreateOneObjectMutation';
|
||||||
|
import { generateDeleteOneObjectMutation } from '../utils/generateDeleteOneObjectMutation';
|
||||||
import { generateFindManyCustomObjectsQuery } from '../utils/generateFindManyCustomObjectsQuery';
|
import { generateFindManyCustomObjectsQuery } from '../utils/generateFindManyCustomObjectsQuery';
|
||||||
import { generateFindOneCustomObjectQuery } from '../utils/generateFindOneCustomObjectQuery';
|
import { generateFindOneCustomObjectQuery } from '../utils/generateFindOneCustomObjectQuery';
|
||||||
import { generateUpdateOneObjectMutation } from '../utils/generateUpdateOneObjectMutation';
|
import { generateUpdateOneObjectMutation } from '../utils/generateUpdateOneObjectMutation';
|
||||||
@ -79,7 +80,7 @@ export const useFindOneMetadataObject = ({
|
|||||||
|
|
||||||
// TODO: implement backend delete
|
// TODO: implement backend delete
|
||||||
const deleteOneMutation = foundMetadataObject
|
const deleteOneMutation = foundMetadataObject
|
||||||
? generateCreateOneObjectMutation({
|
? generateDeleteOneObjectMutation({
|
||||||
metadataObject: foundMetadataObject,
|
metadataObject: foundMetadataObject,
|
||||||
})
|
})
|
||||||
: gql`
|
: gql`
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { TableRecoilScopeContext } from '@/ui/data/data-table/states/recoil-scop
|
|||||||
import { tableRowIdsState } from '@/ui/data/data-table/states/tableRowIdsState';
|
import { tableRowIdsState } from '@/ui/data/data-table/states/tableRowIdsState';
|
||||||
import { entityFieldsFamilyState } from '@/ui/data/field/states/entityFieldsFamilyState';
|
import { entityFieldsFamilyState } from '@/ui/data/field/states/entityFieldsFamilyState';
|
||||||
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
||||||
import { availableSortsScopedState } from '@/views/states/availableSortsScopedState';
|
import { availableSortDefinitionsScopedState } from '@/views/states/availableSortDefinitionsScopedState';
|
||||||
|
|
||||||
export const useSetObjectDataTableData = () => {
|
export const useSetObjectDataTableData = () => {
|
||||||
const resetTableRowSelection = useResetTableRowSelection();
|
const resetTableRowSelection = useResetTableRowSelection();
|
||||||
@ -41,7 +41,10 @@ export const useSetObjectDataTableData = () => {
|
|||||||
|
|
||||||
set(numberOfTableRowsState, entityIds.length);
|
set(numberOfTableRowsState, entityIds.length);
|
||||||
|
|
||||||
set(availableSortsScopedState({ scopeId: tableContextScopeId }), []);
|
set(
|
||||||
|
availableSortDefinitionsScopedState({ scopeId: tableContextScopeId }),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
set(isFetchingDataTableDataState, false);
|
set(isFetchingDataTableDataState, false);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,97 +0,0 @@
|
|||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import { getPeopleOptimisticEffectDefinition } from '@/people/graphql/optimistic-effect-definitions/getPeopleOptimisticEffectDefinition';
|
|
||||||
import { usePersonTableContextMenuEntries } from '@/people/hooks/usePeopleTableContextMenuEntries';
|
|
||||||
import { usePersonTableActionBarEntries } from '@/people/hooks/usePersonTableActionBarEntries';
|
|
||||||
import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport';
|
|
||||||
import { DataTable } from '@/ui/data/data-table/components/DataTable';
|
|
||||||
import { DataTableEffect } from '@/ui/data/data-table/components/DataTableEffect';
|
|
||||||
import { TableContext } from '@/ui/data/data-table/contexts/TableContext';
|
|
||||||
import { useUpsertDataTableItem } from '@/ui/data/data-table/hooks/useUpsertDataTableItem';
|
|
||||||
import { TableOptionsDropdown } from '@/ui/data/data-table/options/components/TableOptionsDropdown';
|
|
||||||
import { ViewBar } from '@/views/components/ViewBar';
|
|
||||||
import { ViewBarEffect } from '@/views/components/ViewBarEffect';
|
|
||||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
|
||||||
import {
|
|
||||||
UpdateOnePersonMutationVariables,
|
|
||||||
useGetPeopleQuery,
|
|
||||||
useUpdateOnePersonMutation,
|
|
||||||
} from '~/generated/graphql';
|
|
||||||
import { peopleAvailableFilters } from '~/pages/people/people-filters';
|
|
||||||
import { peopleAvailableSorts } from '~/pages/people/people-sorts';
|
|
||||||
|
|
||||||
import PersonTableEffect from './PersonTableEffect';
|
|
||||||
|
|
||||||
export const PeopleTable = () => {
|
|
||||||
const tableViewScopeId = 'person-table';
|
|
||||||
|
|
||||||
const [updateEntityMutation] = useUpdateOnePersonMutation();
|
|
||||||
const upsertDataTableItem = useUpsertDataTableItem();
|
|
||||||
|
|
||||||
const { setContextMenuEntries } = usePersonTableContextMenuEntries();
|
|
||||||
const { setActionBarEntries } = usePersonTableActionBarEntries();
|
|
||||||
|
|
||||||
const { openPersonSpreadsheetImport: onImport } =
|
|
||||||
useSpreadsheetPersonImport();
|
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ViewScope
|
|
||||||
viewScopeId={tableViewScopeId}
|
|
||||||
onViewFieldsChange={() => {}}
|
|
||||||
onViewSortsChange={() => {}}
|
|
||||||
onViewFiltersChange={() => {}}
|
|
||||||
>
|
|
||||||
<StyledContainer>
|
|
||||||
<TableContext.Provider
|
|
||||||
value={{
|
|
||||||
onColumnsChange: () => {},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ViewBarEffect />
|
|
||||||
|
|
||||||
<ViewBar
|
|
||||||
optionsDropdownButton={<TableOptionsDropdown onImport={onImport} />}
|
|
||||||
optionsDropdownScopeId="table-dropdown-option"
|
|
||||||
/>
|
|
||||||
<PersonTableEffect />
|
|
||||||
|
|
||||||
<DataTableEffect
|
|
||||||
getRequestResultKey="people"
|
|
||||||
useGetRequest={useGetPeopleQuery}
|
|
||||||
getRequestOptimisticEffectDefinition={
|
|
||||||
getPeopleOptimisticEffectDefinition
|
|
||||||
}
|
|
||||||
filterDefinitionArray={peopleAvailableFilters}
|
|
||||||
sortDefinitionArray={peopleAvailableSorts}
|
|
||||||
setContextMenuEntries={setContextMenuEntries}
|
|
||||||
setActionBarEntries={setActionBarEntries}
|
|
||||||
/>
|
|
||||||
<DataTable
|
|
||||||
updateEntityMutation={({
|
|
||||||
variables,
|
|
||||||
}: {
|
|
||||||
variables: UpdateOnePersonMutationVariables;
|
|
||||||
}) =>
|
|
||||||
updateEntityMutation({
|
|
||||||
variables,
|
|
||||||
onCompleted: (data) => {
|
|
||||||
if (!data.updateOnePerson) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
upsertDataTableItem(data.updateOnePerson);
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</TableContext.Provider>
|
|
||||||
</StyledContainer>
|
|
||||||
</ViewScope>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
135
front/src/modules/people/table/components/PersonTable.tsx
Normal file
135
front/src/modules/people/table/components/PersonTable.tsx
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
import { peopleAvailableFieldDefinitions } from '@/people/constants/peopleAvailableFieldDefinitions';
|
||||||
|
import { getPeopleOptimisticEffectDefinition } from '@/people/graphql/optimistic-effect-definitions/getPeopleOptimisticEffectDefinition';
|
||||||
|
import { usePersonTableActionBarEntries } from '@/people/hooks/usePersonTableActionBarEntries';
|
||||||
|
import { usePersonTableContextMenuEntries } from '@/people/hooks/usePersonTableContextMenuEntries';
|
||||||
|
import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport';
|
||||||
|
import { DataTable } from '@/ui/data/data-table/components/DataTable';
|
||||||
|
import { DataTableEffect } from '@/ui/data/data-table/components/DataTableEffect';
|
||||||
|
import { TableContext } from '@/ui/data/data-table/contexts/TableContext';
|
||||||
|
import { useUpsertDataTableItem } from '@/ui/data/data-table/hooks/useUpsertDataTableItem';
|
||||||
|
import { TableOptionsDropdown } from '@/ui/data/data-table/options/components/TableOptionsDropdown';
|
||||||
|
import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumnsScopedState';
|
||||||
|
import { tableFiltersScopedState } from '@/ui/data/data-table/states/tableFiltersScopedState';
|
||||||
|
import { tableSortsScopedState } from '@/ui/data/data-table/states/tableSortsScopedState';
|
||||||
|
import { ViewBar } from '@/views/components/ViewBar';
|
||||||
|
import { useViewFields } from '@/views/hooks/internal/useViewFields';
|
||||||
|
import { useView } from '@/views/hooks/useView';
|
||||||
|
import { ViewScope } from '@/views/scopes/ViewScope';
|
||||||
|
import { columnDefinitionsToViewFields } from '@/views/utils/columnDefinitionToViewField';
|
||||||
|
import { viewFieldsToColumnDefinitions } from '@/views/utils/viewFieldsToColumnDefinitions';
|
||||||
|
import { viewFiltersToFilters } from '@/views/utils/viewFiltersToFilters';
|
||||||
|
import { viewSortsToSorts } from '@/views/utils/viewSortsToSorts';
|
||||||
|
import {
|
||||||
|
UpdateOnePersonMutationVariables,
|
||||||
|
useGetPeopleQuery,
|
||||||
|
useUpdateOnePersonMutation,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
import { personTableFilterDefinitions } from '~/pages/people/constants/personTableFilterDefinitions';
|
||||||
|
import { personTableSortDefinitions } from '~/pages/people/constants/personTableSortDefinitions';
|
||||||
|
|
||||||
|
import PersonTableEffect from './PersonTableEffect';
|
||||||
|
|
||||||
|
export const PersonTable = () => {
|
||||||
|
const viewScopeId = 'person-table-view';
|
||||||
|
const tableScopeId = 'people';
|
||||||
|
const setTableColumns = useSetRecoilState(
|
||||||
|
tableColumnsScopedState(tableScopeId),
|
||||||
|
);
|
||||||
|
|
||||||
|
const setTableFilters = useSetRecoilState(
|
||||||
|
tableFiltersScopedState(tableScopeId),
|
||||||
|
);
|
||||||
|
|
||||||
|
const setTableSorts = useSetRecoilState(tableSortsScopedState(tableScopeId));
|
||||||
|
|
||||||
|
const [updateEntityMutation] = useUpdateOnePersonMutation();
|
||||||
|
const upsertDataTableItem = useUpsertDataTableItem();
|
||||||
|
|
||||||
|
const { persistViewFields } = useViewFields(viewScopeId);
|
||||||
|
const { setCurrentViewFields } = useView({
|
||||||
|
viewScopeId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { setContextMenuEntries } = usePersonTableContextMenuEntries();
|
||||||
|
const { setActionBarEntries } = usePersonTableActionBarEntries();
|
||||||
|
|
||||||
|
const updatePerson = async (variables: UpdateOnePersonMutationVariables) => {
|
||||||
|
updateEntityMutation({
|
||||||
|
variables: variables,
|
||||||
|
onCompleted: (data) => {
|
||||||
|
if (!data.updateOnePerson) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
upsertDataTableItem(data.updateOnePerson);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const { openPersonSpreadsheetImport: onImport } =
|
||||||
|
useSpreadsheetPersonImport();
|
||||||
|
|
||||||
|
const StyledContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ViewScope
|
||||||
|
viewScopeId={viewScopeId}
|
||||||
|
onViewFieldsChange={(viewFields) => {
|
||||||
|
setTableColumns(
|
||||||
|
viewFieldsToColumnDefinitions(
|
||||||
|
viewFields,
|
||||||
|
peopleAvailableFieldDefinitions,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
onViewFiltersChange={(viewFilters) => {
|
||||||
|
setTableFilters(viewFiltersToFilters(viewFilters));
|
||||||
|
}}
|
||||||
|
onViewSortsChange={(viewSorts) => {
|
||||||
|
setTableSorts(viewSortsToSorts(viewSorts));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StyledContainer>
|
||||||
|
<TableContext.Provider
|
||||||
|
value={{
|
||||||
|
onColumnsChange: useRecoilCallback(() => (columns) => {
|
||||||
|
setCurrentViewFields?.(columnDefinitionsToViewFields(columns));
|
||||||
|
persistViewFields(columnDefinitionsToViewFields(columns));
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ViewBar
|
||||||
|
optionsDropdownButton={<TableOptionsDropdown onImport={onImport} />}
|
||||||
|
optionsDropdownScopeId="table-dropdown-option"
|
||||||
|
/>
|
||||||
|
<PersonTableEffect />
|
||||||
|
<DataTableEffect
|
||||||
|
getRequestResultKey="people"
|
||||||
|
useGetRequest={useGetPeopleQuery}
|
||||||
|
getRequestOptimisticEffectDefinition={
|
||||||
|
getPeopleOptimisticEffectDefinition
|
||||||
|
}
|
||||||
|
filterDefinitionArray={personTableFilterDefinitions}
|
||||||
|
sortDefinitionArray={personTableSortDefinitions}
|
||||||
|
setContextMenuEntries={setContextMenuEntries}
|
||||||
|
setActionBarEntries={setActionBarEntries}
|
||||||
|
/>
|
||||||
|
<DataTable
|
||||||
|
updateEntityMutation={({
|
||||||
|
variables,
|
||||||
|
}: {
|
||||||
|
variables: UpdateOnePersonMutationVariables;
|
||||||
|
}) => updatePerson(variables)}
|
||||||
|
/>
|
||||||
|
</TableContext.Provider>
|
||||||
|
</StyledContainer>
|
||||||
|
</ViewScope>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -7,14 +7,14 @@ import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumn
|
|||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { ViewType } from '@/views/types/ViewType';
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
import { peopleAvailableFilters } from '~/pages/people/people-filters';
|
import { personTableFilterDefinitions } from '~/pages/people/constants/personTableFilterDefinitions';
|
||||||
import { peopleAvailableSorts } from '~/pages/people/people-sorts';
|
import { personTableSortDefinitions } from '~/pages/people/constants/personTableSortDefinitions';
|
||||||
|
|
||||||
const PeopleTableEffect = () => {
|
const PeopleTableEffect = () => {
|
||||||
const {
|
const {
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setAvailableFields,
|
setAvailableFieldDefinitions,
|
||||||
setViewType,
|
setViewType,
|
||||||
setViewObjectId,
|
setViewObjectId,
|
||||||
} = useView();
|
} = useView();
|
||||||
@ -30,17 +30,17 @@ const PeopleTableEffect = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setAvailableSorts?.(peopleAvailableSorts);
|
setAvailableSortDefinitions?.(personTableSortDefinitions);
|
||||||
setAvailableFilters?.(peopleAvailableFilters);
|
setAvailableFilterDefinitions?.(personTableFilterDefinitions);
|
||||||
setAvailableFields?.(peopleAvailableFieldDefinitions);
|
setAvailableFieldDefinitions?.(peopleAvailableFieldDefinitions);
|
||||||
setViewObjectId?.('person');
|
setViewObjectId?.('person');
|
||||||
setViewType?.(ViewType.Table);
|
setViewType?.(ViewType.Table);
|
||||||
|
|
||||||
setAvailableTableColumns(peopleAvailableFieldDefinitions);
|
setAvailableTableColumns(peopleAvailableFieldDefinitions);
|
||||||
}, [
|
}, [
|
||||||
setAvailableFields,
|
setAvailableFieldDefinitions,
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
setAvailableTableColumns,
|
setAvailableTableColumns,
|
||||||
setTableColumns,
|
setTableColumns,
|
||||||
setViewObjectId,
|
setViewObjectId,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
|
||||||
import {
|
import {
|
||||||
FieldDateMetadata,
|
FieldDateMetadata,
|
||||||
FieldMetadata,
|
FieldMetadata,
|
||||||
@ -12,10 +13,9 @@ import {
|
|||||||
IconUser,
|
IconUser,
|
||||||
} from '@/ui/display/icon';
|
} from '@/ui/display/icon';
|
||||||
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
||||||
import { BoardFieldDefinition } from '@/ui/layout/board/types/BoardFieldDefinition';
|
|
||||||
import { Person } from '~/generated/graphql';
|
import { Person } from '~/generated/graphql';
|
||||||
|
|
||||||
export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetadata>[] =
|
export const pipelineAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[] =
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
fieldId: 'closeDate',
|
fieldId: 'closeDate',
|
||||||
@ -26,10 +26,11 @@ export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetada
|
|||||||
metadata: {
|
metadata: {
|
||||||
fieldName: 'closeDate',
|
fieldName: 'closeDate',
|
||||||
},
|
},
|
||||||
|
size: 0,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
infoTooltipContent:
|
infoTooltipContent:
|
||||||
'Specified date by which an opportunity must be completed.',
|
'Specified date by which an opportunity must be completed.',
|
||||||
} satisfies BoardFieldDefinition<FieldDateMetadata>,
|
} satisfies ColumnDefinition<FieldDateMetadata>,
|
||||||
{
|
{
|
||||||
fieldId: 'amount',
|
fieldId: 'amount',
|
||||||
label: 'Amount',
|
label: 'Amount',
|
||||||
@ -40,9 +41,10 @@ export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetada
|
|||||||
fieldName: 'amount',
|
fieldName: 'amount',
|
||||||
placeHolder: '0',
|
placeHolder: '0',
|
||||||
},
|
},
|
||||||
|
size: 0,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
infoTooltipContent: 'Potential monetary value of a business opportunity.',
|
infoTooltipContent: 'Potential monetary value of a business opportunity.',
|
||||||
} satisfies BoardFieldDefinition<FieldNumberMetadata>,
|
} satisfies ColumnDefinition<FieldNumberMetadata>,
|
||||||
{
|
{
|
||||||
fieldId: 'probability',
|
fieldId: 'probability',
|
||||||
label: 'Probability',
|
label: 'Probability',
|
||||||
@ -52,10 +54,11 @@ export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetada
|
|||||||
metadata: {
|
metadata: {
|
||||||
fieldName: 'probability',
|
fieldName: 'probability',
|
||||||
},
|
},
|
||||||
|
size: 0,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
infoTooltipContent:
|
infoTooltipContent:
|
||||||
"Level of certainty in the lead's potential to convert into a success.",
|
"Level of certainty in the lead's potential to convert into a success.",
|
||||||
} satisfies BoardFieldDefinition<FieldProbabilityMetadata>,
|
} satisfies ColumnDefinition<FieldProbabilityMetadata>,
|
||||||
{
|
{
|
||||||
fieldId: 'pointOfContact',
|
fieldId: 'pointOfContact',
|
||||||
label: 'Point of Contact',
|
label: 'Point of Contact',
|
||||||
@ -67,6 +70,7 @@ export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetada
|
|||||||
relationType: Entity.Person,
|
relationType: Entity.Person,
|
||||||
useEditButton: true,
|
useEditButton: true,
|
||||||
},
|
},
|
||||||
|
size: 0,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
infoTooltipContent: 'Primary contact within the company.',
|
infoTooltipContent: 'Primary contact within the company.',
|
||||||
entityChipDisplayMapper: (dataObject: Person) => {
|
entityChipDisplayMapper: (dataObject: Person) => {
|
||||||
@ -76,5 +80,5 @@ export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetada
|
|||||||
avatarType: 'rounded',
|
avatarType: 'rounded',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
} satisfies BoardFieldDefinition<FieldRelationMetadata>,
|
} satisfies ColumnDefinition<FieldRelationMetadata>,
|
||||||
];
|
];
|
||||||
|
|||||||
@ -55,7 +55,12 @@ export const SettingsObjectIconSection = ({
|
|||||||
<StyledArrowContainer>
|
<StyledArrowContainer>
|
||||||
<img src={ArrowRight} alt="Arrow right" width={32} height={16} />
|
<img src={ArrowRight} alt="Arrow right" width={32} height={16} />
|
||||||
</StyledArrowContainer>
|
</StyledArrowContainer>
|
||||||
<SettingsObjectIconWithLabel Icon={Icon} label={label || 'Investors'} />
|
{Icon && (
|
||||||
|
<SettingsObjectIconWithLabel
|
||||||
|
Icon={Icon}
|
||||||
|
label={label || 'Investors'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
</Section>
|
</Section>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -168,37 +168,35 @@ export const DataTableHeader = () => {
|
|||||||
>
|
>
|
||||||
<SelectAllCheckbox />
|
<SelectAllCheckbox />
|
||||||
</th>
|
</th>
|
||||||
{[...visibleTableColumns]
|
{visibleTableColumns.map((column) => (
|
||||||
.sort((columnA, columnB) => columnA.position - columnB.position)
|
<StyledColumnHeaderCell
|
||||||
.map((column) => (
|
key={column.fieldId}
|
||||||
<StyledColumnHeaderCell
|
isResizing={resizedFieldKey === column.fieldId}
|
||||||
key={column.fieldId}
|
columnWidth={Math.max(
|
||||||
isResizing={resizedFieldKey === column.fieldId}
|
tableColumnsByKey[column.fieldId].size +
|
||||||
columnWidth={Math.max(
|
(resizedFieldKey === column.fieldId ? resizeFieldOffset : 0),
|
||||||
tableColumnsByKey[column.fieldId].size +
|
COLUMN_MIN_WIDTH,
|
||||||
(resizedFieldKey === column.fieldId ? resizeFieldOffset : 0),
|
)}
|
||||||
COLUMN_MIN_WIDTH,
|
>
|
||||||
)}
|
<StyledColumnHeadContainer>
|
||||||
>
|
<ColumnHeadWithDropdown
|
||||||
<StyledColumnHeadContainer>
|
column={column}
|
||||||
<ColumnHeadWithDropdown
|
isFirstColumn={column.position === 1}
|
||||||
column={column}
|
isLastColumn={
|
||||||
isFirstColumn={column.position === 1}
|
column.position === visibleTableColumns.length - 1
|
||||||
isLastColumn={
|
}
|
||||||
column.position === visibleTableColumns.length - 1
|
primaryColumnKey={primaryColumn?.fieldId || ''}
|
||||||
}
|
|
||||||
primaryColumnKey={primaryColumn?.fieldId || ''}
|
|
||||||
/>
|
|
||||||
</StyledColumnHeadContainer>
|
|
||||||
<StyledResizeHandler
|
|
||||||
className="cursor-col-resize"
|
|
||||||
role="separator"
|
|
||||||
onPointerDown={() => {
|
|
||||||
setResizedFieldKey(column.fieldId);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</StyledColumnHeaderCell>
|
</StyledColumnHeadContainer>
|
||||||
))}
|
<StyledResizeHandler
|
||||||
|
className="cursor-col-resize"
|
||||||
|
role="separator"
|
||||||
|
onPointerDown={() => {
|
||||||
|
setResizedFieldKey(column.fieldId);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</StyledColumnHeaderCell>
|
||||||
|
))}
|
||||||
<th>
|
<th>
|
||||||
{hiddenTableColumns.length > 0 && (
|
{hiddenTableColumns.length > 0 && (
|
||||||
<StyledColumnHeadContainer>
|
<StyledColumnHeadContainer>
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { entityFieldsFamilyState } from '@/ui/data/field/states/entityFieldsFami
|
|||||||
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
||||||
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
||||||
import { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { availableSortsScopedState } from '@/views/states/availableSortsScopedState';
|
import { availableSortDefinitionsScopedState } from '@/views/states/availableSortDefinitionsScopedState';
|
||||||
|
|
||||||
import { SortDefinition } from '../../sort/types/SortDefinition';
|
import { SortDefinition } from '../../sort/types/SortDefinition';
|
||||||
import { isFetchingDataTableDataState } from '../states/isFetchingDataTableDataState';
|
import { isFetchingDataTableDataState } from '../states/isFetchingDataTableDataState';
|
||||||
@ -54,7 +54,7 @@ export const useSetDataTableData = () => {
|
|||||||
setEntityCountInCurrentView(entityIds.length);
|
setEntityCountInCurrentView(entityIds.length);
|
||||||
|
|
||||||
set(
|
set(
|
||||||
availableSortsScopedState({ scopeId: tableContextScopeId }),
|
availableSortDefinitionsScopedState({ scopeId: tableContextScopeId }),
|
||||||
sortDefinitionArray,
|
sortDefinitionArray,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,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 { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { useViewInternalStates } from '@/views/hooks/useViewInternalStates';
|
import { useViewGetStates } from '@/views/hooks/useViewGetStates';
|
||||||
|
|
||||||
import { useTableColumns } from '../../hooks/useTableColumns';
|
import { useTableColumns } from '../../hooks/useTableColumns';
|
||||||
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
|
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
@ -29,7 +29,7 @@ export const TableOptionsDropdownContent = ({
|
|||||||
onImport?: () => void;
|
onImport?: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { setViewEditMode, handleViewNameSubmit } = useView();
|
const { setViewEditMode, handleViewNameSubmit } = useView();
|
||||||
const { viewEditMode, currentView } = useViewInternalStates();
|
const { viewEditMode, currentView } = useViewGetStates();
|
||||||
|
|
||||||
const { closeDropdown } = useDropdown();
|
const { closeDropdown } = useDropdown();
|
||||||
|
|
||||||
|
|||||||
@ -12,12 +12,13 @@ type FilterDropdownButtonProps = {
|
|||||||
export const FilterDropdownButton = ({
|
export const FilterDropdownButton = ({
|
||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
}: FilterDropdownButtonProps) => {
|
}: FilterDropdownButtonProps) => {
|
||||||
const { availableFilters } = useFilter();
|
const { availableFilterDefinitions } = useFilter();
|
||||||
|
|
||||||
const hasOnlyOneEntityFilter =
|
const hasOnlyOneEntityFilter =
|
||||||
availableFilters.length === 1 && availableFilters[0].type === 'entity';
|
availableFilterDefinitions.length === 1 &&
|
||||||
|
availableFilterDefinitions[0].type === 'entity';
|
||||||
|
|
||||||
if (!availableFilters.length) {
|
if (!availableFilterDefinitions.length) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker';
|
import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker';
|
||||||
import { useUpsertFilter } from '@/views/hooks/useUpsertFilter';
|
|
||||||
|
|
||||||
import { useFilter } from '../hooks/useFilter';
|
import { useFilter } from '../hooks/useFilter';
|
||||||
|
|
||||||
@ -8,19 +7,18 @@ export const FilterDropdownDateSearchInput = () => {
|
|||||||
filterDefinitionUsedInDropdown,
|
filterDefinitionUsedInDropdown,
|
||||||
selectedOperandInDropdown,
|
selectedOperandInDropdown,
|
||||||
setIsFilterDropdownUnfolded,
|
setIsFilterDropdownUnfolded,
|
||||||
|
selectFilter,
|
||||||
} = useFilter();
|
} = useFilter();
|
||||||
|
|
||||||
const upsertFilter = useUpsertFilter();
|
|
||||||
|
|
||||||
const handleChange = (date: Date) => {
|
const handleChange = (date: Date) => {
|
||||||
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;
|
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;
|
||||||
|
|
||||||
upsertFilter({
|
selectFilter?.({
|
||||||
key: filterDefinitionUsedInDropdown.key,
|
fieldId: filterDefinitionUsedInDropdown.fieldId,
|
||||||
type: filterDefinitionUsedInDropdown.type,
|
|
||||||
value: date.toISOString(),
|
value: date.toISOString(),
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: date.toLocaleDateString(),
|
displayValue: date.toLocaleDateString(),
|
||||||
|
definition: filterDefinitionUsedInDropdown,
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsFilterDropdownUnfolded(false);
|
setIsFilterDropdownUnfolded(false);
|
||||||
|
|||||||
@ -1,11 +1,8 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { useFilterCurrentlyEdited } from '@/ui/data/filter/hooks/useFilterCurrentlyEdited';
|
|
||||||
import { EntitiesForMultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect';
|
import { EntitiesForMultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect';
|
||||||
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 { useRemoveFilter } from '@/views/hooks/useRemoveFilter';
|
|
||||||
import { useUpsertFilter } from '@/views/hooks/useUpsertFilter';
|
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
|
|
||||||
import { useFilter } from '../hooks/useFilter';
|
import { useFilter } from '../hooks/useFilter';
|
||||||
@ -16,20 +13,16 @@ export const FilterDropdownEntitySearchSelect = ({
|
|||||||
entitiesForSelect: EntitiesForMultipleEntitySelect<EntityForSelect>;
|
entitiesForSelect: EntitiesForMultipleEntitySelect<EntityForSelect>;
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
filterDropdownSelectedEntityId,
|
|
||||||
setFilterDropdownSelectedEntityId,
|
setFilterDropdownSelectedEntityId,
|
||||||
filterDefinitionUsedInDropdown,
|
filterDefinitionUsedInDropdown,
|
||||||
selectedOperandInDropdown,
|
selectedOperandInDropdown,
|
||||||
filterDropdownSearchInput,
|
filterDropdownSearchInput,
|
||||||
|
selectedFilter,
|
||||||
|
selectFilter,
|
||||||
} = useFilter();
|
} = useFilter();
|
||||||
|
|
||||||
const [isAllEntitySelected, setIsAllEntitySelected] = useState(false);
|
const [isAllEntitySelected, setIsAllEntitySelected] = useState(false);
|
||||||
|
|
||||||
const upsertFilter = useUpsertFilter();
|
|
||||||
const removeFilter = useRemoveFilter();
|
|
||||||
|
|
||||||
const filterCurrentlyEdited = useFilterCurrentlyEdited();
|
|
||||||
|
|
||||||
const handleUserSelected = (
|
const handleUserSelected = (
|
||||||
selectedEntity: EntityForSelect | null | undefined,
|
selectedEntity: EntityForSelect | null | undefined,
|
||||||
) => {
|
) => {
|
||||||
@ -45,24 +38,16 @@ export const FilterDropdownEntitySearchSelect = ({
|
|||||||
setIsAllEntitySelected(false);
|
setIsAllEntitySelected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const clickedOnAlreadySelectedEntity =
|
setFilterDropdownSelectedEntityId(selectedEntity.id);
|
||||||
selectedEntity.id === filterDropdownSelectedEntityId;
|
|
||||||
|
|
||||||
if (clickedOnAlreadySelectedEntity) {
|
selectFilter?.({
|
||||||
removeFilter(filterDefinitionUsedInDropdown.key);
|
displayValue: selectedEntity.name,
|
||||||
setFilterDropdownSelectedEntityId(null);
|
fieldId: filterDefinitionUsedInDropdown.fieldId,
|
||||||
} else {
|
operand: selectedOperandInDropdown,
|
||||||
setFilterDropdownSelectedEntityId(selectedEntity.id);
|
value: selectedEntity.id,
|
||||||
|
displayAvatarUrl: selectedEntity.avatarUrl,
|
||||||
upsertFilter({
|
definition: filterDefinitionUsedInDropdown,
|
||||||
displayValue: selectedEntity.name,
|
});
|
||||||
key: filterDefinitionUsedInDropdown.key,
|
|
||||||
operand: selectedOperandInDropdown,
|
|
||||||
type: filterDefinitionUsedInDropdown.type,
|
|
||||||
value: selectedEntity.id,
|
|
||||||
displayAvatarUrl: selectedEntity.avatarUrl,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const isAllEntitySelectShown =
|
const isAllEntitySelectShown =
|
||||||
@ -81,36 +66,30 @@ export const FilterDropdownEntitySearchSelect = ({
|
|||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isAllEntitySelected) {
|
|
||||||
setIsAllEntitySelected(false);
|
|
||||||
|
|
||||||
removeFilter(filterDefinitionUsedInDropdown.key);
|
setIsAllEntitySelected(true);
|
||||||
} else {
|
setFilterDropdownSelectedEntityId(null);
|
||||||
setIsAllEntitySelected(true);
|
|
||||||
|
|
||||||
setFilterDropdownSelectedEntityId(null);
|
selectFilter?.({
|
||||||
|
displayValue: filterDefinitionUsedInDropdown.selectAllLabel,
|
||||||
upsertFilter({
|
fieldId: filterDefinitionUsedInDropdown.fieldId,
|
||||||
displayValue: filterDefinitionUsedInDropdown.selectAllLabel,
|
operand: ViewFilterOperand.IsNotNull,
|
||||||
key: filterDefinitionUsedInDropdown.key,
|
value: '',
|
||||||
operand: ViewFilterOperand.IsNotNull,
|
definition: filterDefinitionUsedInDropdown,
|
||||||
type: filterDefinitionUsedInDropdown.type,
|
});
|
||||||
value: '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!filterCurrentlyEdited) {
|
if (!selectedFilter) {
|
||||||
setFilterDropdownSelectedEntityId(null);
|
setFilterDropdownSelectedEntityId(null);
|
||||||
} else {
|
} else {
|
||||||
setFilterDropdownSelectedEntityId(filterCurrentlyEdited.value);
|
setFilterDropdownSelectedEntityId(selectedFilter.value);
|
||||||
setIsAllEntitySelected(
|
setIsAllEntitySelected(
|
||||||
filterCurrentlyEdited.operand === ViewFilterOperand.IsNotNull,
|
selectedFilter.operand === ViewFilterOperand.IsNotNull,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
filterCurrentlyEdited,
|
selectedFilter,
|
||||||
setFilterDropdownSelectedEntityId,
|
setFilterDropdownSelectedEntityId,
|
||||||
entitiesForSelect.selectedEntities,
|
entitiesForSelect.selectedEntities,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -11,32 +11,32 @@ export const FilterDropdownFilterSelect = () => {
|
|||||||
setFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
setFilterDropdownSearchInput,
|
setFilterDropdownSearchInput,
|
||||||
availableFilters,
|
availableFilterDefinitions,
|
||||||
} = useFilter();
|
} = useFilter();
|
||||||
|
|
||||||
const setHotkeyScope = useSetHotkeyScope();
|
const setHotkeyScope = useSetHotkeyScope();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
{availableFilters.map((availableFilter, index) => (
|
{availableFilterDefinitions.map((availableFilterDefinition, index) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={`select-filter-${index}`}
|
key={`select-filter-${index}`}
|
||||||
testId={`select-filter-${index}`}
|
testId={`select-filter-${index}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFilterDefinitionUsedInDropdown(availableFilter);
|
setFilterDefinitionUsedInDropdown(availableFilterDefinition);
|
||||||
|
|
||||||
if (availableFilter.type === 'entity') {
|
if (availableFilterDefinition.type === 'entity') {
|
||||||
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
|
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedOperandInDropdown(
|
setSelectedOperandInDropdown(
|
||||||
getOperandsForFilterType(availableFilter.type)?.[0],
|
getOperandsForFilterType(availableFilterDefinition.type)?.[0],
|
||||||
);
|
);
|
||||||
|
|
||||||
setFilterDropdownSearchInput('');
|
setFilterDropdownSearchInput('');
|
||||||
}}
|
}}
|
||||||
LeftIcon={availableFilter.Icon}
|
LeftIcon={availableFilterDefinition.Icon}
|
||||||
text={availableFilter.label}
|
text={availableFilterDefinition.label}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
|
|||||||
@ -2,16 +2,14 @@ import { ChangeEvent } from 'react';
|
|||||||
|
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
|
|
||||||
import { useRemoveFilter } from '../../../../views/hooks/useRemoveFilter';
|
|
||||||
import { useUpsertFilter } from '../../../../views/hooks/useUpsertFilter';
|
|
||||||
import { useFilter } from '../hooks/useFilter';
|
import { useFilter } from '../hooks/useFilter';
|
||||||
|
|
||||||
export const FilterDropdownNumberSearchInput = () => {
|
export const FilterDropdownNumberSearchInput = () => {
|
||||||
const { selectedOperandInDropdown, filterDefinitionUsedInDropdown } =
|
const {
|
||||||
useFilter();
|
selectedOperandInDropdown,
|
||||||
|
filterDefinitionUsedInDropdown,
|
||||||
const upsertFilter = useUpsertFilter();
|
selectFilter,
|
||||||
const removeFilter = useRemoveFilter();
|
} = useFilter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
@ -21,17 +19,13 @@ export const FilterDropdownNumberSearchInput = () => {
|
|||||||
type="number"
|
type="number"
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
if (event.target.value === '') {
|
selectFilter?.({
|
||||||
removeFilter(filterDefinitionUsedInDropdown.key);
|
fieldId: filterDefinitionUsedInDropdown.fieldId,
|
||||||
} else {
|
value: event.target.value,
|
||||||
upsertFilter({
|
operand: selectedOperandInDropdown,
|
||||||
key: filterDefinitionUsedInDropdown.key,
|
displayValue: event.target.value,
|
||||||
type: filterDefinitionUsedInDropdown.type,
|
definition: filterDefinitionUsedInDropdown,
|
||||||
value: event.target.value,
|
});
|
||||||
operand: selectedOperandInDropdown,
|
|
||||||
displayValue: event.target.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -2,9 +2,7 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
|||||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
|
|
||||||
import { useUpsertFilter } from '../../../../views/hooks/useUpsertFilter';
|
|
||||||
import { useFilter } from '../hooks/useFilter';
|
import { useFilter } from '../hooks/useFilter';
|
||||||
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
|
|
||||||
import { getOperandLabel } from '../utils/getOperandLabel';
|
import { getOperandLabel } from '../utils/getOperandLabel';
|
||||||
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
||||||
|
|
||||||
@ -14,27 +12,25 @@ export const FilterDropdownOperandSelect = () => {
|
|||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
isFilterDropdownOperandSelectUnfolded,
|
isFilterDropdownOperandSelectUnfolded,
|
||||||
setIsFilterDropdownOperandSelectUnfolded,
|
setIsFilterDropdownOperandSelectUnfolded,
|
||||||
|
selectedFilter,
|
||||||
|
selectFilter,
|
||||||
} = useFilter();
|
} = useFilter();
|
||||||
|
|
||||||
const operandsForFilterType = getOperandsForFilterType(
|
const operandsForFilterType = getOperandsForFilterType(
|
||||||
filterDefinitionUsedInDropdown?.type,
|
filterDefinitionUsedInDropdown?.type,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filterCurrentlyEdited = useFilterCurrentlyEdited();
|
|
||||||
|
|
||||||
const upsertFilter = useUpsertFilter();
|
|
||||||
|
|
||||||
const handleOperangeChange = (newOperand: ViewFilterOperand) => {
|
const handleOperangeChange = (newOperand: ViewFilterOperand) => {
|
||||||
setSelectedOperandInDropdown(newOperand);
|
setSelectedOperandInDropdown(newOperand);
|
||||||
setIsFilterDropdownOperandSelectUnfolded(false);
|
setIsFilterDropdownOperandSelectUnfolded(false);
|
||||||
|
|
||||||
if (filterDefinitionUsedInDropdown && filterCurrentlyEdited) {
|
if (filterDefinitionUsedInDropdown && selectedFilter) {
|
||||||
upsertFilter({
|
selectFilter?.({
|
||||||
key: filterCurrentlyEdited.key,
|
fieldId: selectedFilter.fieldId,
|
||||||
displayValue: filterCurrentlyEdited.displayValue,
|
displayValue: selectedFilter.displayValue,
|
||||||
operand: newOperand,
|
operand: newOperand,
|
||||||
type: filterCurrentlyEdited.type,
|
value: selectedFilter.value,
|
||||||
value: filterCurrentlyEdited.value,
|
definition: filterDefinitionUsedInDropdown,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,10 +2,7 @@ import { ChangeEvent } from 'react';
|
|||||||
|
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
|
|
||||||
import { useRemoveFilter } from '../../../../views/hooks/useRemoveFilter';
|
|
||||||
import { useUpsertFilter } from '../../../../views/hooks/useUpsertFilter';
|
|
||||||
import { useFilter } from '../hooks/useFilter';
|
import { useFilter } from '../hooks/useFilter';
|
||||||
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
|
|
||||||
|
|
||||||
export const FilterDropdownTextSearchInput = () => {
|
export const FilterDropdownTextSearchInput = () => {
|
||||||
const {
|
const {
|
||||||
@ -13,13 +10,10 @@ export const FilterDropdownTextSearchInput = () => {
|
|||||||
selectedOperandInDropdown,
|
selectedOperandInDropdown,
|
||||||
filterDropdownSearchInput,
|
filterDropdownSearchInput,
|
||||||
setFilterDropdownSearchInput,
|
setFilterDropdownSearchInput,
|
||||||
|
selectedFilter,
|
||||||
|
selectFilter,
|
||||||
} = useFilter();
|
} = useFilter();
|
||||||
|
|
||||||
const upsertFilter = useUpsertFilter();
|
|
||||||
const removeFilter = useRemoveFilter();
|
|
||||||
|
|
||||||
const filterCurrentlyEdited = useFilterCurrentlyEdited();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
@ -27,21 +21,17 @@ export const FilterDropdownTextSearchInput = () => {
|
|||||||
autoFocus
|
autoFocus
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
value={filterCurrentlyEdited?.value ?? filterDropdownSearchInput}
|
value={selectedFilter?.value ?? filterDropdownSearchInput}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilterDropdownSearchInput(event.target.value);
|
setFilterDropdownSearchInput(event.target.value);
|
||||||
|
|
||||||
if (event.target.value === '') {
|
selectFilter?.({
|
||||||
removeFilter(filterDefinitionUsedInDropdown.key);
|
fieldId: filterDefinitionUsedInDropdown.fieldId,
|
||||||
} else {
|
value: event.target.value,
|
||||||
upsertFilter({
|
operand: selectedOperandInDropdown,
|
||||||
key: filterDefinitionUsedInDropdown.key,
|
displayValue: event.target.value,
|
||||||
type: filterDefinitionUsedInDropdown.type,
|
definition: filterDefinitionUsedInDropdown,
|
||||||
value: event.target.value,
|
});
|
||||||
operand: selectedOperandInDropdown,
|
|
||||||
displayValue: event.target.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -21,13 +21,13 @@ export const SingleEntityFilterDropdownButton = ({
|
|||||||
hotkeyScope: HotkeyScope;
|
hotkeyScope: HotkeyScope;
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
availableFilters,
|
availableFilterDefinitions,
|
||||||
selectedFilters,
|
selectedFilter,
|
||||||
setFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
} = useFilter();
|
} = useFilter();
|
||||||
|
|
||||||
const availableFilter = availableFilters[0];
|
const availableFilter = availableFilterDefinitions[0];
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setFilterDefinitionUsedInDropdown(availableFilter);
|
setFilterDefinitionUsedInDropdown(availableFilter);
|
||||||
@ -48,11 +48,11 @@ export const SingleEntityFilterDropdownButton = ({
|
|||||||
dropdownOffset={{ x: 0, y: -28 }}
|
dropdownOffset={{ x: 0, y: -28 }}
|
||||||
clickableComponent={
|
clickableComponent={
|
||||||
<StyledHeaderDropdownButton>
|
<StyledHeaderDropdownButton>
|
||||||
{selectedFilters[0] ? (
|
{selectedFilter ? (
|
||||||
<GenericEntityFilterChip
|
<GenericEntityFilterChip
|
||||||
filter={selectedFilters[0]}
|
filter={selectedFilter}
|
||||||
Icon={
|
Icon={
|
||||||
selectedFilters[0].operand === ViewFilterOperand.IsNotNull
|
selectedFilter.operand === ViewFilterOperand.IsNotNull
|
||||||
? availableFilter.SelectAllIcon
|
? availableFilter.SelectAllIcon
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
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 { FilterScopeInternalContext } from '../scopes/scope-internal-context/FilterScopeInternalContext';
|
import { FilterScopeInternalContext } from '../scopes/scope-internal-context/FilterScopeInternalContext';
|
||||||
|
import { Filter } from '../types/Filter';
|
||||||
|
|
||||||
import { useFilterStates } from './useFilterStates';
|
import { useFilterStates } from './useFilterStates';
|
||||||
|
|
||||||
@ -14,8 +18,8 @@ export const useFilter = (props?: UseFilterProps) => {
|
|||||||
props?.filterScopeId,
|
props?.filterScopeId,
|
||||||
);
|
);
|
||||||
const {
|
const {
|
||||||
availableFilters,
|
availableFilterDefinitions,
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
filterDefinitionUsedInDropdown,
|
filterDefinitionUsedInDropdown,
|
||||||
setFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
filterDropdownSearchInput,
|
filterDropdownSearchInput,
|
||||||
@ -26,16 +30,28 @@ export const useFilter = (props?: UseFilterProps) => {
|
|||||||
setIsFilterDropdownOperandSelectUnfolded,
|
setIsFilterDropdownOperandSelectUnfolded,
|
||||||
isFilterDropdownUnfolded,
|
isFilterDropdownUnfolded,
|
||||||
setIsFilterDropdownUnfolded,
|
setIsFilterDropdownUnfolded,
|
||||||
selectedFilters,
|
selectedFilter,
|
||||||
setSelectedFilters,
|
setSelectedFilter,
|
||||||
selectedOperandInDropdown,
|
selectedOperandInDropdown,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
} = useFilterStates(scopeId);
|
} = useFilterStates(scopeId);
|
||||||
|
|
||||||
|
const { onFilterSelect } = useScopeInternalContextOrThrow(
|
||||||
|
FilterScopeInternalContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const selectFilter = useCallback(
|
||||||
|
(filter: Filter) => {
|
||||||
|
setSelectedFilter(filter);
|
||||||
|
onFilterSelect?.(filter);
|
||||||
|
},
|
||||||
|
[setSelectedFilter, onFilterSelect],
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
scopeId,
|
scopeId,
|
||||||
availableFilters,
|
availableFilterDefinitions,
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
filterDefinitionUsedInDropdown,
|
filterDefinitionUsedInDropdown,
|
||||||
setFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
filterDropdownSearchInput,
|
filterDropdownSearchInput,
|
||||||
@ -46,9 +62,10 @@ export const useFilter = (props?: UseFilterProps) => {
|
|||||||
setIsFilterDropdownOperandSelectUnfolded,
|
setIsFilterDropdownOperandSelectUnfolded,
|
||||||
isFilterDropdownUnfolded,
|
isFilterDropdownUnfolded,
|
||||||
setIsFilterDropdownUnfolded,
|
setIsFilterDropdownUnfolded,
|
||||||
selectedFilters,
|
selectedFilter,
|
||||||
setSelectedFilters,
|
setSelectedFilter,
|
||||||
selectedOperandInDropdown,
|
selectedOperandInDropdown,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
|
selectFilter,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
|
|
||||||
import { useFilter } from './useFilter';
|
|
||||||
|
|
||||||
export const useFilterCurrentlyEdited = () => {
|
|
||||||
const { selectedFilters, filterDefinitionUsedInDropdown } = useFilter();
|
|
||||||
|
|
||||||
return useMemo(() => {
|
|
||||||
return selectedFilters?.find(
|
|
||||||
(filter) => filter.key === filterDefinitionUsedInDropdown?.key,
|
|
||||||
);
|
|
||||||
}, [filterDefinitionUsedInDropdown?.key, selectedFilters]);
|
|
||||||
};
|
|
||||||
@ -1,19 +1,17 @@
|
|||||||
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
|
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
|
||||||
|
|
||||||
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
|
import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState';
|
||||||
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
|
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
|
||||||
import { filterDropdownSearchInputScopedState } from '../states/filterDropdownSearchInputScopedState';
|
import { filterDropdownSearchInputScopedState } from '../states/filterDropdownSearchInputScopedState';
|
||||||
import { filterDropdownSelectedEntityIdScopedState } from '../states/filterDropdownSelectedEntityIdScopedState';
|
import { filterDropdownSelectedEntityIdScopedState } from '../states/filterDropdownSelectedEntityIdScopedState';
|
||||||
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
|
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
|
||||||
import { isFilterDropdownUnfoldedScopedState } from '../states/isFilterDropdownUnfoldedScopedState';
|
import { isFilterDropdownUnfoldedScopedState } from '../states/isFilterDropdownUnfoldedScopedState';
|
||||||
import { selectedFiltersScopedState } from '../states/selectedFiltersScopedState';
|
import { selectedFilterScopedState } from '../states/selectedFilterScopedState';
|
||||||
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
|
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
|
||||||
|
|
||||||
export const useFilterStates = (scopeId: string) => {
|
export const useFilterStates = (scopeId: string) => {
|
||||||
const [availableFilters, setAvailableFilters] = useRecoilScopedStateV2(
|
const [availableFilterDefinitions, setAvailableFilterDefinitions] =
|
||||||
availableFiltersScopedState,
|
useRecoilScopedStateV2(availableFilterDefinitionsScopedState, scopeId);
|
||||||
scopeId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [filterDefinitionUsedInDropdown, setFilterDefinitionUsedInDropdown] =
|
const [filterDefinitionUsedInDropdown, setFilterDefinitionUsedInDropdown] =
|
||||||
useRecoilScopedStateV2(filterDefinitionUsedInDropdownScopedState, scopeId);
|
useRecoilScopedStateV2(filterDefinitionUsedInDropdownScopedState, scopeId);
|
||||||
@ -35,8 +33,8 @@ export const useFilterStates = (scopeId: string) => {
|
|||||||
const [isFilterDropdownUnfolded, setIsFilterDropdownUnfolded] =
|
const [isFilterDropdownUnfolded, setIsFilterDropdownUnfolded] =
|
||||||
useRecoilScopedStateV2(isFilterDropdownUnfoldedScopedState, scopeId);
|
useRecoilScopedStateV2(isFilterDropdownUnfoldedScopedState, scopeId);
|
||||||
|
|
||||||
const [selectedFilters, setSelectedFilters] = useRecoilScopedStateV2(
|
const [selectedFilter, setSelectedFilter] = useRecoilScopedStateV2(
|
||||||
selectedFiltersScopedState,
|
selectedFilterScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -44,8 +42,8 @@ export const useFilterStates = (scopeId: string) => {
|
|||||||
useRecoilScopedStateV2(selectedOperandInDropdownScopedState, scopeId);
|
useRecoilScopedStateV2(selectedOperandInDropdownScopedState, scopeId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
availableFilters,
|
availableFilterDefinitions,
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
filterDefinitionUsedInDropdown,
|
filterDefinitionUsedInDropdown,
|
||||||
setFilterDefinitionUsedInDropdown,
|
setFilterDefinitionUsedInDropdown,
|
||||||
filterDropdownSearchInput,
|
filterDropdownSearchInput,
|
||||||
@ -56,8 +54,8 @@ export const useFilterStates = (scopeId: string) => {
|
|||||||
setIsFilterDropdownOperandSelectUnfolded,
|
setIsFilterDropdownOperandSelectUnfolded,
|
||||||
isFilterDropdownUnfolded,
|
isFilterDropdownUnfolded,
|
||||||
setIsFilterDropdownUnfolded,
|
setIsFilterDropdownUnfolded,
|
||||||
selectedFilters,
|
selectedFilter,
|
||||||
setSelectedFilters,
|
setSelectedFilter,
|
||||||
selectedOperandInDropdown,
|
selectedOperandInDropdown,
|
||||||
setSelectedOperandInDropdown,
|
setSelectedOperandInDropdown,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,25 +2,31 @@ import { ReactNode } from 'react';
|
|||||||
|
|
||||||
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
||||||
|
|
||||||
|
import { Filter } from '../types/Filter';
|
||||||
|
|
||||||
import { FilterScopeInitEffect } from './init-effect/FilterScopeInitEffect';
|
import { FilterScopeInitEffect } from './init-effect/FilterScopeInitEffect';
|
||||||
import { FilterScopeInternalContext } from './scope-internal-context/FilterScopeInternalContext';
|
import { FilterScopeInternalContext } from './scope-internal-context/FilterScopeInternalContext';
|
||||||
|
|
||||||
type FilterScopeProps = {
|
type FilterScopeProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
filterScopeId: string;
|
filterScopeId: string;
|
||||||
availableFilters?: FilterDefinition[];
|
availableFilterDefinitions?: FilterDefinition[];
|
||||||
|
onFilterSelect?: (filter: Filter) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FilterScope = ({
|
export const FilterScope = ({
|
||||||
children,
|
children,
|
||||||
filterScopeId,
|
filterScopeId,
|
||||||
availableFilters,
|
availableFilterDefinitions,
|
||||||
|
onFilterSelect,
|
||||||
}: FilterScopeProps) => {
|
}: FilterScopeProps) => {
|
||||||
return (
|
return (
|
||||||
<FilterScopeInternalContext.Provider value={{ scopeId: filterScopeId }}>
|
<FilterScopeInternalContext.Provider
|
||||||
|
value={{ scopeId: filterScopeId, onFilterSelect }}
|
||||||
|
>
|
||||||
<FilterScopeInitEffect
|
<FilterScopeInitEffect
|
||||||
filterScopeId={filterScopeId}
|
filterScopeId={filterScopeId}
|
||||||
availableFilters={availableFilters}
|
availableFilterDefinitions={availableFilterDefinitions}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</FilterScopeInternalContext.Provider>
|
</FilterScopeInternalContext.Provider>
|
||||||
|
|||||||
@ -6,20 +6,20 @@ import { useFilterStates } from '../../hooks/useFilterStates';
|
|||||||
|
|
||||||
type FilterScopeInitEffectProps = {
|
type FilterScopeInitEffectProps = {
|
||||||
filterScopeId: string;
|
filterScopeId: string;
|
||||||
availableFilters?: FilterDefinition[];
|
availableFilterDefinitions?: FilterDefinition[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FilterScopeInitEffect = ({
|
export const FilterScopeInitEffect = ({
|
||||||
filterScopeId,
|
filterScopeId,
|
||||||
availableFilters,
|
availableFilterDefinitions,
|
||||||
}: FilterScopeInitEffectProps) => {
|
}: FilterScopeInitEffectProps) => {
|
||||||
const { setAvailableFilters } = useFilterStates(filterScopeId);
|
const { setAvailableFilterDefinitions } = useFilterStates(filterScopeId);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (availableFilters) {
|
if (availableFilterDefinitions) {
|
||||||
setAvailableFilters(availableFilters);
|
setAvailableFilterDefinitions(availableFilterDefinitions);
|
||||||
}
|
}
|
||||||
}, [availableFilters, setAvailableFilters]);
|
}, [availableFilterDefinitions, setAvailableFilterDefinitions]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
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 FilterScopeInternalContextProps = ScopedStateKey & {
|
type FilterScopeInternalContextProps = ScopedStateKey & {
|
||||||
test?: string;
|
onFilterSelect?: (sort: Filter) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FilterScopeInternalContext =
|
export const FilterScopeInternalContext =
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
||||||
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
|
||||||
export const availableFiltersScopedState = createScopedState<
|
export const availableFilterDefinitionsScopedState = createScopedState<
|
||||||
FilterDefinition[]
|
FilterDefinition[]
|
||||||
>({
|
>({
|
||||||
key: 'availableFiltersScopedState',
|
key: 'availableFilterDefinitionsScopedState',
|
||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
});
|
});
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
|
||||||
|
import { Filter } from '../types/Filter';
|
||||||
|
|
||||||
|
export const selectedFilterScopedState = createScopedState<Filter | undefined>({
|
||||||
|
key: 'selectedFilterScopedState',
|
||||||
|
defaultValue: undefined,
|
||||||
|
});
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
|
||||||
|
|
||||||
import { Filter } from '../types/Filter';
|
|
||||||
|
|
||||||
export const selectedFiltersScopedState = createScopedState<Filter[]>({
|
|
||||||
key: 'selectedFiltersScopedState',
|
|
||||||
defaultValue: [],
|
|
||||||
});
|
|
||||||
@ -1,12 +1,12 @@
|
|||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
|
|
||||||
import { FilterType } from './FilterType';
|
import { FilterDefinition } from './FilterDefinition';
|
||||||
|
|
||||||
export type Filter = {
|
export type Filter = {
|
||||||
key: string;
|
fieldId: string;
|
||||||
type: FilterType;
|
|
||||||
value: string;
|
value: string;
|
||||||
displayValue: string;
|
displayValue: string;
|
||||||
displayAvatarUrl?: string;
|
displayAvatarUrl?: string;
|
||||||
operand: ViewFilterOperand;
|
operand: ViewFilterOperand;
|
||||||
|
definition: FilterDefinition;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
|||||||
import { FilterType } from './FilterType';
|
import { FilterType } from './FilterType';
|
||||||
|
|
||||||
export type FilterDefinition = {
|
export type FilterDefinition = {
|
||||||
key: string;
|
fieldId: string;
|
||||||
label: string;
|
label: string;
|
||||||
Icon: IconComponent;
|
Icon: IconComponent;
|
||||||
type: FilterType;
|
type: FilterType;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { FilterDefinition } from './FilterDefinition';
|
import { FilterDefinition } from './FilterDefinition';
|
||||||
|
|
||||||
export type FilterDefinitionByEntity<T> = FilterDefinition & {
|
export type FilterDefinitionByEntity<T> = FilterDefinition & {
|
||||||
key: keyof T;
|
fieldId: keyof T;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,28 +3,39 @@ import { QueryMode } from '~/generated/graphql';
|
|||||||
|
|
||||||
import { Filter } from '../types/Filter';
|
import { Filter } from '../types/Filter';
|
||||||
|
|
||||||
export const turnFilterIntoWhereClause = (filter: Filter) => {
|
type FilterToTurnIntoWhereClause = Omit<Filter, 'definition'> & {
|
||||||
|
definition: {
|
||||||
|
type: Filter['definition']['type'];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const turnFilterIntoWhereClause = (
|
||||||
|
filter: FilterToTurnIntoWhereClause | undefined,
|
||||||
|
) => {
|
||||||
|
if (!filter) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
switch (filter.operand) {
|
switch (filter.operand) {
|
||||||
case ViewFilterOperand.IsNotNull:
|
case ViewFilterOperand.IsNotNull:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
not: null,
|
not: null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
switch (filter.type) {
|
switch (filter.definition.type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
switch (filter.operand) {
|
switch (filter.operand) {
|
||||||
case ViewFilterOperand.Contains:
|
case ViewFilterOperand.Contains:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
contains: filter.value,
|
contains: filter.value,
|
||||||
mode: QueryMode.Insensitive,
|
mode: QueryMode.Insensitive,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
case ViewFilterOperand.DoesNotContain:
|
case ViewFilterOperand.DoesNotContain:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
not: {
|
not: {
|
||||||
contains: filter.value,
|
contains: filter.value,
|
||||||
mode: QueryMode.Insensitive,
|
mode: QueryMode.Insensitive,
|
||||||
@ -33,64 +44,64 @@ export const turnFilterIntoWhereClause = (filter: Filter) => {
|
|||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unknown operand ${filter.operand} for ${filter.type} filter`,
|
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case 'number':
|
case 'number':
|
||||||
switch (filter.operand) {
|
switch (filter.operand) {
|
||||||
case ViewFilterOperand.GreaterThan:
|
case ViewFilterOperand.GreaterThan:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
gte: parseFloat(filter.value),
|
gte: parseFloat(filter.value),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
case ViewFilterOperand.LessThan:
|
case ViewFilterOperand.LessThan:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
lte: parseFloat(filter.value),
|
lte: parseFloat(filter.value),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unknown operand ${filter.operand} for ${filter.type} filter`,
|
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case 'date':
|
case 'date':
|
||||||
switch (filter.operand) {
|
switch (filter.operand) {
|
||||||
case ViewFilterOperand.GreaterThan:
|
case ViewFilterOperand.GreaterThan:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
gte: filter.value,
|
gte: filter.value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
case ViewFilterOperand.LessThan:
|
case ViewFilterOperand.LessThan:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
lte: filter.value,
|
lte: filter.value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unknown operand ${filter.operand} for ${filter.type} filter`,
|
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case 'entity':
|
case 'entity':
|
||||||
switch (filter.operand) {
|
switch (filter.operand) {
|
||||||
case ViewFilterOperand.Is:
|
case ViewFilterOperand.Is:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
equals: filter.value,
|
equals: filter.value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
case ViewFilterOperand.IsNot:
|
case ViewFilterOperand.IsNot:
|
||||||
return {
|
return {
|
||||||
[filter.key]: {
|
[filter.fieldId]: {
|
||||||
not: { equals: filter.value },
|
not: { equals: filter.value },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unknown operand ${filter.operand} for ${filter.type} filter`,
|
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export const SortDropdownButton = ({
|
|||||||
setSelectedSortDirection('asc');
|
setSelectedSortDirection('asc');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { availableSorts, onSortAdd, isSortSelected } = useSort();
|
const { availableSortDefinitions, onSortSelect, isSortSelected } = useSort();
|
||||||
|
|
||||||
const { toggleDropdown } = useDropdown({
|
const { toggleDropdown } = useDropdown({
|
||||||
dropdownScopeId: SortDropdownId,
|
dropdownScopeId: SortDropdownId,
|
||||||
@ -48,8 +48,8 @@ export const SortDropdownButton = ({
|
|||||||
|
|
||||||
const handleAddSort = (selectedSortDefinition: SortDefinition) => {
|
const handleAddSort = (selectedSortDefinition: SortDefinition) => {
|
||||||
toggleDropdown();
|
toggleDropdown();
|
||||||
onSortAdd?.({
|
onSortSelect?.({
|
||||||
key: selectedSortDefinition.key,
|
fieldId: selectedSortDefinition.fieldId,
|
||||||
direction: selectedSortDirection,
|
direction: selectedSortDirection,
|
||||||
definition: selectedSortDefinition,
|
definition: selectedSortDefinition,
|
||||||
});
|
});
|
||||||
@ -96,7 +96,7 @@ export const SortDropdownButton = ({
|
|||||||
</DropdownMenuHeader>
|
</DropdownMenuHeader>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
{availableSorts.map((availableSort, index) => (
|
{availableSortDefinitions.map((availableSort, index) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
testId={`select-sort-${index}`}
|
testId={`select-sort-${index}`}
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@ -15,22 +15,22 @@ export const useSort = (props?: UseSortProps) => {
|
|||||||
props?.sortScopeId,
|
props?.sortScopeId,
|
||||||
);
|
);
|
||||||
const {
|
const {
|
||||||
availableSorts,
|
availableSortDefinitions,
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
isSortSelected,
|
isSortSelected,
|
||||||
setIsSortSelected,
|
setIsSortSelected,
|
||||||
} = useSortStates(scopeId);
|
} = useSortStates(scopeId);
|
||||||
|
|
||||||
const { onSortAdd } = useScopeInternalContextOrThrow(
|
const { onSortSelect } = useScopeInternalContextOrThrow(
|
||||||
SortScopeInternalContext,
|
SortScopeInternalContext,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onSortAdd,
|
onSortSelect,
|
||||||
scopeId,
|
scopeId,
|
||||||
availableSorts,
|
availableSortDefinitions,
|
||||||
isSortSelected,
|
isSortSelected,
|
||||||
setIsSortSelected,
|
setIsSortSelected,
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,13 +1,11 @@
|
|||||||
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
|
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
|
||||||
import { availableSortsScopedState } from '@/views/states/availableSortsScopedState';
|
import { availableSortDefinitionsScopedState } from '@/views/states/availableSortDefinitionsScopedState';
|
||||||
|
|
||||||
import { isSortSelectedScopedState } from '../states/isSortSelectedScopedState';
|
import { isSortSelectedScopedState } from '../states/isSortSelectedScopedState';
|
||||||
|
|
||||||
export const useSortStates = (scopeId: string) => {
|
export const useSortStates = (scopeId: string) => {
|
||||||
const [availableSorts, setAvailableSorts] = useRecoilScopedStateV2(
|
const [availableSortDefinitions, setAvailableSortDefinitions] =
|
||||||
availableSortsScopedState,
|
useRecoilScopedStateV2(availableSortDefinitionsScopedState, scopeId);
|
||||||
scopeId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [isSortSelected, setIsSortSelected] = useRecoilScopedStateV2(
|
const [isSortSelected, setIsSortSelected] = useRecoilScopedStateV2(
|
||||||
isSortSelectedScopedState,
|
isSortSelectedScopedState,
|
||||||
@ -15,8 +13,8 @@ export const useSortStates = (scopeId: string) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
availableSorts,
|
availableSortDefinitions,
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
isSortSelected,
|
isSortSelected,
|
||||||
setIsSortSelected,
|
setIsSortSelected,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,23 +9,23 @@ import { SortScopeInternalContext } from './scope-internal-context/SortScopeInte
|
|||||||
type SortScopeProps = {
|
type SortScopeProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
sortScopeId: string;
|
sortScopeId: string;
|
||||||
availableSorts?: SortDefinition[];
|
availableSortDefinitions?: SortDefinition[];
|
||||||
onSortAdd?: (sort: Sort) => void | Promise<void>;
|
onSortSelect?: (sort: Sort) => void | Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SortScope = ({
|
export const SortScope = ({
|
||||||
children,
|
children,
|
||||||
sortScopeId,
|
sortScopeId,
|
||||||
availableSorts,
|
availableSortDefinitions,
|
||||||
onSortAdd,
|
onSortSelect,
|
||||||
}: SortScopeProps) => {
|
}: SortScopeProps) => {
|
||||||
return (
|
return (
|
||||||
<SortScopeInternalContext.Provider
|
<SortScopeInternalContext.Provider
|
||||||
value={{ scopeId: sortScopeId, onSortAdd }}
|
value={{ scopeId: sortScopeId, onSortSelect }}
|
||||||
>
|
>
|
||||||
<SortScopeInitEffect
|
<SortScopeInitEffect
|
||||||
sortScopeId={sortScopeId}
|
sortScopeId={sortScopeId}
|
||||||
availableSorts={availableSorts}
|
availableSortDefinitions={availableSortDefinitions}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</SortScopeInternalContext.Provider>
|
</SortScopeInternalContext.Provider>
|
||||||
|
|||||||
@ -6,20 +6,20 @@ import { useSortStates } from '../../hooks/useSortStates';
|
|||||||
|
|
||||||
type SortScopeInitEffectProps = {
|
type SortScopeInitEffectProps = {
|
||||||
sortScopeId: string;
|
sortScopeId: string;
|
||||||
availableSorts?: SortDefinition[];
|
availableSortDefinitions?: SortDefinition[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SortScopeInitEffect = ({
|
export const SortScopeInitEffect = ({
|
||||||
sortScopeId,
|
sortScopeId,
|
||||||
availableSorts,
|
availableSortDefinitions,
|
||||||
}: SortScopeInitEffectProps) => {
|
}: SortScopeInitEffectProps) => {
|
||||||
const { setAvailableSorts } = useSortStates(sortScopeId);
|
const { setAvailableSortDefinitions } = useSortStates(sortScopeId);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (availableSorts) {
|
if (availableSortDefinitions) {
|
||||||
setAvailableSorts(availableSorts);
|
setAvailableSortDefinitions(availableSortDefinitions);
|
||||||
}
|
}
|
||||||
}, [availableSorts, setAvailableSorts]);
|
}, [availableSortDefinitions, setAvailableSortDefinitions]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,11 +2,9 @@ import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/type
|
|||||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||||
|
|
||||||
import { Sort } from '../../types/Sort';
|
import { Sort } from '../../types/Sort';
|
||||||
import { SortDefinition } from '../../types/SortDefinition';
|
|
||||||
|
|
||||||
type SortScopeInternalContextProps = ScopedStateKey & {
|
type SortScopeInternalContextProps = ScopedStateKey & {
|
||||||
onSortAdd?: (sort: Sort) => void;
|
onSortSelect?: (sort: Sort) => void;
|
||||||
availableSorts?: SortDefinition[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SortScopeInternalContext =
|
export const SortScopeInternalContext =
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { SortDefinition } from './SortDefinition';
|
|||||||
import { SortDirection } from './SortDirection';
|
import { SortDirection } from './SortDirection';
|
||||||
|
|
||||||
export type Sort = {
|
export type Sort = {
|
||||||
key: string;
|
fieldId: string;
|
||||||
direction: SortDirection;
|
direction: SortDirection;
|
||||||
definition: SortDefinition;
|
definition: SortDefinition;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
|||||||
import { SortDirection } from './SortDirection';
|
import { SortDirection } from './SortDirection';
|
||||||
|
|
||||||
export type SortDefinition = {
|
export type SortDefinition = {
|
||||||
key: string;
|
fieldId: string;
|
||||||
label: string;
|
label: string;
|
||||||
Icon?: IconComponent;
|
Icon?: IconComponent;
|
||||||
getOrderByTemplate?: (direction: SortDirection) => any[];
|
getOrderByTemplate?: (direction: SortDirection) => any[];
|
||||||
|
|||||||
@ -10,7 +10,7 @@ export const reduceSortsToOrderBy = (sorts: Sort[]): any[] =>
|
|||||||
if (sort.definition.getOrderByTemplate) {
|
if (sort.definition.getOrderByTemplate) {
|
||||||
return sort.definition.getOrderByTemplate(direction);
|
return sort.definition.getOrderByTemplate(direction);
|
||||||
} else {
|
} else {
|
||||||
return [{ [sort.definition.key]: direction }];
|
return [{ [sort.definition.fieldId]: direction }];
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.flat();
|
.flat();
|
||||||
|
|||||||
@ -2,8 +2,9 @@ import { useView } from '@/views/hooks/useView';
|
|||||||
|
|
||||||
import { Dropdown } from '../../dropdown/components/Dropdown';
|
import { Dropdown } from '../../dropdown/components/Dropdown';
|
||||||
import { DropdownScope } from '../../dropdown/scopes/DropdownScope';
|
import { DropdownScope } from '../../dropdown/scopes/DropdownScope';
|
||||||
import { BoardScopeIds } from '../types/enums/BoardScopeIds';
|
import { BoardOptionsHotkeyScope } from '../types/BoardOptionsHotkeyScope';
|
||||||
|
|
||||||
|
import { BoardOptionsDropdownId } from './constants/BoardOptionsDropdownId';
|
||||||
import { BoardOptionsDropdownButton } from './BoardOptionsDropdownButton';
|
import { BoardOptionsDropdownButton } from './BoardOptionsDropdownButton';
|
||||||
import {
|
import {
|
||||||
BoardOptionsDropdownContent,
|
BoardOptionsDropdownContent,
|
||||||
@ -12,26 +13,22 @@ import {
|
|||||||
|
|
||||||
type BoardOptionsDropdownProps = Pick<
|
type BoardOptionsDropdownProps = Pick<
|
||||||
BoardOptionsDropdownContentProps,
|
BoardOptionsDropdownContentProps,
|
||||||
'customHotkeyScope' | 'onStageAdd'
|
'onStageAdd'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const BoardOptionsDropdown = ({
|
export const BoardOptionsDropdown = ({
|
||||||
customHotkeyScope,
|
|
||||||
onStageAdd,
|
onStageAdd,
|
||||||
}: BoardOptionsDropdownProps) => {
|
}: BoardOptionsDropdownProps) => {
|
||||||
const { setViewEditMode } = useView();
|
const { setViewEditMode } = useView();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownScope dropdownScopeId={BoardScopeIds.OptionsDropdown}>
|
<DropdownScope dropdownScopeId={BoardOptionsDropdownId}>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
clickableComponent={<BoardOptionsDropdownButton />}
|
clickableComponent={<BoardOptionsDropdownButton />}
|
||||||
dropdownComponents={
|
dropdownComponents={
|
||||||
<BoardOptionsDropdownContent
|
<BoardOptionsDropdownContent onStageAdd={onStageAdd} />
|
||||||
customHotkeyScope={customHotkeyScope}
|
|
||||||
onStageAdd={onStageAdd}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
dropdownHotkeyScope={customHotkeyScope}
|
dropdownHotkeyScope={{ scope: BoardOptionsHotkeyScope.Dropdown }}
|
||||||
onClickOutside={() => setViewEditMode('none')}
|
onClickOutside={() => setViewEditMode('none')}
|
||||||
dropdownMenuWidth={170}
|
dropdownMenuWidth={170}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,12 +1,8 @@
|
|||||||
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 { BoardScopeIds } from '../types/enums/BoardScopeIds';
|
|
||||||
|
|
||||||
export const BoardOptionsDropdownButton = () => {
|
export const BoardOptionsDropdownButton = () => {
|
||||||
const { isDropdownOpen, toggleDropdown } = useDropdown({
|
const { isDropdownOpen, toggleDropdown } = useDropdown();
|
||||||
dropdownScopeId: BoardScopeIds.OptionsDropdown,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
toggleDropdown();
|
toggleDropdown();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useContext, useRef, useState } from 'react';
|
import { useContext, useRef, useState } from 'react';
|
||||||
import { useRecoilCallback, useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
@ -22,25 +22,20 @@ import { MenuItemNavigate } from '@/ui/navigation/menu-item/components/MenuItemN
|
|||||||
import { MenuItemToggle } from '@/ui/navigation/menu-item/components/MenuItemToggle';
|
import { MenuItemToggle } from '@/ui/navigation/menu-item/components/MenuItemToggle';
|
||||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
|
||||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
|
||||||
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
|
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
|
||||||
import { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { useViewInternalStates } from '@/views/hooks/useViewInternalStates';
|
import { useViewGetStates } from '@/views/hooks/useViewGetStates';
|
||||||
import { viewEditModeScopedState } from '@/views/states/viewEditModeScopedState';
|
|
||||||
|
|
||||||
import { useBoardCardFields } from '../hooks/useBoardCardFields';
|
import { useBoardCardFields } from '../hooks/useBoardCardFields';
|
||||||
import { boardCardFieldsScopedState } from '../states/boardCardFieldsScopedState';
|
|
||||||
import { boardColumnsState } from '../states/boardColumnsState';
|
import { boardColumnsState } from '../states/boardColumnsState';
|
||||||
import { isCompactViewEnabledState } from '../states/isCompactViewEnabledState';
|
import { isCompactViewEnabledState } from '../states/isCompactViewEnabledState';
|
||||||
import { savedBoardCardFieldsFamilyState } from '../states/savedBoardCardFieldsFamilyState';
|
|
||||||
import { hiddenBoardCardFieldsScopedSelector } from '../states/selectors/hiddenBoardCardFieldsScopedSelector';
|
import { hiddenBoardCardFieldsScopedSelector } from '../states/selectors/hiddenBoardCardFieldsScopedSelector';
|
||||||
import { visibleBoardCardFieldsScopedSelector } from '../states/selectors/visibleBoardCardFieldsScopedSelector';
|
import { visibleBoardCardFieldsScopedSelector } from '../states/selectors/visibleBoardCardFieldsScopedSelector';
|
||||||
import { BoardColumnDefinition } from '../types/BoardColumnDefinition';
|
import { BoardColumnDefinition } from '../types/BoardColumnDefinition';
|
||||||
|
import { BoardOptionsHotkeyScope } from '../types/BoardOptionsHotkeyScope';
|
||||||
|
|
||||||
export type BoardOptionsDropdownContentProps = {
|
export type BoardOptionsDropdownContentProps = {
|
||||||
customHotkeyScope: HotkeyScope;
|
|
||||||
onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
|
onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,15 +49,12 @@ type ColumnForCreate = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const BoardOptionsDropdownContent = ({
|
export const BoardOptionsDropdownContent = ({
|
||||||
customHotkeyScope,
|
|
||||||
onStageAdd,
|
onStageAdd,
|
||||||
}: BoardOptionsDropdownContentProps) => {
|
}: BoardOptionsDropdownContentProps) => {
|
||||||
const { setViewEditMode, createView, currentViewId } = useView();
|
const { setViewEditMode, handleViewNameSubmit } = useView();
|
||||||
const { viewEditMode, currentView } = useViewInternalStates();
|
const { viewEditMode, currentView } = useViewGetStates();
|
||||||
const { BoardRecoilScopeContext } = useContext(BoardContext);
|
const { BoardRecoilScopeContext } = useContext(BoardContext);
|
||||||
|
|
||||||
const boardRecoilScopeId = useRecoilScopeId(BoardRecoilScopeContext);
|
|
||||||
|
|
||||||
const stageInputRef = useRef<HTMLInputElement>(null);
|
const stageInputRef = useRef<HTMLInputElement>(null);
|
||||||
const viewEditInputRef = useRef<HTMLInputElement>(null);
|
const viewEditInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
@ -104,31 +96,6 @@ export const BoardOptionsDropdownContent = ({
|
|||||||
onStageAdd?.(columnToCreate);
|
onStageAdd?.(columnToCreate);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleViewNameSubmit = useRecoilCallback(
|
|
||||||
({ set, snapshot }) =>
|
|
||||||
async () => {
|
|
||||||
const viewEditMode = snapshot
|
|
||||||
.getLoadable(viewEditModeScopedState({ scopeId: boardRecoilScopeId }))
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
if (!viewEditMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const boardCardFields = await snapshot.getPromise(
|
|
||||||
boardCardFieldsScopedState(boardRecoilScopeId),
|
|
||||||
);
|
|
||||||
const isCreateMode = viewEditMode === 'create';
|
|
||||||
const name = viewEditInputRef.current?.value;
|
|
||||||
|
|
||||||
if (isCreateMode && name) {
|
|
||||||
await createView(name);
|
|
||||||
set(savedBoardCardFieldsFamilyState(currentViewId), boardCardFields);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[boardRecoilScopeId, createView, currentViewId],
|
|
||||||
);
|
|
||||||
|
|
||||||
const resetMenu = () => setCurrentMenu(undefined);
|
const resetMenu = () => setCurrentMenu(undefined);
|
||||||
|
|
||||||
const handleMenuNavigate = (menu: BoardOptionsMenu) => {
|
const handleMenuNavigate = (menu: BoardOptionsMenu) => {
|
||||||
@ -146,43 +113,39 @@ export const BoardOptionsDropdownContent = ({
|
|||||||
setViewEditMode('none');
|
setViewEditMode('none');
|
||||||
closeDropdown();
|
closeDropdown();
|
||||||
},
|
},
|
||||||
customHotkeyScope.scope,
|
BoardOptionsHotkeyScope.Dropdown,
|
||||||
);
|
);
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
Key.Enter,
|
Key.Enter,
|
||||||
() => {
|
() => {
|
||||||
|
const name = viewEditInputRef.current?.value;
|
||||||
|
resetMenu();
|
||||||
|
setViewEditMode('none');
|
||||||
|
closeDropdown();
|
||||||
handleStageSubmit();
|
handleStageSubmit();
|
||||||
handleViewNameSubmit();
|
handleViewNameSubmit(name);
|
||||||
closeDropdown();
|
closeDropdown();
|
||||||
},
|
},
|
||||||
customHotkeyScope.scope,
|
BoardOptionsHotkeyScope.Dropdown,
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!currentMenu && (
|
{!currentMenu && (
|
||||||
<>
|
<>
|
||||||
{viewEditMode && (
|
<DropdownMenuInput
|
||||||
<DropdownMenuInput
|
ref={viewEditInputRef}
|
||||||
ref={viewEditInputRef}
|
autoFocus={viewEditMode !== 'none'}
|
||||||
autoFocus={viewEditMode !== 'none'}
|
placeholder={
|
||||||
placeholder={
|
viewEditMode === 'create'
|
||||||
viewEditMode === 'create'
|
? 'New view'
|
||||||
? 'New view'
|
: viewEditMode === 'edit'
|
||||||
: viewEditMode === 'edit'
|
? 'View name'
|
||||||
? 'View name'
|
: ''
|
||||||
: ''
|
}
|
||||||
}
|
defaultValue={viewEditMode === 'create' ? '' : currentView?.name}
|
||||||
defaultValue={
|
/>
|
||||||
viewEditMode === 'create'
|
|
||||||
? ''
|
|
||||||
: viewEditMode === 'edit'
|
|
||||||
? currentView?.name
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
<MenuItemNavigate
|
<MenuItemNavigate
|
||||||
|
|||||||
@ -40,6 +40,8 @@ export type EntityBoardProps = {
|
|||||||
const StyledWrapper = styled.div`
|
const StyledWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
// We should either apply the constant all caps case or maybe define a more general enum to store those ids ?
|
||||||
|
export const BoardOptionsDropdownId = 'board-options';
|
||||||
@ -7,6 +7,6 @@ import { PipelineProgress } from '~/generated/graphql';
|
|||||||
export type BoardOptions = {
|
export type BoardOptions = {
|
||||||
newCardComponent: React.ReactNode;
|
newCardComponent: React.ReactNode;
|
||||||
CardComponent: ComponentType;
|
CardComponent: ComponentType;
|
||||||
filters: FilterDefinitionByEntity<PipelineProgress>[];
|
filterDefinitions: FilterDefinitionByEntity<PipelineProgress>[];
|
||||||
sorts: SortDefinition[];
|
sortDefinitions: SortDefinition[];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
export enum BoardScopeIds {
|
|
||||||
OptionsDropdown = 'board-options',
|
|
||||||
}
|
|
||||||
@ -10,7 +10,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 { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
|
|
||||||
import { useViewInternalStates } from '../hooks/useViewInternalStates';
|
import { useViewGetStates } from '../hooks/useViewGetStates';
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@ -28,7 +28,7 @@ export const UpdateViewButtonGroup = ({
|
|||||||
}: UpdateViewButtonGroupProps) => {
|
}: UpdateViewButtonGroupProps) => {
|
||||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||||
const { updateCurrentView, setViewEditMode } = useView();
|
const { updateCurrentView, setViewEditMode } = useView();
|
||||||
const { canPersistFilters, canPersistSorts } = useViewInternalStates();
|
const { canPersistFilters, canPersistSorts } = useViewGetStates();
|
||||||
|
|
||||||
const canPersistView = canPersistFilters || canPersistSorts;
|
const canPersistView = canPersistFilters || canPersistSorts;
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ 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 { useView } from '../hooks/useView';
|
import { useView } from '../hooks/useView';
|
||||||
import { useViewInternalStates } from '../hooks/useViewInternalStates';
|
import { useViewGetStates } from '../hooks/useViewGetStates';
|
||||||
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
|
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
|
||||||
|
|
||||||
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
|
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
|
||||||
@ -31,18 +31,20 @@ export const ViewBar = ({
|
|||||||
const { openDropdown: openOptionsDropdownButton } = useDropdown({
|
const { openDropdown: openOptionsDropdownButton } = useDropdown({
|
||||||
dropdownScopeId: optionsDropdownScopeId,
|
dropdownScopeId: optionsDropdownScopeId,
|
||||||
});
|
});
|
||||||
const { upsertViewSort } = useView();
|
const { upsertViewSort, upsertViewFilter } = useView();
|
||||||
const { availableFilters, availableSorts } = useViewInternalStates();
|
const { availableFilterDefinitions, availableSortDefinitions } =
|
||||||
|
useViewGetStates();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterScope
|
<FilterScope
|
||||||
filterScopeId="view-filter"
|
filterScopeId="view-filter"
|
||||||
availableFilters={availableFilters}
|
availableFilterDefinitions={availableFilterDefinitions}
|
||||||
|
onFilterSelect={upsertViewFilter}
|
||||||
>
|
>
|
||||||
<SortScope
|
<SortScope
|
||||||
sortScopeId="view-sort"
|
sortScopeId="view-sort"
|
||||||
availableSorts={availableSorts}
|
availableSortDefinitions={availableSortDefinitions}
|
||||||
onSortAdd={upsertViewSort}
|
onSortSelect={upsertViewSort}
|
||||||
>
|
>
|
||||||
<ViewBarEffect />
|
<ViewBarEffect />
|
||||||
<TopBar
|
<TopBar
|
||||||
@ -51,6 +53,7 @@ export const ViewBar = ({
|
|||||||
<ViewsDropdownButton
|
<ViewsDropdownButton
|
||||||
onViewEditModeChange={openOptionsDropdownButton}
|
onViewEditModeChange={openOptionsDropdownButton}
|
||||||
hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
|
hotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
|
||||||
|
optionsDropdownScopeId={optionsDropdownScopeId}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
displayBottomBorder={false}
|
displayBottomBorder={false}
|
||||||
|
|||||||
@ -5,9 +5,8 @@ import { AddFilterFromDropdownButton } from '@/ui/data/filter/components/AddFilt
|
|||||||
import { getOperandLabelShort } from '@/ui/data/filter/utils/getOperandLabel';
|
import { getOperandLabelShort } from '@/ui/data/filter/utils/getOperandLabel';
|
||||||
import { IconArrowDown, IconArrowUp } from '@/ui/display/icon/index';
|
import { IconArrowDown, IconArrowUp } from '@/ui/display/icon/index';
|
||||||
|
|
||||||
import { useRemoveFilter } from '../hooks/useRemoveFilter';
|
|
||||||
import { useView } from '../hooks/useView';
|
import { useView } from '../hooks/useView';
|
||||||
import { useViewInternalStates } from '../hooks/useViewInternalStates';
|
import { useViewGetStates } from '../hooks/useViewGetStates';
|
||||||
|
|
||||||
import SortOrFilterChip from './SortOrFilterChip';
|
import SortOrFilterChip from './SortOrFilterChip';
|
||||||
|
|
||||||
@ -90,43 +89,23 @@ export const ViewBarDetails = ({
|
|||||||
}: ViewBarDetailsProps) => {
|
}: ViewBarDetailsProps) => {
|
||||||
const {
|
const {
|
||||||
currentViewSorts,
|
currentViewSorts,
|
||||||
setCurrentViewSorts,
|
|
||||||
availableFilters,
|
|
||||||
currentViewFilters,
|
currentViewFilters,
|
||||||
canPersistFilters,
|
canPersistFilters,
|
||||||
canPersistSorts,
|
canPersistSorts,
|
||||||
isViewBarExpanded,
|
isViewBarExpanded,
|
||||||
} = useViewInternalStates();
|
} = useViewGetStates();
|
||||||
|
|
||||||
const { resetViewBar } = useView();
|
const { resetViewBar, removeViewSort, removeViewFilter } = useView();
|
||||||
|
|
||||||
const canPersistView = canPersistFilters || canPersistSorts;
|
const canPersistView = canPersistFilters || canPersistSorts;
|
||||||
|
|
||||||
const filtersWithDefinition = currentViewFilters?.map((filter) => {
|
|
||||||
const filterDefinition = availableFilters.find((availableFilter) => {
|
|
||||||
return availableFilter.key === filter.key;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...filter,
|
|
||||||
...filterDefinition,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const removeFilter = useRemoveFilter();
|
|
||||||
|
|
||||||
const handleCancelClick = () => {
|
const handleCancelClick = () => {
|
||||||
resetViewBar();
|
resetViewBar();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSortRemove = (sortKey: string) =>
|
|
||||||
setCurrentViewSorts?.((previousSorts) =>
|
|
||||||
previousSorts.filter((sort) => sort.key !== sortKey),
|
|
||||||
);
|
|
||||||
|
|
||||||
const shouldExpandViewBar =
|
const shouldExpandViewBar =
|
||||||
canPersistView ||
|
canPersistView ||
|
||||||
((filtersWithDefinition?.length || currentViewSorts?.length) &&
|
((currentViewSorts?.length || currentViewFilters?.length) &&
|
||||||
isViewBarExpanded);
|
isViewBarExpanded);
|
||||||
|
|
||||||
if (!shouldExpandViewBar) {
|
if (!shouldExpandViewBar) {
|
||||||
@ -140,32 +119,32 @@ export const ViewBarDetails = ({
|
|||||||
{currentViewSorts?.map((sort) => {
|
{currentViewSorts?.map((sort) => {
|
||||||
return (
|
return (
|
||||||
<SortOrFilterChip
|
<SortOrFilterChip
|
||||||
key={sort.key}
|
key={sort.fieldId}
|
||||||
testId={sort.key}
|
testId={sort.fieldId}
|
||||||
labelValue={sort.definition.label}
|
labelValue={sort.definition.label}
|
||||||
Icon={sort.direction === 'desc' ? IconArrowDown : IconArrowUp}
|
Icon={sort.direction === 'desc' ? IconArrowDown : IconArrowUp}
|
||||||
isSort
|
isSort
|
||||||
onRemove={() => handleSortRemove(sort.key)}
|
onRemove={() => removeViewSort(sort.fieldId)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{!!currentViewSorts?.length && !!filtersWithDefinition?.length && (
|
{!!currentViewSorts?.length && !!currentViewFilters?.length && (
|
||||||
<StyledSeperatorContainer>
|
<StyledSeperatorContainer>
|
||||||
<StyledSeperator />
|
<StyledSeperator />
|
||||||
</StyledSeperatorContainer>
|
</StyledSeperatorContainer>
|
||||||
)}
|
)}
|
||||||
{filtersWithDefinition?.map((filter) => {
|
{currentViewFilters?.map((filter) => {
|
||||||
return (
|
return (
|
||||||
<SortOrFilterChip
|
<SortOrFilterChip
|
||||||
key={filter.key}
|
key={filter.fieldId}
|
||||||
testId={filter.key}
|
testId={filter.fieldId}
|
||||||
labelKey={filter.label}
|
labelKey={filter.definition.label}
|
||||||
labelValue={`${getOperandLabelShort(filter.operand)} ${
|
labelValue={`${getOperandLabelShort(filter.operand)} ${
|
||||||
filter.displayValue
|
filter.displayValue
|
||||||
}`}
|
}`}
|
||||||
Icon={filter.Icon}
|
Icon={filter.definition.Icon}
|
||||||
onRemove={() => {
|
onRemove={() => {
|
||||||
removeFilter(filter.key);
|
removeViewFilter(filter.fieldId);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -8,28 +8,65 @@ import { assertNotNull } from '~/utils/assert';
|
|||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||||
|
|
||||||
import { useView } from '../hooks/useView';
|
import { useView } from '../hooks/useView';
|
||||||
import { useViewInternalStates } from '../hooks/useViewInternalStates';
|
import { useViewGetStates } from '../hooks/useViewGetStates';
|
||||||
import { availableFieldsScopedState } from '../states/availableFieldsScopedState';
|
import { availableFieldDefinitionsScopedState } from '../states/availableFieldDefinitionsScopedState';
|
||||||
|
import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState';
|
||||||
|
import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState';
|
||||||
import { onViewFieldsChangeScopedState } from '../states/onViewFieldsChangeScopedState';
|
import { onViewFieldsChangeScopedState } from '../states/onViewFieldsChangeScopedState';
|
||||||
|
import { onViewFiltersChangeScopedState } from '../states/onViewFiltersChangeScopedState';
|
||||||
|
import { onViewSortsChangeScopedState } from '../states/onViewSortsChangeScopedState';
|
||||||
import { savedViewFieldsScopedFamilyState } from '../states/savedViewFieldsScopedFamilyState';
|
import { savedViewFieldsScopedFamilyState } from '../states/savedViewFieldsScopedFamilyState';
|
||||||
|
import { savedViewFiltersScopedFamilyState } from '../states/savedViewFiltersScopedFamilyState';
|
||||||
|
import { savedViewSortsScopedFamilyState } from '../states/savedViewSortsScopedFamilyState';
|
||||||
import { viewsScopedState } from '../states/viewsScopedState';
|
import { viewsScopedState } from '../states/viewsScopedState';
|
||||||
import { View } from '../types/View';
|
import { View } from '../types/View';
|
||||||
import { ViewField } from '../types/ViewField';
|
import { ViewField } from '../types/ViewField';
|
||||||
|
import { ViewFilter } from '../types/ViewFilter';
|
||||||
|
import { ViewSort } from '../types/ViewSort';
|
||||||
|
|
||||||
export const ViewBarEffect = () => {
|
export const ViewBarEffect = () => {
|
||||||
const {
|
const {
|
||||||
scopeId: viewScopeId,
|
scopeId: viewScopeId,
|
||||||
setCurrentViewFields,
|
setCurrentViewFields,
|
||||||
setSavedViewFields,
|
setSavedViewFields,
|
||||||
|
setCurrentViewFilters,
|
||||||
|
setSavedViewFilters,
|
||||||
|
setCurrentViewSorts,
|
||||||
|
setSavedViewSorts,
|
||||||
currentViewId,
|
currentViewId,
|
||||||
setViews,
|
setViews,
|
||||||
changeView,
|
loadView,
|
||||||
|
changeViewInUrl,
|
||||||
setCurrentViewId,
|
setCurrentViewId,
|
||||||
} = useView();
|
} = useView();
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
|
||||||
const { viewType, viewObjectId } = useViewInternalStates(viewScopeId);
|
const { viewType, viewObjectId } = useViewGetStates(viewScopeId);
|
||||||
|
|
||||||
|
useFindManyObjects({
|
||||||
|
objectNamePlural: 'viewsV2',
|
||||||
|
filter: { type: { eq: viewType }, objectId: { eq: viewObjectId } },
|
||||||
|
onCompleted: useRecoilCallback(
|
||||||
|
({ snapshot }) =>
|
||||||
|
async (data: PaginatedObjectTypeResults<View>) => {
|
||||||
|
const nextViews = data.edges.map((view) => ({
|
||||||
|
id: view.node.id,
|
||||||
|
name: view.node.name,
|
||||||
|
objectId: view.node.objectId,
|
||||||
|
}));
|
||||||
|
const views = snapshot
|
||||||
|
.getLoadable(viewsScopedState({ scopeId: viewScopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
if (!isDeeplyEqual(views, nextViews)) setViews(nextViews);
|
||||||
|
|
||||||
|
if (!nextViews.length) return;
|
||||||
|
|
||||||
|
if (!currentViewId) return changeViewInUrl(nextViews[0].id);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
useFindManyObjects({
|
useFindManyObjects({
|
||||||
objectNamePlural: 'viewFieldsV2',
|
objectNamePlural: 'viewFieldsV2',
|
||||||
@ -38,7 +75,9 @@ export const ViewBarEffect = () => {
|
|||||||
({ snapshot }) =>
|
({ snapshot }) =>
|
||||||
async (data: PaginatedObjectTypeResults<ViewField>) => {
|
async (data: PaginatedObjectTypeResults<ViewField>) => {
|
||||||
const availableFields = snapshot
|
const availableFields = snapshot
|
||||||
.getLoadable(availableFieldsScopedState({ scopeId: viewScopeId }))
|
.getLoadable(
|
||||||
|
availableFieldDefinitionsScopedState({ scopeId: viewScopeId }),
|
||||||
|
)
|
||||||
.getValue();
|
.getValue();
|
||||||
|
|
||||||
const onViewFieldsChange = snapshot
|
const onViewFieldsChange = snapshot
|
||||||
@ -74,133 +113,122 @@ export const ViewBarEffect = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useFindManyObjects({
|
useFindManyObjects({
|
||||||
objectNamePlural: 'viewsV2',
|
objectNamePlural: 'viewFiltersV2',
|
||||||
filter: { type: { eq: viewType }, objectId: { eq: viewObjectId } },
|
filter: { viewId: { eq: currentViewId } },
|
||||||
onCompleted: useRecoilCallback(
|
onCompleted: useRecoilCallback(
|
||||||
({ snapshot }) =>
|
({ snapshot }) =>
|
||||||
async (data: PaginatedObjectTypeResults<View>) => {
|
async (data: PaginatedObjectTypeResults<Required<ViewFilter>>) => {
|
||||||
const nextViews = data.edges.map((view) => ({
|
const availableFilterDefinitions = snapshot
|
||||||
id: view.node.id,
|
.getLoadable(
|
||||||
name: view.node.name,
|
availableFilterDefinitionsScopedState({ scopeId: viewScopeId }),
|
||||||
objectId: view.node.objectId,
|
)
|
||||||
}));
|
|
||||||
const views = snapshot
|
|
||||||
.getLoadable(viewsScopedState({ scopeId: viewScopeId }))
|
|
||||||
.getValue();
|
.getValue();
|
||||||
|
|
||||||
if (!isDeeplyEqual(views, nextViews)) setViews(nextViews);
|
if (!availableFilterDefinitions || !currentViewId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!nextViews.length) return;
|
const savedViewFilters = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
savedViewFiltersScopedFamilyState({
|
||||||
|
scopeId: viewScopeId,
|
||||||
|
familyKey: currentViewId,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
if (!currentViewId) return changeView(nextViews[0].id);
|
const onViewFiltersChange = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
onViewFiltersChangeScopedState({ scopeId: viewScopeId }),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const queriedViewFilters = data.edges
|
||||||
|
.map(({ node }) => {
|
||||||
|
const availableFilterDefinition = availableFilterDefinitions.find(
|
||||||
|
(filterDefinition) => filterDefinition.fieldId === node.fieldId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!availableFilterDefinition) return null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
displayValue: node.displayValue ?? node.value,
|
||||||
|
definition: availableFilterDefinition,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(assertNotNull);
|
||||||
|
|
||||||
|
if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) {
|
||||||
|
setSavedViewFilters?.(queriedViewFilters);
|
||||||
|
setCurrentViewFilters?.(queriedViewFilters);
|
||||||
|
onViewFiltersChange?.(queriedViewFilters);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
// useGetViewSortsQuery({
|
useFindManyObjects({
|
||||||
// skip: !currentViewId,
|
objectNamePlural: 'viewSortsV2',
|
||||||
// variables: {
|
filter: { viewId: { eq: currentViewId } },
|
||||||
// where: {
|
onCompleted: useRecoilCallback(
|
||||||
// viewId: { equals: currentViewId },
|
({ snapshot }) =>
|
||||||
// },
|
async (data: PaginatedObjectTypeResults<Required<ViewSort>>) => {
|
||||||
// },
|
const availableSortDefinitions = snapshot
|
||||||
// onCompleted: useRecoilCallback(({ snapshot }) => async (data) => {
|
.getLoadable(
|
||||||
// const availableSorts = snapshot
|
availableSortDefinitionsScopedState({ scopeId: viewScopeId }),
|
||||||
// .getLoadable(availableSortsScopedState({ scopeId: viewScopeId }))
|
)
|
||||||
// .getValue();
|
.getValue();
|
||||||
|
|
||||||
// if (!availableSorts || !currentViewId) {
|
if (!availableSortDefinitions || !currentViewId) {
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const savedViewSorts = snapshot
|
const savedViewSorts = snapshot
|
||||||
// .getLoadable(
|
.getLoadable(
|
||||||
// savedViewSortsScopedFamilyState({
|
savedViewSortsScopedFamilyState({
|
||||||
// scopeId: viewScopeId,
|
scopeId: viewScopeId,
|
||||||
// familyKey: currentViewId,
|
familyKey: currentViewId,
|
||||||
// }),
|
}),
|
||||||
// )
|
)
|
||||||
// .getValue();
|
.getValue();
|
||||||
|
|
||||||
// const queriedViewSorts = data.viewSorts
|
const onViewSortsChange = snapshot
|
||||||
// .map((viewSort) => {
|
.getLoadable(onViewSortsChangeScopedState({ scopeId: viewScopeId }))
|
||||||
// const foundCorrespondingSortDefinition = availableSorts.find(
|
.getValue();
|
||||||
// (sort) => sort.key === viewSort.key,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if (foundCorrespondingSortDefinition) {
|
const queriedViewSorts = data.edges
|
||||||
// return {
|
.map(({ node }) => {
|
||||||
// key: viewSort.key,
|
const availableSortDefinition = availableSortDefinitions.find(
|
||||||
// definition: foundCorrespondingSortDefinition,
|
(sort) => sort.fieldId === node.fieldId,
|
||||||
// direction: viewSort.direction.toLowerCase(),
|
);
|
||||||
// } as Sort;
|
|
||||||
// } else {
|
|
||||||
// return undefined;
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .filter((sort): sort is Sort => !!sort);
|
|
||||||
|
|
||||||
// if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) {
|
if (!availableSortDefinition) return null;
|
||||||
// setSavedViewSorts?.(queriedViewSorts);
|
|
||||||
// setCurrentViewSorts?.(queriedViewSorts);
|
|
||||||
// }
|
|
||||||
// }),
|
|
||||||
// });
|
|
||||||
|
|
||||||
// useGetViewFiltersQuery({
|
return {
|
||||||
// skip: !currentViewId,
|
id: node.id,
|
||||||
// variables: {
|
fieldId: node.fieldId,
|
||||||
// where: {
|
direction: node.direction,
|
||||||
// viewId: { equals: currentViewId },
|
definition: availableSortDefinition,
|
||||||
// },
|
};
|
||||||
// },
|
})
|
||||||
// onCompleted: useRecoilCallback(({ snapshot }) => (data) => {
|
.filter(assertNotNull);
|
||||||
// const availableFilters = snapshot
|
|
||||||
// .getLoadable(availableFiltersScopedState({ scopeId: viewScopeId }))
|
|
||||||
// .getValue();
|
|
||||||
|
|
||||||
// if (!availableFilters || !currentViewId) {
|
if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) {
|
||||||
// return;
|
setSavedViewSorts?.(queriedViewSorts);
|
||||||
// }
|
setCurrentViewSorts?.(queriedViewSorts);
|
||||||
|
onViewSortsChange?.(queriedViewSorts);
|
||||||
// const savedViewFilters = snapshot
|
}
|
||||||
// .getLoadable(
|
},
|
||||||
// savedViewFiltersScopedFamilyState({
|
),
|
||||||
// scopeId: viewScopeId,
|
});
|
||||||
// familyKey: currentViewId,
|
|
||||||
// }),
|
|
||||||
// )
|
|
||||||
// .getValue();
|
|
||||||
|
|
||||||
// const queriedViewFilters = data.viewFilters
|
|
||||||
// .map(({ __typename, name: _name, ...viewFilter }) => {
|
|
||||||
// const availableFilter = availableFilters.find(
|
|
||||||
// (filter) => filter.key === viewFilter.key,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// return availableFilter
|
|
||||||
// ? {
|
|
||||||
// ...viewFilter,
|
|
||||||
// displayValue: viewFilter.displayValue ?? viewFilter.value,
|
|
||||||
// type: availableFilter.type,
|
|
||||||
// }
|
|
||||||
// : undefined;
|
|
||||||
// })
|
|
||||||
// .filter((filter): filter is Filter => !!filter);
|
|
||||||
|
|
||||||
// if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) {
|
|
||||||
// setSavedViewFilters?.(queriedViewFilters);
|
|
||||||
// setCurrentViewFilters?.(queriedViewFilters);
|
|
||||||
// }
|
|
||||||
// }),
|
|
||||||
// });
|
|
||||||
|
|
||||||
const currentViewIdFromUrl = searchParams.get('view');
|
const currentViewIdFromUrl = searchParams.get('view');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentViewIdFromUrl) return;
|
if (!currentViewIdFromUrl) return;
|
||||||
setCurrentViewId(currentViewIdFromUrl);
|
loadView(currentViewIdFromUrl);
|
||||||
}, [currentViewIdFromUrl, setCurrentViewId]);
|
}, [currentViewIdFromUrl, loadView, setCurrentViewId]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import { useTheme } from '@emotion/react';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { TableOptionsDropdownId } from '@/ui/data/data-table/constants/TableOptionsDropdownId';
|
|
||||||
import {
|
import {
|
||||||
IconChevronDown,
|
IconChevronDown,
|
||||||
IconList,
|
IconList,
|
||||||
@ -24,7 +23,7 @@ import { assertNotNull } from '~/utils/assert';
|
|||||||
|
|
||||||
import { ViewsDropdownId } from '../constants/ViewsDropdownId';
|
import { ViewsDropdownId } from '../constants/ViewsDropdownId';
|
||||||
import { useView } from '../hooks/useView';
|
import { useView } from '../hooks/useView';
|
||||||
import { useViewInternalStates } from '../hooks/useViewInternalStates';
|
import { useViewGetStates } from '../hooks/useViewGetStates';
|
||||||
|
|
||||||
const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||||
@ -60,17 +59,22 @@ const StyledViewName = styled.span`
|
|||||||
export type ViewsDropdownButtonProps = {
|
export type ViewsDropdownButtonProps = {
|
||||||
hotkeyScope: HotkeyScope;
|
hotkeyScope: HotkeyScope;
|
||||||
onViewEditModeChange?: () => void;
|
onViewEditModeChange?: () => void;
|
||||||
|
optionsDropdownScopeId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ViewsDropdownButton = ({
|
export const ViewsDropdownButton = ({
|
||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
onViewEditModeChange,
|
onViewEditModeChange,
|
||||||
|
optionsDropdownScopeId,
|
||||||
}: ViewsDropdownButtonProps) => {
|
}: ViewsDropdownButtonProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { scopeId, removeView, currentViewId, changeView } = useView();
|
const { scopeId, removeView, currentViewId, changeViewInUrl } = useView();
|
||||||
|
|
||||||
const { views, currentView, setViewEditMode, entityCountInCurrentView } =
|
const { views, currentView, entityCountInCurrentView } = useViewGetStates(
|
||||||
useViewInternalStates(scopeId, currentViewId);
|
scopeId,
|
||||||
|
currentViewId,
|
||||||
|
);
|
||||||
|
const { setViewEditMode } = useView();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isDropdownOpen: isViewsDropdownOpen,
|
isDropdownOpen: isViewsDropdownOpen,
|
||||||
@ -80,16 +84,16 @@ export const ViewsDropdownButton = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { openDropdown: openOptionsDropdown } = useDropdown({
|
const { openDropdown: openOptionsDropdown } = useDropdown({
|
||||||
dropdownScopeId: TableOptionsDropdownId,
|
dropdownScopeId: optionsDropdownScopeId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleViewSelect = useRecoilCallback(
|
const handleViewSelect = useRecoilCallback(
|
||||||
() => async (viewId: string) => {
|
() => async (viewId: string) => {
|
||||||
changeView(viewId);
|
changeViewInUrl(viewId);
|
||||||
|
|
||||||
closeViewsDropdown();
|
closeViewsDropdown();
|
||||||
},
|
},
|
||||||
[changeView, closeViewsDropdown],
|
[changeViewInUrl, closeViewsDropdown],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleAddViewButtonClick = () => {
|
const handleAddViewButtonClick = () => {
|
||||||
@ -104,7 +108,7 @@ export const ViewsDropdownButton = ({
|
|||||||
viewId: string,
|
viewId: string,
|
||||||
) => {
|
) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
changeView(viewId);
|
changeViewInUrl(viewId);
|
||||||
setViewEditMode('edit');
|
setViewEditMode('edit');
|
||||||
onViewEditModeChange?.();
|
onViewEditModeChange?.();
|
||||||
closeViewsDropdown();
|
closeViewsDropdown();
|
||||||
|
|||||||
@ -8,9 +8,10 @@ import { viewObjectIdScopeState } from '@/views/states/viewObjectIdScopeState';
|
|||||||
import { ViewField } from '@/views/types/ViewField';
|
import { ViewField } from '@/views/types/ViewField';
|
||||||
|
|
||||||
export const useViewFields = (viewScopeId: string) => {
|
export const useViewFields = (viewScopeId: string) => {
|
||||||
const { updateOneMutation, createOneMutation } = useFindOneMetadataObject({
|
const { updateOneMutation, createOneMutation, findManyQuery } =
|
||||||
objectNameSingular: 'viewFieldV2',
|
useFindOneMetadataObject({
|
||||||
});
|
objectNameSingular: 'viewFieldV2',
|
||||||
|
});
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
|
|
||||||
const persistViewFields = useRecoilCallback(
|
const persistViewFields = useRecoilCallback(
|
||||||
@ -49,12 +50,13 @@ export const useViewFields = (viewScopeId: string) => {
|
|||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
fieldId: viewField.fieldId,
|
fieldId: viewField.fieldId,
|
||||||
viewId: currentViewId,
|
viewId: viewId,
|
||||||
isVisible: viewField.isVisible,
|
isVisible: viewField.isVisible,
|
||||||
size: viewField.size,
|
size: viewField.size,
|
||||||
position: viewField.position,
|
position: viewField.position,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
refetchQueries: [findManyQuery],
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,14 +1,26 @@
|
|||||||
|
import { useApolloClient } from '@apollo/client';
|
||||||
|
import { produce } from 'immer';
|
||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
|
import { useFindOneMetadataObject } from '@/metadata/hooks/useFindOneMetadataObject';
|
||||||
import { Filter } from '@/ui/data/filter/types/Filter';
|
import { Filter } from '@/ui/data/filter/types/Filter';
|
||||||
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
|
||||||
import { availableFiltersScopedState } from '@/views/states/availableFiltersScopedState';
|
|
||||||
import { currentViewFiltersScopedFamilyState } from '@/views/states/currentViewFiltersScopedFamilyState';
|
import { currentViewFiltersScopedFamilyState } from '@/views/states/currentViewFiltersScopedFamilyState';
|
||||||
import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState';
|
import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState';
|
||||||
|
import { onViewFiltersChangeScopedState } from '@/views/states/onViewFiltersChangeScopedState';
|
||||||
import { savedViewFiltersScopedFamilyState } from '@/views/states/savedViewFiltersScopedFamilyState';
|
import { savedViewFiltersScopedFamilyState } from '@/views/states/savedViewFiltersScopedFamilyState';
|
||||||
import { savedViewFiltersByKeyScopedFamilySelector } from '@/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector';
|
import { savedViewFiltersByKeyScopedFamilySelector } from '@/views/states/selectors/savedViewFiltersByKeyScopedFamilySelector';
|
||||||
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
|
|
||||||
|
import { useViewSetStates } from '../useViewSetStates';
|
||||||
|
|
||||||
export const useViewFilters = (viewScopeId: string) => {
|
export const useViewFilters = (viewScopeId: string) => {
|
||||||
|
const { updateOneMutation, createOneMutation, findManyQuery } =
|
||||||
|
useFindOneMetadataObject({
|
||||||
|
objectNameSingular: 'viewFilterV2',
|
||||||
|
});
|
||||||
|
const apolloClient = useApolloClient();
|
||||||
|
const { setCurrentViewFilters } = useViewSetStates(viewScopeId);
|
||||||
|
|
||||||
const persistViewFilters = useRecoilCallback(
|
const persistViewFilters = useRecoilCallback(
|
||||||
({ snapshot, set }) =>
|
({ snapshot, set }) =>
|
||||||
async (viewId?: string) => {
|
async (viewId?: string) => {
|
||||||
@ -19,69 +31,52 @@ export const useViewFilters = (viewScopeId: string) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _createViewFilters = (
|
const createViewFilters = (viewFiltersToCreate: ViewFilter[]) => {
|
||||||
filters: Filter[],
|
if (!viewFiltersToCreate.length) return;
|
||||||
availableFilters: FilterDefinition[] = [],
|
|
||||||
) => {
|
|
||||||
if (!currentViewId || !filters.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!availableFilters) {
|
return Promise.all(
|
||||||
return;
|
viewFiltersToCreate.map((viewFilter) =>
|
||||||
}
|
apolloClient.mutate({
|
||||||
|
mutation: createOneMutation,
|
||||||
// return createViewFiltersMutation({
|
variables: {
|
||||||
// variables: {
|
input: {
|
||||||
// data: filters.map((filter) => ({
|
fieldId: viewFilter.fieldId,
|
||||||
// displayValue: filter.displayValue ?? filter.value,
|
viewId: viewId ?? currentViewId,
|
||||||
// key: filter.key,
|
value: viewFilter.value,
|
||||||
// name:
|
displayValue: viewFilter.displayValue,
|
||||||
// availableFilters.find(({ key }) => key === filter.key)
|
operand: viewFilter.operand,
|
||||||
// ?.label ?? '',
|
},
|
||||||
// operand: filter.operand,
|
},
|
||||||
// value: filter.value,
|
refetchQueries: [findManyQuery],
|
||||||
// viewId: viewId ?? currentViewId,
|
}),
|
||||||
// })),
|
),
|
||||||
// },
|
);
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const _updateViewFilters = (filters: Filter[]) => {
|
const updateViewFilters = (viewFiltersToUpdate: ViewFilter[]) => {
|
||||||
if (!currentViewId || !filters.length) return;
|
if (!viewFiltersToUpdate.length) return;
|
||||||
|
|
||||||
// return Promise.all(
|
return Promise.all(
|
||||||
// filters.map((filter) =>
|
viewFiltersToUpdate.map((viewFilter) =>
|
||||||
// updateViewFilterMutation({
|
apolloClient.mutate({
|
||||||
// variables: {
|
mutation: updateOneMutation,
|
||||||
// data: {
|
variables: {
|
||||||
// displayValue: filter.displayValue ?? filter.value,
|
idToUpdate: viewFilter.id,
|
||||||
// operand: filter.operand,
|
input: {
|
||||||
// value: filter.value,
|
value: viewFilter.value,
|
||||||
// },
|
displayValue: viewFilter.displayValue,
|
||||||
// where: {
|
operand: viewFilter.operand,
|
||||||
// viewId_key: {
|
},
|
||||||
// key: filter.key,
|
},
|
||||||
// viewId: viewId ?? currentViewId,
|
}),
|
||||||
// },
|
),
|
||||||
// },
|
);
|
||||||
// },
|
|
||||||
// }),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const _deleteViewFilters = (filterKeys: string[]) => {
|
const deleteViewFilters = (viewFilterIdsToDelete: string[]) => {
|
||||||
if (!currentViewId || !filterKeys.length) return;
|
if (!viewFilterIdsToDelete.length) return;
|
||||||
|
|
||||||
// return deleteViewFiltersMutation({
|
// Todo
|
||||||
// variables: {
|
|
||||||
// where: {
|
|
||||||
// key: { in: filterKeys },
|
|
||||||
// viewId: { equals: viewId ?? currentViewId },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentViewFilters = snapshot
|
const currentViewFilters = snapshot
|
||||||
@ -97,7 +92,7 @@ export const useViewFilters = (viewScopeId: string) => {
|
|||||||
.getLoadable(
|
.getLoadable(
|
||||||
savedViewFiltersByKeyScopedFamilySelector({
|
savedViewFiltersByKeyScopedFamilySelector({
|
||||||
scopeId: viewScopeId,
|
scopeId: viewScopeId,
|
||||||
viewId: currentViewId,
|
viewId: viewId ?? currentViewId,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.getValue();
|
.getValue();
|
||||||
@ -109,32 +104,24 @@ export const useViewFilters = (viewScopeId: string) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const availableFilters = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
availableFiltersScopedState({
|
|
||||||
scopeId: viewScopeId,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
const filtersToCreate = currentViewFilters.filter(
|
const filtersToCreate = currentViewFilters.filter(
|
||||||
(filter) => !savedViewFiltersByKey[filter.key],
|
(filter) => !savedViewFiltersByKey[filter.fieldId],
|
||||||
);
|
);
|
||||||
await _createViewFilters(filtersToCreate, availableFilters);
|
await createViewFilters(filtersToCreate);
|
||||||
|
|
||||||
const filtersToUpdate = currentViewFilters.filter(
|
const filtersToUpdate = currentViewFilters.filter(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
savedViewFiltersByKey[filter.key] &&
|
savedViewFiltersByKey[filter.fieldId] &&
|
||||||
(savedViewFiltersByKey[filter.key].operand !== filter.operand ||
|
(savedViewFiltersByKey[filter.fieldId].operand !== filter.operand ||
|
||||||
savedViewFiltersByKey[filter.key].value !== filter.value),
|
savedViewFiltersByKey[filter.fieldId].value !== filter.value),
|
||||||
);
|
);
|
||||||
await _updateViewFilters(filtersToUpdate);
|
await updateViewFilters(filtersToUpdate);
|
||||||
|
|
||||||
const filterKeys = currentViewFilters.map((filter) => filter.key);
|
const filterKeys = currentViewFilters.map((filter) => filter.fieldId);
|
||||||
const filterKeysToDelete = Object.keys(savedViewFiltersByKey).filter(
|
const filterKeysToDelete = Object.keys(savedViewFiltersByKey).filter(
|
||||||
(previousFilterKey) => !filterKeys.includes(previousFilterKey),
|
(previousFilterKey) => !filterKeys.includes(previousFilterKey),
|
||||||
);
|
);
|
||||||
await _deleteViewFilters(filterKeysToDelete);
|
await deleteViewFilters(filterKeysToDelete);
|
||||||
set(
|
set(
|
||||||
savedViewFiltersScopedFamilyState({
|
savedViewFiltersScopedFamilyState({
|
||||||
scopeId: viewScopeId,
|
scopeId: viewScopeId,
|
||||||
@ -143,8 +130,102 @@ export const useViewFilters = (viewScopeId: string) => {
|
|||||||
currentViewFilters,
|
currentViewFilters,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[viewScopeId],
|
[
|
||||||
|
apolloClient,
|
||||||
|
createOneMutation,
|
||||||
|
findManyQuery,
|
||||||
|
updateOneMutation,
|
||||||
|
viewScopeId,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { persistViewFilters };
|
const upsertViewFilter = useRecoilCallback(
|
||||||
|
({ snapshot }) =>
|
||||||
|
(filterToUpsert: Filter) => {
|
||||||
|
const currentViewId = snapshot
|
||||||
|
.getLoadable(currentViewIdScopedState({ scopeId: viewScopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
if (!currentViewId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const savedViewFiltersByKey = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
savedViewFiltersByKeyScopedFamilySelector({
|
||||||
|
scopeId: viewScopeId,
|
||||||
|
viewId: currentViewId,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
if (!savedViewFiltersByKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onViewFiltersChange = snapshot
|
||||||
|
.getLoadable(onViewFiltersChangeScopedState({ scopeId: viewScopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const existingSavedFilterId =
|
||||||
|
savedViewFiltersByKey[filterToUpsert.fieldId]?.id;
|
||||||
|
|
||||||
|
setCurrentViewFilters?.((filters) => {
|
||||||
|
const newViewFilters = produce(filters, (filtersDraft) => {
|
||||||
|
const existingFilterIndex = filtersDraft.findIndex(
|
||||||
|
(filter) => filter.fieldId === filterToUpsert.fieldId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingFilterIndex === -1) {
|
||||||
|
filtersDraft.push({
|
||||||
|
...filterToUpsert,
|
||||||
|
id: existingSavedFilterId,
|
||||||
|
});
|
||||||
|
return filtersDraft;
|
||||||
|
}
|
||||||
|
|
||||||
|
filtersDraft[existingFilterIndex] = {
|
||||||
|
...filterToUpsert,
|
||||||
|
id: existingSavedFilterId,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
onViewFiltersChange?.(newViewFilters);
|
||||||
|
return newViewFilters;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const removeViewFilter = useRecoilCallback(
|
||||||
|
({ snapshot }) =>
|
||||||
|
(fieldId: string) => {
|
||||||
|
const currentViewId = snapshot
|
||||||
|
.getLoadable(currentViewIdScopedState({ scopeId: viewScopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
if (!currentViewId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onViewFiltersChange = snapshot
|
||||||
|
.getLoadable(onViewFiltersChangeScopedState({ scopeId: viewScopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const currentViewFilters = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
currentViewFiltersScopedFamilyState({
|
||||||
|
scopeId: viewScopeId,
|
||||||
|
familyKey: currentViewId,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const newViewFilters = currentViewFilters.filter((filter) => {
|
||||||
|
return filter.fieldId !== fieldId;
|
||||||
|
});
|
||||||
|
setCurrentViewFilters?.(newViewFilters);
|
||||||
|
onViewFiltersChange?.(newViewFilters);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return { persistViewFilters, removeViewFilter, upsertViewFilter };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,16 +1,25 @@
|
|||||||
|
import { useApolloClient } from '@apollo/client';
|
||||||
import { produce } from 'immer';
|
import { produce } from 'immer';
|
||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
|
import { useFindOneMetadataObject } from '@/metadata/hooks/useFindOneMetadataObject';
|
||||||
import { Sort } from '@/ui/data/sort/types/Sort';
|
import { Sort } from '@/ui/data/sort/types/Sort';
|
||||||
import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState';
|
import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState';
|
||||||
import { currentViewSortsScopedFamilyState } from '@/views/states/currentViewSortsScopedFamilyState';
|
import { currentViewSortsScopedFamilyState } from '@/views/states/currentViewSortsScopedFamilyState';
|
||||||
|
import { onViewSortsChangeScopedState } from '@/views/states/onViewSortsChangeScopedState';
|
||||||
import { savedViewSortsScopedFamilyState } from '@/views/states/savedViewSortsScopedFamilyState';
|
import { savedViewSortsScopedFamilyState } from '@/views/states/savedViewSortsScopedFamilyState';
|
||||||
import { savedViewSortsByKeyScopedFamilySelector } from '@/views/states/selectors/savedViewSortsByKeyScopedFamilySelector';
|
import { savedViewSortsByKeyScopedFamilySelector } from '@/views/states/selectors/savedViewSortsByKeyScopedFamilySelector';
|
||||||
|
import { ViewSort } from '@/views/types/ViewSort';
|
||||||
|
|
||||||
import { useViewStates } from '../useViewStates';
|
import { useViewSetStates } from '../useViewSetStates';
|
||||||
|
|
||||||
export const useViewSorts = (viewScopeId: string) => {
|
export const useViewSorts = (viewScopeId: string) => {
|
||||||
const { setCurrentViewSorts } = useViewStates(viewScopeId);
|
const { updateOneMutation, createOneMutation, findManyQuery } =
|
||||||
|
useFindOneMetadataObject({
|
||||||
|
objectNameSingular: 'viewSortV2',
|
||||||
|
});
|
||||||
|
const apolloClient = useApolloClient();
|
||||||
|
const { setCurrentViewSorts } = useViewSetStates(viewScopeId);
|
||||||
|
|
||||||
const persistViewSorts = useRecoilCallback(
|
const persistViewSorts = useRecoilCallback(
|
||||||
({ snapshot, set }) =>
|
({ snapshot, set }) =>
|
||||||
@ -22,54 +31,48 @@ export const useViewSorts = (viewScopeId: string) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _createViewSorts = (sorts: Sort[]) => {
|
const createViewSorts = (viewSortsToCreate: ViewSort[]) => {
|
||||||
if (!currentViewId || !sorts.length) return;
|
if (!viewSortsToCreate.length) return;
|
||||||
|
|
||||||
// return createViewSortsMutation({
|
return Promise.all(
|
||||||
// variables: {
|
viewSortsToCreate.map((viewSort) =>
|
||||||
// data: sorts.map((sort) => ({
|
apolloClient.mutate({
|
||||||
// key: sort.key,
|
mutation: createOneMutation,
|
||||||
// direction: sort.direction as ViewSortDirection,
|
variables: {
|
||||||
// name: sort.definition.label,
|
input: {
|
||||||
// viewId: viewId ?? currentViewId,
|
fieldId: viewSort.fieldId,
|
||||||
// })),
|
viewId: viewId ?? currentViewId,
|
||||||
// },
|
direction: viewSort.direction,
|
||||||
// });
|
},
|
||||||
|
},
|
||||||
|
refetchQueries: [findManyQuery],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const _updateViewSorts = (sorts: Sort[]) => {
|
const updateViewSorts = (viewSortsToUpdate: ViewSort[]) => {
|
||||||
if (!currentViewId || !sorts.length) return;
|
if (!viewSortsToUpdate.length) return;
|
||||||
|
|
||||||
// return Promise.all(
|
return Promise.all(
|
||||||
// sorts.map((sort) =>
|
viewSortsToUpdate.map((viewSort) =>
|
||||||
// updateViewSortMutation({
|
apolloClient.mutate({
|
||||||
// variables: {
|
mutation: updateOneMutation,
|
||||||
// data: {
|
variables: {
|
||||||
// direction: sort.direction as ViewSortDirection,
|
idToUpdate: viewSort.id,
|
||||||
// },
|
input: {
|
||||||
// where: {
|
direction: viewSort.direction,
|
||||||
// viewId_key: {
|
},
|
||||||
// key: sort.key,
|
},
|
||||||
// viewId: viewId ?? currentViewId,
|
}),
|
||||||
// },
|
),
|
||||||
// },
|
);
|
||||||
// },
|
|
||||||
// }),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const _deleteViewSorts = (sortKeys: string[]) => {
|
const deleteViewSorts = (viewSortIdsToDelete: string[]) => {
|
||||||
if (!currentViewId || !sortKeys.length) return;
|
if (!viewSortIdsToDelete.length) return;
|
||||||
|
|
||||||
// return deleteViewSortsMutation({
|
// Todo
|
||||||
// variables: {
|
|
||||||
// where: {
|
|
||||||
// key: { in: sortKeys },
|
|
||||||
// viewId: { equals: viewId ?? currentViewId },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentViewSorts = snapshot
|
const currentViewSorts = snapshot
|
||||||
@ -85,7 +88,7 @@ export const useViewSorts = (viewScopeId: string) => {
|
|||||||
.getLoadable(
|
.getLoadable(
|
||||||
savedViewSortsByKeyScopedFamilySelector({
|
savedViewSortsByKeyScopedFamilySelector({
|
||||||
scopeId: viewScopeId,
|
scopeId: viewScopeId,
|
||||||
viewId: currentViewId,
|
viewId: viewId ?? currentViewId,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.getValue();
|
.getValue();
|
||||||
@ -98,22 +101,23 @@ export const useViewSorts = (viewScopeId: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sortsToCreate = currentViewSorts.filter(
|
const sortsToCreate = currentViewSorts.filter(
|
||||||
(sort) => !savedViewSortsByKey[sort.key],
|
(sort) => !savedViewSortsByKey[sort.fieldId],
|
||||||
);
|
);
|
||||||
await _createViewSorts(sortsToCreate);
|
|
||||||
|
await createViewSorts(sortsToCreate);
|
||||||
|
|
||||||
const sortsToUpdate = currentViewSorts.filter(
|
const sortsToUpdate = currentViewSorts.filter(
|
||||||
(sort) =>
|
(sort) =>
|
||||||
savedViewSortsByKey[sort.key] &&
|
savedViewSortsByKey[sort.fieldId] &&
|
||||||
savedViewSortsByKey[sort.key].direction !== sort.direction,
|
savedViewSortsByKey[sort.fieldId].direction !== sort.direction,
|
||||||
);
|
);
|
||||||
await _updateViewSorts(sortsToUpdate);
|
await updateViewSorts(sortsToUpdate);
|
||||||
|
|
||||||
const sortKeys = currentViewSorts.map((sort) => sort.key);
|
const sortKeys = currentViewSorts.map((sort) => sort.fieldId);
|
||||||
const sortKeysToDelete = Object.keys(savedViewSortsByKey).filter(
|
const sortKeysToDelete = Object.keys(savedViewSortsByKey).filter(
|
||||||
(previousSortKey) => !sortKeys.includes(previousSortKey),
|
(previousSortKey) => !sortKeys.includes(previousSortKey),
|
||||||
);
|
);
|
||||||
await _deleteViewSorts(sortKeysToDelete);
|
await deleteViewSorts(sortKeysToDelete);
|
||||||
set(
|
set(
|
||||||
savedViewSortsScopedFamilyState({
|
savedViewSortsScopedFamilyState({
|
||||||
scopeId: viewScopeId,
|
scopeId: viewScopeId,
|
||||||
@ -122,24 +126,99 @@ export const useViewSorts = (viewScopeId: string) => {
|
|||||||
currentViewSorts,
|
currentViewSorts,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[viewScopeId],
|
[
|
||||||
|
apolloClient,
|
||||||
|
createOneMutation,
|
||||||
|
findManyQuery,
|
||||||
|
updateOneMutation,
|
||||||
|
viewScopeId,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const upsertViewSort = (sortToUpsert: Sort) => {
|
const upsertViewSort = useRecoilCallback(
|
||||||
setCurrentViewSorts?.((sorts) => {
|
({ snapshot }) =>
|
||||||
return produce(sorts, (sortsDraft) => {
|
(sortToUpsert: Sort) => {
|
||||||
const index = sortsDraft.findIndex(
|
const currentViewId = snapshot
|
||||||
(sort) => sort.key === sortToUpsert.key,
|
.getLoadable(currentViewIdScopedState({ scopeId: viewScopeId }))
|
||||||
);
|
.getValue();
|
||||||
|
|
||||||
if (index === -1) {
|
if (!currentViewId) {
|
||||||
sortsDraft.push(sortToUpsert);
|
return;
|
||||||
} else {
|
|
||||||
sortsDraft[index] = sortToUpsert;
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return { persistViewSorts, upsertViewSort };
|
const savedViewSortsByKey = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
savedViewSortsByKeyScopedFamilySelector({
|
||||||
|
scopeId: viewScopeId,
|
||||||
|
viewId: currentViewId,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
if (!savedViewSortsByKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onViewSortsChange = snapshot
|
||||||
|
.getLoadable(onViewSortsChangeScopedState({ scopeId: viewScopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const existingSavedSortId =
|
||||||
|
savedViewSortsByKey[sortToUpsert.fieldId]?.id;
|
||||||
|
|
||||||
|
setCurrentViewSorts?.((sorts) => {
|
||||||
|
const newViewSorts = produce(sorts, (sortsDraft) => {
|
||||||
|
const existingSortIndex = sortsDraft.findIndex(
|
||||||
|
(sort) => sort.fieldId === sortToUpsert.fieldId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingSortIndex === -1) {
|
||||||
|
sortsDraft.push({ ...sortToUpsert, id: existingSavedSortId });
|
||||||
|
return sortsDraft;
|
||||||
|
}
|
||||||
|
|
||||||
|
sortsDraft[existingSortIndex] = {
|
||||||
|
...sortToUpsert,
|
||||||
|
id: existingSavedSortId,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
onViewSortsChange?.(newViewSorts);
|
||||||
|
return newViewSorts;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const removeViewSort = useRecoilCallback(
|
||||||
|
({ snapshot }) =>
|
||||||
|
(fieldId: string) => {
|
||||||
|
const currentViewId = snapshot
|
||||||
|
.getLoadable(currentViewIdScopedState({ scopeId: viewScopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
if (!currentViewId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onViewSortsChange = snapshot
|
||||||
|
.getLoadable(onViewSortsChangeScopedState({ scopeId: viewScopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const currentViewSorts = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
currentViewSortsScopedFamilyState({
|
||||||
|
scopeId: viewScopeId,
|
||||||
|
familyKey: currentViewId,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const newViewSorts = currentViewSorts.filter((filter) => {
|
||||||
|
return filter.fieldId !== fieldId;
|
||||||
|
});
|
||||||
|
setCurrentViewSorts?.(newViewSorts);
|
||||||
|
onViewSortsChange?.(newViewSorts);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return { persistViewSorts, upsertViewSort, removeViewSort };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,13 +1,21 @@
|
|||||||
|
import { useApolloClient } from '@apollo/client';
|
||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
|
import { useFindOneMetadataObject } from '@/metadata/hooks/useFindOneMetadataObject';
|
||||||
import { viewObjectIdScopeState } from '@/views/states/viewObjectIdScopeState';
|
import { viewObjectIdScopeState } from '@/views/states/viewObjectIdScopeState';
|
||||||
import { viewTypeScopedState } from '@/views/states/viewTypeScopedState';
|
import { viewTypeScopedState } from '@/views/states/viewTypeScopedState';
|
||||||
import { View } from '@/views/types/View';
|
import { View } from '@/views/types/View';
|
||||||
|
|
||||||
export const useViews = (scopeId: string) => {
|
export const useViews = (scopeId: string) => {
|
||||||
|
const { updateOneMutation, createOneMutation, findManyQuery } =
|
||||||
|
useFindOneMetadataObject({
|
||||||
|
objectNameSingular: 'viewV2',
|
||||||
|
});
|
||||||
|
const apolloClient = useApolloClient();
|
||||||
|
|
||||||
const createView = useRecoilCallback(
|
const createView = useRecoilCallback(
|
||||||
({ snapshot }) =>
|
({ snapshot }) =>
|
||||||
async (_view: Pick<View, 'id' | 'name'>) => {
|
async (view: Pick<View, 'id' | 'name'>) => {
|
||||||
const viewObjectId = await snapshot
|
const viewObjectId = await snapshot
|
||||||
.getLoadable(viewObjectIdScopeState({ scopeId }))
|
.getLoadable(viewObjectIdScopeState({ scopeId }))
|
||||||
.getValue();
|
.getValue();
|
||||||
@ -19,27 +27,31 @@ export const useViews = (scopeId: string) => {
|
|||||||
if (!viewObjectId || !viewType) {
|
if (!viewObjectId || !viewType) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// await createViewMutation({
|
await apolloClient.mutate({
|
||||||
// variables: {
|
mutation: createOneMutation,
|
||||||
// data: {
|
variables: {
|
||||||
// ...view,
|
input: {
|
||||||
// objectId: viewObjectId,
|
...view,
|
||||||
// type: viewType,
|
objectId: viewObjectId,
|
||||||
// },
|
type: viewType,
|
||||||
// },
|
},
|
||||||
// refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
|
},
|
||||||
// });
|
refetchQueries: [findManyQuery],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateView = async (_view: View) => {
|
const updateView = async (view: View) => {
|
||||||
// await updateViewMutation({
|
await apolloClient.mutate({
|
||||||
// variables: {
|
mutation: updateOneMutation,
|
||||||
// data: { name: view.name },
|
variables: {
|
||||||
// where: { id: view.id },
|
idToUpdate: view.id,
|
||||||
// },
|
input: {
|
||||||
// refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
|
...view,
|
||||||
// });
|
},
|
||||||
|
},
|
||||||
|
refetchQueries: [findManyQuery],
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteView = async (_viewId: string) => {
|
const deleteView = async (_viewId: string) => {
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
import { useView } from '@/views/hooks/useView';
|
|
||||||
|
|
||||||
export const useRemoveFilter = () => {
|
|
||||||
const { setCurrentViewFilters } = useView();
|
|
||||||
|
|
||||||
const removeFilter = (filterKey: string) => {
|
|
||||||
setCurrentViewFilters?.((filters) => {
|
|
||||||
return filters.filter((filter) => {
|
|
||||||
return filter.key !== filterKey;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return removeFilter;
|
|
||||||
};
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
import { produce } from 'immer';
|
|
||||||
|
|
||||||
import { Filter } from '@/ui/data/filter/types/Filter';
|
|
||||||
import { useView } from '@/views/hooks/useView';
|
|
||||||
|
|
||||||
export const useUpsertFilter = () => {
|
|
||||||
const { setCurrentViewFilters } = useView();
|
|
||||||
|
|
||||||
const upsertFilter = (filterToUpsert: Filter) => {
|
|
||||||
setCurrentViewFilters?.((filters) => {
|
|
||||||
return produce(filters, (filtersDraft) => {
|
|
||||||
const index = filtersDraft.findIndex(
|
|
||||||
(filter) => filter.key === filterToUpsert.key,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index === -1) {
|
|
||||||
filtersDraft.push(filterToUpsert);
|
|
||||||
} else {
|
|
||||||
filtersDraft[index] = filterToUpsert;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return upsertFilter;
|
|
||||||
};
|
|
||||||
@ -10,8 +10,12 @@ import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsS
|
|||||||
import { currentViewFiltersScopedFamilyState } from '../states/currentViewFiltersScopedFamilyState';
|
import { currentViewFiltersScopedFamilyState } from '../states/currentViewFiltersScopedFamilyState';
|
||||||
import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
|
import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
|
||||||
import { currentViewSortsScopedFamilyState } from '../states/currentViewSortsScopedFamilyState';
|
import { currentViewSortsScopedFamilyState } from '../states/currentViewSortsScopedFamilyState';
|
||||||
|
import { onViewFieldsChangeScopedState } from '../states/onViewFieldsChangeScopedState';
|
||||||
|
import { onViewFiltersChangeScopedState } from '../states/onViewFiltersChangeScopedState';
|
||||||
|
import { onViewSortsChangeScopedState } from '../states/onViewSortsChangeScopedState';
|
||||||
import { savedViewFiltersScopedFamilyState } from '../states/savedViewFiltersScopedFamilyState';
|
import { savedViewFiltersScopedFamilyState } from '../states/savedViewFiltersScopedFamilyState';
|
||||||
import { savedViewSortsScopedFamilyState } from '../states/savedViewSortsScopedFamilyState';
|
import { savedViewSortsScopedFamilyState } from '../states/savedViewSortsScopedFamilyState';
|
||||||
|
import { currentViewScopedSelector } from '../states/selectors/currentViewScopedSelector';
|
||||||
import { viewEditModeScopedState } from '../states/viewEditModeScopedState';
|
import { viewEditModeScopedState } from '../states/viewEditModeScopedState';
|
||||||
import { viewsScopedState } from '../states/viewsScopedState';
|
import { viewsScopedState } from '../states/viewsScopedState';
|
||||||
|
|
||||||
@ -19,7 +23,7 @@ import { useViewFields } from './internal/useViewFields';
|
|||||||
import { useViewFilters } from './internal/useViewFilters';
|
import { useViewFilters } from './internal/useViewFilters';
|
||||||
import { useViews } from './internal/useViews';
|
import { useViews } from './internal/useViews';
|
||||||
import { useViewSorts } from './internal/useViewSorts';
|
import { useViewSorts } from './internal/useViewSorts';
|
||||||
import { useViewStates } from './useViewStates';
|
import { useViewSetStates } from './useViewSetStates';
|
||||||
|
|
||||||
type UseViewProps = {
|
type UseViewProps = {
|
||||||
viewScopeId?: string;
|
viewScopeId?: string;
|
||||||
@ -42,33 +46,81 @@ export const useView = (props?: UseViewProps) => {
|
|||||||
setEntityCountInCurrentView,
|
setEntityCountInCurrentView,
|
||||||
setIsViewBarExpanded,
|
setIsViewBarExpanded,
|
||||||
|
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
setCurrentViewSorts,
|
setCurrentViewSorts,
|
||||||
setSavedViewSorts,
|
setSavedViewSorts,
|
||||||
|
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setCurrentViewFilters,
|
setCurrentViewFilters,
|
||||||
setSavedViewFilters,
|
setSavedViewFilters,
|
||||||
|
|
||||||
setAvailableFields,
|
setAvailableFieldDefinitions,
|
||||||
setCurrentViewFields,
|
setCurrentViewFields,
|
||||||
setSavedViewFields,
|
setSavedViewFields,
|
||||||
} = useViewStates(scopeId);
|
|
||||||
|
|
||||||
const { persistViewSorts, upsertViewSort } = useViewSorts(scopeId);
|
setOnViewFieldsChange,
|
||||||
const { persistViewFilters } = useViewFilters(scopeId);
|
setOnViewFiltersChange,
|
||||||
|
setOnViewSortsChange,
|
||||||
|
} = useViewSetStates(scopeId);
|
||||||
|
|
||||||
|
const { persistViewSorts, upsertViewSort, removeViewSort } =
|
||||||
|
useViewSorts(scopeId);
|
||||||
|
const { persistViewFilters, upsertViewFilter, removeViewFilter } =
|
||||||
|
useViewFilters(scopeId);
|
||||||
const { persistViewFields } = useViewFields(scopeId);
|
const { persistViewFields } = useViewFields(scopeId);
|
||||||
const { createView: internalCreateView, deleteView: internalDeleteView } =
|
const {
|
||||||
useViews(scopeId);
|
createView: internalCreateView,
|
||||||
|
updateView: internalUpdateView,
|
||||||
|
deleteView: internalDeleteView,
|
||||||
|
} = useViews(scopeId);
|
||||||
const [_, setSearchParams] = useSearchParams();
|
const [_, setSearchParams] = useSearchParams();
|
||||||
|
|
||||||
const changeView = useCallback(
|
const changeViewInUrl = useCallback(
|
||||||
(viewId: string) => {
|
(viewId: string) => {
|
||||||
setSearchParams({ view: viewId });
|
setSearchParams({ view: viewId });
|
||||||
},
|
},
|
||||||
[setSearchParams],
|
[setSearchParams],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const loadView = useRecoilCallback(({ snapshot }) => (viewId: string) => {
|
||||||
|
setCurrentViewId?.(viewId);
|
||||||
|
const currentViewFields = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
currentViewFieldsScopedFamilyState({ scopeId, familyKey: viewId }),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const onViewFieldsChange = snapshot
|
||||||
|
.getLoadable(onViewFieldsChangeScopedState({ scopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
onViewFieldsChange?.(currentViewFields);
|
||||||
|
|
||||||
|
const currentViewFilters = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
currentViewFiltersScopedFamilyState({ scopeId, familyKey: viewId }),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const onViewFiltersChange = snapshot
|
||||||
|
.getLoadable(onViewFiltersChangeScopedState({ scopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
onViewFiltersChange?.(currentViewFilters);
|
||||||
|
|
||||||
|
const currentViewSorts = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
currentViewSortsScopedFamilyState({ scopeId, familyKey: viewId }),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
const onViewSortsChange = snapshot
|
||||||
|
.getLoadable(onViewSortsChangeScopedState({ scopeId }))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
onViewSortsChange?.(currentViewSorts);
|
||||||
|
});
|
||||||
|
|
||||||
const resetViewBar = useRecoilCallback(({ snapshot }) => () => {
|
const resetViewBar = useRecoilCallback(({ snapshot }) => () => {
|
||||||
const savedViewFilters = snapshot
|
const savedViewFilters = snapshot
|
||||||
.getLoadable(
|
.getLoadable(
|
||||||
@ -95,7 +147,6 @@ export const useView = (props?: UseViewProps) => {
|
|||||||
setCurrentViewSorts?.(savedViewSorts);
|
setCurrentViewSorts?.(savedViewSorts);
|
||||||
}
|
}
|
||||||
setViewEditMode?.('none');
|
setViewEditMode?.('none');
|
||||||
setIsViewBarExpanded?.(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const createView = useRecoilCallback(
|
const createView = useRecoilCallback(
|
||||||
@ -156,10 +207,10 @@ export const useView = (props?: UseViewProps) => {
|
|||||||
await persistViewFilters(newViewId);
|
await persistViewFilters(newViewId);
|
||||||
await persistViewSorts(newViewId);
|
await persistViewSorts(newViewId);
|
||||||
|
|
||||||
changeView(newViewId);
|
changeViewInUrl(newViewId);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
changeView,
|
changeViewInUrl,
|
||||||
currentViewId,
|
currentViewId,
|
||||||
internalCreateView,
|
internalCreateView,
|
||||||
persistViewFields,
|
persistViewFields,
|
||||||
@ -195,15 +246,32 @@ export const useView = (props?: UseViewProps) => {
|
|||||||
const handleViewNameSubmit = useRecoilCallback(
|
const handleViewNameSubmit = useRecoilCallback(
|
||||||
({ snapshot }) =>
|
({ snapshot }) =>
|
||||||
async (name?: string) => {
|
async (name?: string) => {
|
||||||
|
if (!name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const viewEditMode = snapshot
|
const viewEditMode = snapshot
|
||||||
.getLoadable(viewEditModeScopedState({ scopeId }))
|
.getLoadable(viewEditModeScopedState({ scopeId }))
|
||||||
.getValue();
|
.getValue();
|
||||||
|
|
||||||
|
const currentView = snapshot
|
||||||
|
.getLoadable(currentViewScopedSelector(scopeId))
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
if (!currentView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (viewEditMode === 'create' && name) {
|
if (viewEditMode === 'create' && name) {
|
||||||
await createView(name);
|
await createView(name);
|
||||||
|
} else {
|
||||||
|
await internalUpdateView({
|
||||||
|
...currentView,
|
||||||
|
name,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[createView, scopeId],
|
[createView, internalUpdateView, scopeId],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -224,20 +292,28 @@ export const useView = (props?: UseViewProps) => {
|
|||||||
setViewType,
|
setViewType,
|
||||||
setEntityCountInCurrentView,
|
setEntityCountInCurrentView,
|
||||||
|
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
setCurrentViewSorts,
|
setCurrentViewSorts,
|
||||||
setSavedViewSorts,
|
setSavedViewSorts,
|
||||||
upsertViewSort,
|
upsertViewSort,
|
||||||
|
removeViewSort,
|
||||||
|
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setCurrentViewFilters,
|
setCurrentViewFilters,
|
||||||
setSavedViewFilters,
|
setSavedViewFilters,
|
||||||
|
upsertViewFilter,
|
||||||
|
removeViewFilter,
|
||||||
|
|
||||||
setAvailableFields,
|
setAvailableFieldDefinitions,
|
||||||
setCurrentViewFields,
|
setCurrentViewFields,
|
||||||
setSavedViewFields,
|
setSavedViewFields,
|
||||||
|
|
||||||
persistViewFields,
|
persistViewFields,
|
||||||
changeView,
|
changeViewInUrl,
|
||||||
|
loadView,
|
||||||
|
|
||||||
|
setOnViewFieldsChange,
|
||||||
|
setOnViewFiltersChange,
|
||||||
|
setOnViewSortsChange,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,9 +5,9 @@ import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRec
|
|||||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||||
|
|
||||||
import { ViewScopeInternalContext } from '../scopes/scope-internal-context/ViewScopeInternalContext';
|
import { ViewScopeInternalContext } from '../scopes/scope-internal-context/ViewScopeInternalContext';
|
||||||
import { availableFieldsScopedState } from '../states/availableFieldsScopedState';
|
import { availableFieldDefinitionsScopedState } from '../states/availableFieldDefinitionsScopedState';
|
||||||
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
|
import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState';
|
||||||
import { availableSortsScopedState } from '../states/availableSortsScopedState';
|
import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState';
|
||||||
import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsScopedFamilyState';
|
import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsScopedFamilyState';
|
||||||
import { currentViewFiltersScopedFamilyState } from '../states/currentViewFiltersScopedFamilyState';
|
import { currentViewFiltersScopedFamilyState } from '../states/currentViewFiltersScopedFamilyState';
|
||||||
import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
|
import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
|
||||||
@ -31,17 +31,14 @@ import { viewObjectIdScopeState } from '../states/viewObjectIdScopeState';
|
|||||||
import { viewsScopedState } from '../states/viewsScopedState';
|
import { viewsScopedState } from '../states/viewsScopedState';
|
||||||
import { viewTypeScopedState } from '../states/viewTypeScopedState';
|
import { viewTypeScopedState } from '../states/viewTypeScopedState';
|
||||||
|
|
||||||
export const useViewInternalStates = (
|
export const useViewGetStates = (viewScopeId?: string, viewId?: string) => {
|
||||||
viewScopeId?: string,
|
|
||||||
viewId?: string,
|
|
||||||
) => {
|
|
||||||
const scopeId = useAvailableScopeIdOrThrow(
|
const scopeId = useAvailableScopeIdOrThrow(
|
||||||
ViewScopeInternalContext,
|
ViewScopeInternalContext,
|
||||||
viewScopeId,
|
viewScopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// View
|
// View
|
||||||
const [currentViewId, setCurrentViewId] = useRecoilScopedStateV2(
|
const [currentViewId] = useRecoilScopedStateV2(
|
||||||
currentViewIdScopedState,
|
currentViewIdScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
@ -50,39 +47,38 @@ export const useViewInternalStates = (
|
|||||||
|
|
||||||
const currentView = useRecoilValue(currentViewScopedSelector(scopeId));
|
const currentView = useRecoilValue(currentViewScopedSelector(scopeId));
|
||||||
|
|
||||||
const [viewEditMode, setViewEditMode] = useRecoilScopedStateV2(
|
const [viewEditMode] = useRecoilScopedStateV2(
|
||||||
viewEditModeScopedState,
|
viewEditModeScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [views, setViews] = useRecoilScopedStateV2(viewsScopedState, scopeId);
|
const [views] = useRecoilScopedStateV2(viewsScopedState, scopeId);
|
||||||
|
|
||||||
const [viewObjectId, setViewObjectId] = useRecoilScopedStateV2(
|
const [viewObjectId] = useRecoilScopedStateV2(
|
||||||
viewObjectIdScopeState,
|
viewObjectIdScopeState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [viewType, setViewType] = useRecoilScopedStateV2(
|
const [viewType] = useRecoilScopedStateV2(viewTypeScopedState, scopeId);
|
||||||
viewTypeScopedState,
|
|
||||||
|
const [entityCountInCurrentView] = useRecoilScopedStateV2(
|
||||||
|
entityCountInCurrentViewScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [entityCountInCurrentView, setEntityCountInCurrentView] =
|
const [isViewBarExpanded] = useRecoilScopedStateV2(
|
||||||
useRecoilScopedStateV2(entityCountInCurrentViewScopedState, scopeId);
|
|
||||||
|
|
||||||
const [isViewBarExpanded, setIsViewBarExpanded] = useRecoilScopedStateV2(
|
|
||||||
isViewBarExpandedScopedState,
|
isViewBarExpandedScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ViewSorts
|
// ViewSorts
|
||||||
const [currentViewSorts, setCurrentViewSorts] = useRecoilScopedFamilyState(
|
const [currentViewSorts] = useRecoilScopedFamilyState(
|
||||||
currentViewSortsScopedFamilyState,
|
currentViewSortsScopedFamilyState,
|
||||||
scopeId,
|
scopeId,
|
||||||
familyItemId,
|
familyItemId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [savedViewSorts, setSavedViewSorts] = useRecoilScopedFamilyState(
|
const [savedViewSorts] = useRecoilScopedFamilyState(
|
||||||
savedViewSortsScopedFamilyState,
|
savedViewSortsScopedFamilyState,
|
||||||
scopeId,
|
scopeId,
|
||||||
familyItemId,
|
familyItemId,
|
||||||
@ -95,8 +91,8 @@ export const useViewInternalStates = (
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const [availableSorts, setAvailableSorts] = useRecoilScopedStateV2(
|
const [availableSortDefinitions] = useRecoilScopedStateV2(
|
||||||
availableSortsScopedState,
|
availableSortDefinitionsScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -108,14 +104,13 @@ export const useViewInternalStates = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
// ViewFilters
|
// ViewFilters
|
||||||
const [currentViewFilters, setCurrentViewFilters] =
|
const [currentViewFilters] = useRecoilScopedFamilyState(
|
||||||
useRecoilScopedFamilyState(
|
currentViewFiltersScopedFamilyState,
|
||||||
currentViewFiltersScopedFamilyState,
|
scopeId,
|
||||||
scopeId,
|
familyItemId,
|
||||||
familyItemId,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
const [savedViewFilters, setSavedViewFilters] = useRecoilScopedFamilyState(
|
const [savedViewFilters] = useRecoilScopedFamilyState(
|
||||||
savedViewFiltersScopedFamilyState,
|
savedViewFiltersScopedFamilyState,
|
||||||
scopeId,
|
scopeId,
|
||||||
familyItemId,
|
familyItemId,
|
||||||
@ -128,8 +123,8 @@ export const useViewInternalStates = (
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const [availableFilters, setAvailableFilters] = useRecoilScopedStateV2(
|
const [availableFilterDefinitions] = useRecoilScopedStateV2(
|
||||||
availableFiltersScopedState,
|
availableFilterDefinitionsScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -141,18 +136,18 @@ export const useViewInternalStates = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
// ViewFields
|
// ViewFields
|
||||||
const [availableFields, setAvailableFields] = useRecoilScopedStateV2(
|
const [availableFieldDefinitions] = useRecoilScopedStateV2(
|
||||||
availableFieldsScopedState,
|
availableFieldDefinitionsScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [currentViewFields, setCurrentViewFields] = useRecoilScopedFamilyState(
|
const [currentViewFields] = useRecoilScopedFamilyState(
|
||||||
currentViewFieldsScopedFamilyState,
|
currentViewFieldsScopedFamilyState,
|
||||||
scopeId,
|
scopeId,
|
||||||
familyItemId,
|
familyItemId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [savedViewFields, setSavedViewFields] = useRecoilScopedFamilyState(
|
const [savedViewFields] = useRecoilScopedFamilyState(
|
||||||
savedViewFieldsScopedFamilyState,
|
savedViewFieldsScopedFamilyState,
|
||||||
scopeId,
|
scopeId,
|
||||||
familyItemId,
|
familyItemId,
|
||||||
@ -166,17 +161,17 @@ export const useViewInternalStates = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
// ViewChangeHandlers
|
// ViewChangeHandlers
|
||||||
const [onViewSortsChange, setOnViewSortsChange] = useRecoilScopedStateV2(
|
const [onViewSortsChange] = useRecoilScopedStateV2(
|
||||||
onViewSortsChangeScopedState,
|
onViewSortsChangeScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [onViewFiltersChange, setOnViewFiltersChange] = useRecoilScopedStateV2(
|
const [onViewFiltersChange] = useRecoilScopedStateV2(
|
||||||
onViewFiltersChangeScopedState,
|
onViewFiltersChangeScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [onViewFieldsChange, setOnViewFieldsChange] = useRecoilScopedStateV2(
|
const [onViewFieldsChange] = useRecoilScopedStateV2(
|
||||||
onViewFieldsChangeScopedState,
|
onViewFieldsChangeScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
@ -184,52 +179,33 @@ export const useViewInternalStates = (
|
|||||||
return {
|
return {
|
||||||
currentViewId,
|
currentViewId,
|
||||||
currentView,
|
currentView,
|
||||||
setCurrentViewId,
|
|
||||||
isViewBarExpanded,
|
isViewBarExpanded,
|
||||||
setIsViewBarExpanded,
|
|
||||||
|
|
||||||
views,
|
views,
|
||||||
setViews,
|
|
||||||
viewEditMode,
|
viewEditMode,
|
||||||
setViewEditMode,
|
|
||||||
viewObjectId,
|
viewObjectId,
|
||||||
setViewObjectId,
|
|
||||||
viewType,
|
viewType,
|
||||||
setViewType,
|
|
||||||
entityCountInCurrentView,
|
entityCountInCurrentView,
|
||||||
setEntityCountInCurrentView,
|
|
||||||
|
|
||||||
availableSorts,
|
availableSortDefinitions,
|
||||||
setAvailableSorts,
|
|
||||||
currentViewSorts,
|
currentViewSorts,
|
||||||
setCurrentViewSorts,
|
|
||||||
savedViewSorts,
|
savedViewSorts,
|
||||||
savedViewSortsByKey,
|
savedViewSortsByKey,
|
||||||
setSavedViewSorts,
|
|
||||||
canPersistSorts,
|
canPersistSorts,
|
||||||
|
|
||||||
availableFilters,
|
availableFilterDefinitions,
|
||||||
setAvailableFilters,
|
|
||||||
currentViewFilters,
|
currentViewFilters,
|
||||||
setCurrentViewFilters,
|
|
||||||
savedViewFilters,
|
savedViewFilters,
|
||||||
savedViewFiltersByKey,
|
savedViewFiltersByKey,
|
||||||
setSavedViewFilters,
|
|
||||||
canPersistFilters,
|
canPersistFilters,
|
||||||
|
|
||||||
availableFields,
|
availableFieldDefinitions,
|
||||||
setAvailableFields,
|
|
||||||
currentViewFields,
|
currentViewFields,
|
||||||
savedViewFieldsByKey,
|
savedViewFieldsByKey,
|
||||||
setCurrentViewFields,
|
|
||||||
savedViewFields,
|
savedViewFields,
|
||||||
setSavedViewFields,
|
|
||||||
|
|
||||||
onViewSortsChange,
|
onViewSortsChange,
|
||||||
setOnViewSortsChange,
|
|
||||||
onViewFiltersChange,
|
onViewFiltersChange,
|
||||||
setOnViewFiltersChange,
|
|
||||||
onViewFieldsChange,
|
onViewFieldsChange,
|
||||||
setOnViewFieldsChange,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -4,15 +4,18 @@ import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/use
|
|||||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||||
|
|
||||||
import { ViewScopeInternalContext } from '../scopes/scope-internal-context/ViewScopeInternalContext';
|
import { ViewScopeInternalContext } from '../scopes/scope-internal-context/ViewScopeInternalContext';
|
||||||
import { availableFieldsScopedState } from '../states/availableFieldsScopedState';
|
import { availableFieldDefinitionsScopedState } from '../states/availableFieldDefinitionsScopedState';
|
||||||
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
|
import { availableFilterDefinitionsScopedState } from '../states/availableFilterDefinitionsScopedState';
|
||||||
import { availableSortsScopedState } from '../states/availableSortsScopedState';
|
import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState';
|
||||||
import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsScopedFamilyState';
|
import { currentViewFieldsScopedFamilyState } from '../states/currentViewFieldsScopedFamilyState';
|
||||||
import { currentViewFiltersScopedFamilyState } from '../states/currentViewFiltersScopedFamilyState';
|
import { currentViewFiltersScopedFamilyState } from '../states/currentViewFiltersScopedFamilyState';
|
||||||
import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
|
import { currentViewIdScopedState } from '../states/currentViewIdScopedState';
|
||||||
import { currentViewSortsScopedFamilyState } from '../states/currentViewSortsScopedFamilyState';
|
import { currentViewSortsScopedFamilyState } from '../states/currentViewSortsScopedFamilyState';
|
||||||
import { entityCountInCurrentViewScopedState } from '../states/entityCountInCurrentViewScopedState';
|
import { entityCountInCurrentViewScopedState } from '../states/entityCountInCurrentViewScopedState';
|
||||||
import { isViewBarExpandedScopedState } from '../states/isViewBarExpandedScopedState';
|
import { isViewBarExpandedScopedState } from '../states/isViewBarExpandedScopedState';
|
||||||
|
import { onViewFieldsChangeScopedState } from '../states/onViewFieldsChangeScopedState';
|
||||||
|
import { onViewFiltersChangeScopedState } from '../states/onViewFiltersChangeScopedState';
|
||||||
|
import { onViewSortsChangeScopedState } from '../states/onViewSortsChangeScopedState';
|
||||||
import { savedViewFieldsScopedFamilyState } from '../states/savedViewFieldsScopedFamilyState';
|
import { savedViewFieldsScopedFamilyState } from '../states/savedViewFieldsScopedFamilyState';
|
||||||
import { savedViewFiltersScopedFamilyState } from '../states/savedViewFiltersScopedFamilyState';
|
import { savedViewFiltersScopedFamilyState } from '../states/savedViewFiltersScopedFamilyState';
|
||||||
import { savedViewSortsScopedFamilyState } from '../states/savedViewSortsScopedFamilyState';
|
import { savedViewSortsScopedFamilyState } from '../states/savedViewSortsScopedFamilyState';
|
||||||
@ -21,7 +24,7 @@ import { viewObjectIdScopeState } from '../states/viewObjectIdScopeState';
|
|||||||
import { viewsScopedState } from '../states/viewsScopedState';
|
import { viewsScopedState } from '../states/viewsScopedState';
|
||||||
import { viewTypeScopedState } from '../states/viewTypeScopedState';
|
import { viewTypeScopedState } from '../states/viewTypeScopedState';
|
||||||
|
|
||||||
export const useViewStates = (viewScopeId?: string, viewId?: string) => {
|
export const useViewSetStates = (viewScopeId?: string, viewId?: string) => {
|
||||||
const scopeId = useAvailableScopeIdOrThrow(
|
const scopeId = useAvailableScopeIdOrThrow(
|
||||||
ViewScopeInternalContext,
|
ViewScopeInternalContext,
|
||||||
viewScopeId,
|
viewScopeId,
|
||||||
@ -71,8 +74,8 @@ export const useViewStates = (viewScopeId?: string, viewId?: string) => {
|
|||||||
familyItemId,
|
familyItemId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const setAvailableSorts = useSetRecoilScopedStateV2(
|
const setAvailableSortDefinitions = useSetRecoilScopedStateV2(
|
||||||
availableSortsScopedState,
|
availableSortDefinitionsScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -89,14 +92,14 @@ export const useViewStates = (viewScopeId?: string, viewId?: string) => {
|
|||||||
familyItemId,
|
familyItemId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const setAvailableFilters = useSetRecoilScopedStateV2(
|
const setAvailableFilterDefinitions = useSetRecoilScopedStateV2(
|
||||||
availableFiltersScopedState,
|
availableFilterDefinitionsScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ViewFields
|
// ViewFields
|
||||||
const setAvailableFields = useSetRecoilScopedStateV2(
|
const setAvailableFieldDefinitions = useSetRecoilScopedStateV2(
|
||||||
availableFieldsScopedState,
|
availableFieldDefinitionsScopedState,
|
||||||
scopeId,
|
scopeId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -112,6 +115,21 @@ export const useViewStates = (viewScopeId?: string, viewId?: string) => {
|
|||||||
familyItemId,
|
familyItemId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setOnViewFieldsChange = useSetRecoilScopedStateV2(
|
||||||
|
onViewFieldsChangeScopedState,
|
||||||
|
scopeId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const setOnViewFiltersChange = useSetRecoilScopedStateV2(
|
||||||
|
onViewFiltersChangeScopedState,
|
||||||
|
scopeId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const setOnViewSortsChange = useSetRecoilScopedStateV2(
|
||||||
|
onViewSortsChangeScopedState,
|
||||||
|
scopeId,
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentViewId,
|
currentViewId,
|
||||||
setCurrentViewId,
|
setCurrentViewId,
|
||||||
@ -123,16 +141,20 @@ export const useViewStates = (viewScopeId?: string, viewId?: string) => {
|
|||||||
setViewEditMode,
|
setViewEditMode,
|
||||||
setEntityCountInCurrentView,
|
setEntityCountInCurrentView,
|
||||||
|
|
||||||
setAvailableSorts,
|
setAvailableSortDefinitions,
|
||||||
setCurrentViewSorts,
|
setCurrentViewSorts,
|
||||||
setSavedViewSorts,
|
setSavedViewSorts,
|
||||||
|
|
||||||
setAvailableFilters,
|
setAvailableFilterDefinitions,
|
||||||
setCurrentViewFilters,
|
setCurrentViewFilters,
|
||||||
setSavedViewFilters,
|
setSavedViewFilters,
|
||||||
|
|
||||||
setAvailableFields,
|
setAvailableFieldDefinitions,
|
||||||
setCurrentViewFields,
|
setCurrentViewFields,
|
||||||
setSavedViewFields,
|
setSavedViewFields,
|
||||||
|
|
||||||
|
setOnViewFieldsChange,
|
||||||
|
setOnViewFiltersChange,
|
||||||
|
setOnViewSortsChange,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -3,7 +3,6 @@ import { useEffect } from 'react';
|
|||||||
import { Filter } from '@/ui/data/filter/types/Filter';
|
import { Filter } from '@/ui/data/filter/types/Filter';
|
||||||
import { Sort } from '@/ui/data/sort/types/Sort';
|
import { Sort } from '@/ui/data/sort/types/Sort';
|
||||||
import { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { useViewInternalStates } from '@/views/hooks/useViewInternalStates';
|
|
||||||
import { ViewField } from '@/views/types/ViewField';
|
import { ViewField } from '@/views/types/ViewField';
|
||||||
|
|
||||||
type ViewScopeInitEffectProps = {
|
type ViewScopeInitEffectProps = {
|
||||||
@ -14,17 +13,15 @@ type ViewScopeInitEffectProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ViewScopeInitEffect = ({
|
export const ViewScopeInitEffect = ({
|
||||||
viewScopeId,
|
|
||||||
onViewSortsChange,
|
onViewSortsChange,
|
||||||
onViewFiltersChange,
|
onViewFiltersChange,
|
||||||
onViewFieldsChange,
|
onViewFieldsChange,
|
||||||
}: ViewScopeInitEffectProps) => {
|
}: ViewScopeInitEffectProps) => {
|
||||||
const { currentViewId } = useView();
|
|
||||||
const {
|
const {
|
||||||
setOnViewSortsChange,
|
setOnViewSortsChange,
|
||||||
setOnViewFieldsChange,
|
setOnViewFieldsChange,
|
||||||
setOnViewFiltersChange,
|
setOnViewFiltersChange,
|
||||||
} = useViewInternalStates(viewScopeId, currentViewId);
|
} = useView();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setOnViewSortsChange(() => onViewSortsChange);
|
setOnViewSortsChange(() => onViewSortsChange);
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
|
|||||||
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
|
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
|
||||||
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
|
||||||
export const availableFieldsScopedState = createScopedState<
|
export const availableFieldDefinitionsScopedState = createScopedState<
|
||||||
ColumnDefinition<FieldMetadata>[]
|
ColumnDefinition<FieldMetadata>[]
|
||||||
>({
|
>({
|
||||||
key: 'availableFieldsScopedState',
|
key: 'availableFieldDefinitionsScopedState',
|
||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
});
|
});
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
||||||
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
|
||||||
export const availableFiltersScopedState = createScopedState<
|
export const availableFilterDefinitionsScopedState = createScopedState<
|
||||||
FilterDefinition[]
|
FilterDefinition[]
|
||||||
>({
|
>({
|
||||||
key: 'availableFiltersScopedState',
|
key: 'availableFilterDefinitionsScopedState',
|
||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
});
|
});
|
||||||
@ -1,7 +1,9 @@
|
|||||||
import { SortDefinition } from '@/ui/data/sort/types/SortDefinition';
|
import { SortDefinition } from '@/ui/data/sort/types/SortDefinition';
|
||||||
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
|
||||||
|
|
||||||
export const availableSortsScopedState = createScopedState<SortDefinition[]>({
|
export const availableSortDefinitionsScopedState = createScopedState<
|
||||||
key: 'availableSortsScopedState',
|
SortDefinition[]
|
||||||
|
>({
|
||||||
|
key: 'availableSortDefinitionsScopedState',
|
||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
});
|
});
|
||||||
@ -1,8 +1,9 @@
|
|||||||
import { Filter } from '@/ui/data/filter/types/Filter';
|
|
||||||
import { createScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/createScopedFamilyState';
|
import { createScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/createScopedFamilyState';
|
||||||
|
|
||||||
|
import { ViewFilter } from '../types/ViewFilter';
|
||||||
|
|
||||||
export const currentViewFiltersScopedFamilyState = createScopedFamilyState<
|
export const currentViewFiltersScopedFamilyState = createScopedFamilyState<
|
||||||
Filter[],
|
ViewFilter[],
|
||||||
string
|
string
|
||||||
>({
|
>({
|
||||||
key: 'currentViewFiltersScopedFamilyState',
|
key: 'currentViewFiltersScopedFamilyState',
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { Sort } from '@/ui/data/sort/types/Sort';
|
|
||||||
import { createScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/createScopedFamilyState';
|
import { createScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/createScopedFamilyState';
|
||||||
|
|
||||||
|
import { ViewSort } from '../types/ViewSort';
|
||||||
|
|
||||||
export const currentViewSortsScopedFamilyState = createScopedFamilyState<
|
export const currentViewSortsScopedFamilyState = createScopedFamilyState<
|
||||||
Sort[],
|
ViewSort[],
|
||||||
string
|
string
|
||||||
>({
|
>({
|
||||||
key: 'currentViewSortsScopedFamilyState',
|
key: 'currentViewSortsScopedFamilyState',
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { Filter } from '@/ui/data/filter/types/Filter';
|
|
||||||
import { createScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/createScopedFamilyState';
|
import { createScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/createScopedFamilyState';
|
||||||
|
|
||||||
|
import { ViewFilter } from '../types/ViewFilter';
|
||||||
|
|
||||||
export const savedViewFiltersScopedFamilyState = createScopedFamilyState<
|
export const savedViewFiltersScopedFamilyState = createScopedFamilyState<
|
||||||
Filter[],
|
ViewFilter[],
|
||||||
string
|
string
|
||||||
>({
|
>({
|
||||||
key: 'savedViewFiltersScopedFamilyState',
|
key: 'savedViewFiltersScopedFamilyState',
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { Sort } from '@/ui/data/sort/types/Sort';
|
|
||||||
import { createScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/createScopedFamilyState';
|
import { createScopedFamilyState } from '@/ui/utilities/recoil-scope/utils/createScopedFamilyState';
|
||||||
|
|
||||||
|
import { ViewSort } from '../types/ViewSort';
|
||||||
|
|
||||||
export const savedViewSortsScopedFamilyState = createScopedFamilyState<
|
export const savedViewSortsScopedFamilyState = createScopedFamilyState<
|
||||||
Sort[],
|
ViewSort[],
|
||||||
string
|
string
|
||||||
>({
|
>({
|
||||||
key: 'savedViewSortsScopedFamilyState',
|
key: 'savedViewSortsScopedFamilyState',
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { selectorFamily } from 'recoil';
|
import { selectorFamily } from 'recoil';
|
||||||
|
|
||||||
import { Filter } from '@/ui/data/filter/types/Filter';
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
|
|
||||||
import { savedViewFiltersScopedFamilyState } from '../savedViewFiltersScopedFamilyState';
|
import { savedViewFiltersScopedFamilyState } from '../savedViewFiltersScopedFamilyState';
|
||||||
|
|
||||||
@ -17,8 +17,8 @@ export const savedViewFiltersByKeyScopedFamilySelector = selectorFamily({
|
|||||||
scopeId: scopeId,
|
scopeId: scopeId,
|
||||||
familyKey: viewId,
|
familyKey: viewId,
|
||||||
}),
|
}),
|
||||||
).reduce<Record<string, Filter>>(
|
).reduce<Record<string, ViewFilter>>(
|
||||||
(result, filter) => ({ ...result, [filter.key]: filter }),
|
(result, filter) => ({ ...result, [filter.fieldId]: filter }),
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { selectorFamily } from 'recoil';
|
import { selectorFamily } from 'recoil';
|
||||||
|
|
||||||
import { Sort } from '@/ui/data/sort/types/Sort';
|
import { ViewSort } from '@/views/types/ViewSort';
|
||||||
|
|
||||||
import { savedViewSortsScopedFamilyState } from '../savedViewSortsScopedFamilyState';
|
import { savedViewSortsScopedFamilyState } from '../savedViewSortsScopedFamilyState';
|
||||||
|
|
||||||
@ -17,8 +17,8 @@ export const savedViewSortsByKeyScopedFamilySelector = selectorFamily({
|
|||||||
scopeId: scopeId,
|
scopeId: scopeId,
|
||||||
familyKey: viewId,
|
familyKey: viewId,
|
||||||
}),
|
}),
|
||||||
).reduce<Record<string, Sort>>(
|
).reduce<Record<string, ViewSort>>(
|
||||||
(result, sort) => ({ ...result, [sort.key]: sort }),
|
(result, sort) => ({ ...result, [sort.fieldId]: sort }),
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
|
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
|
||||||
|
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
|
||||||
|
|
||||||
export type ViewField = {
|
export type ViewField = {
|
||||||
id: string;
|
id: string;
|
||||||
fieldId: string;
|
fieldId: string;
|
||||||
position: number;
|
position: number;
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
size: number;
|
size: number;
|
||||||
|
definition: ColumnDefinition<FieldMetadata>;
|
||||||
};
|
};
|
||||||
|
|||||||
12
front/src/modules/views/types/ViewFilter.ts
Normal file
12
front/src/modules/views/types/ViewFilter.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
|
||||||
|
|
||||||
|
import { ViewFilterOperand } from './ViewFilterOperand';
|
||||||
|
|
||||||
|
export type ViewFilter = {
|
||||||
|
id?: string;
|
||||||
|
fieldId: string;
|
||||||
|
operand: ViewFilterOperand;
|
||||||
|
value: string;
|
||||||
|
displayValue: string;
|
||||||
|
definition: FilterDefinition;
|
||||||
|
};
|
||||||
9
front/src/modules/views/types/ViewSort.ts
Normal file
9
front/src/modules/views/types/ViewSort.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { SortDefinition } from '@/ui/data/sort/types/SortDefinition';
|
||||||
|
import { SortDirection } from '@/ui/data/sort/types/SortDirection';
|
||||||
|
|
||||||
|
export type ViewSort = {
|
||||||
|
id?: string;
|
||||||
|
fieldId: string;
|
||||||
|
direction: SortDirection;
|
||||||
|
definition: SortDefinition;
|
||||||
|
};
|
||||||
@ -12,5 +12,6 @@ export const columnDefinitionsToViewFields = (
|
|||||||
position: columnDefinition.position,
|
position: columnDefinition.position,
|
||||||
size: columnDefinition.size,
|
size: columnDefinition.size,
|
||||||
isVisible: columnDefinition.isVisible ?? true,
|
isVisible: columnDefinition.isVisible ?? true,
|
||||||
|
definition: columnDefinition,
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
|
||||||
|
import { BoardFieldDefinition } from '@/ui/layout/board/types/BoardFieldDefinition';
|
||||||
|
import { assertNotNull } from '~/utils/assert';
|
||||||
|
|
||||||
|
import { ViewField } from '../types/ViewField';
|
||||||
|
|
||||||
|
export const viewFieldsToBoardFieldDefinitions = (
|
||||||
|
viewFields: ViewField[],
|
||||||
|
fieldsMetadata: BoardFieldDefinition<FieldMetadata>[],
|
||||||
|
): BoardFieldDefinition<FieldMetadata>[] => {
|
||||||
|
return viewFields
|
||||||
|
.map((viewField) => {
|
||||||
|
const correspondingFieldMetadata = fieldsMetadata.find(
|
||||||
|
({ fieldId }) => viewField.fieldId === fieldId,
|
||||||
|
);
|
||||||
|
|
||||||
|
return correspondingFieldMetadata
|
||||||
|
? {
|
||||||
|
fieldId: viewField.fieldId,
|
||||||
|
label: correspondingFieldMetadata.label,
|
||||||
|
metadata: correspondingFieldMetadata.metadata,
|
||||||
|
entityChipDisplayMapper:
|
||||||
|
correspondingFieldMetadata.entityChipDisplayMapper,
|
||||||
|
infoTooltipContent: correspondingFieldMetadata.infoTooltipContent,
|
||||||
|
basePathToShowPage: correspondingFieldMetadata.basePathToShowPage,
|
||||||
|
Icon: correspondingFieldMetadata.Icon,
|
||||||
|
type: correspondingFieldMetadata.type,
|
||||||
|
position: viewField.position,
|
||||||
|
isVisible: viewField.isVisible,
|
||||||
|
viewFieldId: viewField.id,
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
})
|
||||||
|
.filter(assertNotNull);
|
||||||
|
};
|
||||||
15
front/src/modules/views/utils/viewFiltersToFilters.ts
Normal file
15
front/src/modules/views/utils/viewFiltersToFilters.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Filter } from '@/ui/data/filter/types/Filter';
|
||||||
|
|
||||||
|
import { ViewFilter } from '../types/ViewFilter';
|
||||||
|
|
||||||
|
export const viewFiltersToFilters = (viewFilters: ViewFilter[]): Filter[] => {
|
||||||
|
return viewFilters.map((viewFilter) => {
|
||||||
|
return {
|
||||||
|
fieldId: viewFilter.fieldId,
|
||||||
|
value: viewFilter.value,
|
||||||
|
displayValue: viewFilter.displayValue,
|
||||||
|
operand: viewFilter.operand,
|
||||||
|
definition: viewFilter.definition,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
13
front/src/modules/views/utils/viewSortsToSorts.ts
Normal file
13
front/src/modules/views/utils/viewSortsToSorts.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Sort } from '@/ui/data/sort/types/Sort';
|
||||||
|
|
||||||
|
import { ViewSort } from '../types/ViewSort';
|
||||||
|
|
||||||
|
export const viewSortsToSorts = (viewSorts: ViewSort[]): Sort[] => {
|
||||||
|
return viewSorts.map((viewSort) => {
|
||||||
|
return {
|
||||||
|
fieldId: viewSort.fieldId,
|
||||||
|
direction: viewSort.direction,
|
||||||
|
definition: viewSort.definition,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
@ -28,7 +28,7 @@ import { getLogoUrlFromDomainName } from '~/utils';
|
|||||||
import { CompanyNameEditableField } from '../../modules/companies/editable-field/components/CompanyNameEditableField';
|
import { CompanyNameEditableField } from '../../modules/companies/editable-field/components/CompanyNameEditableField';
|
||||||
import { ShowPageContainer } from '../../modules/ui/layout/page/ShowPageContainer';
|
import { ShowPageContainer } from '../../modules/ui/layout/page/ShowPageContainer';
|
||||||
|
|
||||||
import { companyShowFieldDefinition } from './constants/companyShowFieldDefinition';
|
import { companyShowFieldDefinitions } from './constants/companyShowFieldDefinitions';
|
||||||
|
|
||||||
export const CompanyShow = () => {
|
export const CompanyShow = () => {
|
||||||
const companyId = useParams().companyId ?? '';
|
const companyId = useParams().companyId ?? '';
|
||||||
@ -90,7 +90,7 @@ export const CompanyShow = () => {
|
|||||||
avatarType="squared"
|
avatarType="squared"
|
||||||
/>
|
/>
|
||||||
<PropertyBox extraPadding={true}>
|
<PropertyBox extraPadding={true}>
|
||||||
{companyShowFieldDefinition.map((fieldDefinition) => {
|
{companyShowFieldDefinitions.map((fieldDefinition) => {
|
||||||
return (
|
return (
|
||||||
<FieldContext.Provider
|
<FieldContext.Provider
|
||||||
key={company.id + fieldDefinition.fieldId}
|
key={company.id + fieldDefinition.fieldId}
|
||||||
|
|||||||
@ -1,51 +0,0 @@
|
|||||||
import { FilterDefinitionByEntity } from '@/ui/data/filter/types/FilterDefinitionByEntity';
|
|
||||||
import {
|
|
||||||
IconBuildingSkyscraper,
|
|
||||||
IconCalendarEvent,
|
|
||||||
IconLink,
|
|
||||||
IconMap,
|
|
||||||
IconUser,
|
|
||||||
IconUsers,
|
|
||||||
} from '@/ui/display/icon/index';
|
|
||||||
import { FilterDropdownUserSearchSelect } from '@/users/components/FilterDropdownUserSearchSelect';
|
|
||||||
import { Company } from '~/generated/graphql';
|
|
||||||
|
|
||||||
export const companyAvailableFilters: FilterDefinitionByEntity<Company>[] = [
|
|
||||||
{
|
|
||||||
key: 'name',
|
|
||||||
label: 'Name',
|
|
||||||
Icon: IconBuildingSkyscraper,
|
|
||||||
type: 'text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'employees',
|
|
||||||
label: 'Employees',
|
|
||||||
Icon: IconUsers,
|
|
||||||
type: 'number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'domainName',
|
|
||||||
label: 'URL',
|
|
||||||
Icon: IconLink,
|
|
||||||
type: 'text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'address',
|
|
||||||
label: 'Address',
|
|
||||||
Icon: IconMap,
|
|
||||||
type: 'text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'createdAt',
|
|
||||||
label: 'Created at',
|
|
||||||
Icon: IconCalendarEvent,
|
|
||||||
type: 'date',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'accountOwnerId',
|
|
||||||
label: 'Account owner',
|
|
||||||
Icon: IconUser,
|
|
||||||
type: 'entity',
|
|
||||||
entitySelectComponent: <FilterDropdownUserSearchSelect />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
@ -20,7 +20,7 @@ import {
|
|||||||
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
|
||||||
import { User } from '~/generated/graphql';
|
import { User } from '~/generated/graphql';
|
||||||
|
|
||||||
export const companyShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
|
export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
|
||||||
{
|
{
|
||||||
fieldId: 'domainName',
|
fieldId: 'domainName',
|
||||||
label: 'Domain name',
|
label: 'Domain name',
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
import { FilterDefinitionByEntity } from '@/ui/data/filter/types/FilterDefinitionByEntity';
|
||||||
|
import {
|
||||||
|
IconBuildingSkyscraper,
|
||||||
|
IconCalendarEvent,
|
||||||
|
IconLink,
|
||||||
|
IconMap,
|
||||||
|
IconUser,
|
||||||
|
IconUsers,
|
||||||
|
} from '@/ui/display/icon/index';
|
||||||
|
import { FilterDropdownUserSearchSelect } from '@/users/components/FilterDropdownUserSearchSelect';
|
||||||
|
import { Company } from '~/generated/graphql';
|
||||||
|
|
||||||
|
export const companyTableFilterDefinitions: FilterDefinitionByEntity<Company>[] =
|
||||||
|
[
|
||||||
|
{
|
||||||
|
fieldId: 'name',
|
||||||
|
label: 'Name',
|
||||||
|
Icon: IconBuildingSkyscraper,
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldId: 'employees',
|
||||||
|
label: 'Employees',
|
||||||
|
Icon: IconUsers,
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldId: 'domainName',
|
||||||
|
label: 'URL',
|
||||||
|
Icon: IconLink,
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldId: 'address',
|
||||||
|
label: 'Address',
|
||||||
|
Icon: IconMap,
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldId: 'createdAt',
|
||||||
|
label: 'Created at',
|
||||||
|
Icon: IconCalendarEvent,
|
||||||
|
type: 'date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldId: 'accountOwnerId',
|
||||||
|
label: 'Account owner',
|
||||||
|
Icon: IconUser,
|
||||||
|
type: 'entity',
|
||||||
|
entitySelectComponent: <FilterDropdownUserSearchSelect />,
|
||||||
|
},
|
||||||
|
];
|
||||||
@ -7,29 +7,29 @@ import {
|
|||||||
IconUsers,
|
IconUsers,
|
||||||
} from '@/ui/display/icon/index';
|
} from '@/ui/display/icon/index';
|
||||||
|
|
||||||
export const companyAvailableSorts: SortDefinition[] = [
|
export const companyTableSortDefinitions: SortDefinition[] = [
|
||||||
{
|
{
|
||||||
key: 'name',
|
fieldId: 'name',
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
Icon: IconBuildingSkyscraper,
|
Icon: IconBuildingSkyscraper,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'employees',
|
fieldId: 'employees',
|
||||||
label: 'Employees',
|
label: 'Employees',
|
||||||
Icon: IconUsers,
|
Icon: IconUsers,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'domainName',
|
fieldId: 'domainName',
|
||||||
label: 'Url',
|
label: 'Url',
|
||||||
Icon: IconLink,
|
Icon: IconLink,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'address',
|
fieldId: 'address',
|
||||||
label: 'Address',
|
label: 'Address',
|
||||||
Icon: IconMap,
|
Icon: IconMap,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'createdAt',
|
fieldId: 'createdAt',
|
||||||
label: 'Creation',
|
label: 'Creation',
|
||||||
Icon: IconCalendarEvent,
|
Icon: IconCalendarEvent,
|
||||||
},
|
},
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { CompanyBoard } from '@/companies/board/components/CompanyBoard';
|
import { CompanyBoard } from '@/companies/board/components/CompanyBoard';
|
||||||
import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
|
import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
|
||||||
import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton';
|
import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton';
|
||||||
@ -11,6 +13,11 @@ import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'
|
|||||||
import { useUpdatePipelineStageMutation } from '~/generated/graphql';
|
import { useUpdatePipelineStageMutation } from '~/generated/graphql';
|
||||||
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
|
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
|
||||||
|
|
||||||
|
const StyledBoardContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
export const Opportunities = () => {
|
export const Opportunities = () => {
|
||||||
const { handlePipelineStageAdd, handlePipelineStageDelete } =
|
const { handlePipelineStageAdd, handlePipelineStageDelete } =
|
||||||
usePipelineStages();
|
usePipelineStages();
|
||||||
@ -51,11 +58,13 @@ export const Opportunities = () => {
|
|||||||
scopeId="opportunities"
|
scopeId="opportunities"
|
||||||
CustomRecoilScopeContext={CompanyBoardRecoilScopeContext}
|
CustomRecoilScopeContext={CompanyBoardRecoilScopeContext}
|
||||||
>
|
>
|
||||||
<CompanyBoard
|
<StyledBoardContainer>
|
||||||
onColumnAdd={handlePipelineStageAdd}
|
<CompanyBoard
|
||||||
onColumnDelete={handlePipelineStageDelete}
|
onColumnAdd={handlePipelineStageAdd}
|
||||||
onEditColumnTitle={handleEditColumnTitle}
|
onColumnDelete={handlePipelineStageDelete}
|
||||||
/>
|
onEditColumnTitle={handleEditColumnTitle}
|
||||||
|
/>
|
||||||
|
</StyledBoardContainer>
|
||||||
</RecoilScope>
|
</RecoilScope>
|
||||||
</BoardOptionsContext.Provider>
|
</BoardOptionsContext.Provider>
|
||||||
</PageBody>
|
</PageBody>
|
||||||
|
|||||||
@ -8,31 +8,31 @@ import {
|
|||||||
} from '@/ui/display/icon/index';
|
} from '@/ui/display/icon/index';
|
||||||
import { PipelineProgress } from '~/generated/graphql';
|
import { PipelineProgress } from '~/generated/graphql';
|
||||||
|
|
||||||
import { FilterDropdownPeopleSearchSelect } from '../../modules/people/components/FilterDropdownPeopleSearchSelect';
|
import { FilterDropdownPeopleSearchSelect } from '../../../modules/people/components/FilterDropdownPeopleSearchSelect';
|
||||||
|
|
||||||
export const opportunitiesFilters: FilterDefinitionByEntity<PipelineProgress>[] =
|
export const opportunityBoardFilterDefinitions: FilterDefinitionByEntity<PipelineProgress>[] =
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
key: 'amount',
|
fieldId: 'amount',
|
||||||
label: 'Amount',
|
label: 'Amount',
|
||||||
Icon: IconCurrencyDollar,
|
Icon: IconCurrencyDollar,
|
||||||
type: 'number',
|
type: 'number',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'closeDate',
|
fieldId: 'closeDate',
|
||||||
label: 'Close date',
|
label: 'Close date',
|
||||||
Icon: IconCalendarEvent,
|
Icon: IconCalendarEvent,
|
||||||
type: 'date',
|
type: 'date',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'companyId',
|
fieldId: 'companyId',
|
||||||
label: 'Company',
|
label: 'Company',
|
||||||
Icon: IconBuildingSkyscraper,
|
Icon: IconBuildingSkyscraper,
|
||||||
type: 'entity',
|
type: 'entity',
|
||||||
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
|
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'pointOfContactId',
|
fieldId: 'pointOfContactId',
|
||||||
label: 'Point of contact',
|
label: 'Point of contact',
|
||||||
Icon: IconUser,
|
Icon: IconUser,
|
||||||
type: 'entity',
|
type: 'entity',
|
||||||
@ -1,19 +1,19 @@
|
|||||||
import { SortDefinition } from '@/ui/data/sort/types/SortDefinition';
|
import { SortDefinition } from '@/ui/data/sort/types/SortDefinition';
|
||||||
import { IconCalendarEvent, IconCurrencyDollar } from '@/ui/display/icon/index';
|
import { IconCalendarEvent, IconCurrencyDollar } from '@/ui/display/icon/index';
|
||||||
|
|
||||||
export const opportunitiesSorts: SortDefinition[] = [
|
export const opportunityBoardSortDefinitions: SortDefinition[] = [
|
||||||
{
|
{
|
||||||
key: 'createdAt',
|
fieldId: 'createdAt',
|
||||||
label: 'Creation',
|
label: 'Creation',
|
||||||
Icon: IconCalendarEvent,
|
Icon: IconCalendarEvent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'amount',
|
fieldId: 'amount',
|
||||||
label: 'Amount',
|
label: 'Amount',
|
||||||
Icon: IconCurrencyDollar,
|
Icon: IconCurrencyDollar,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'closeDate',
|
fieldId: 'closeDate',
|
||||||
label: 'Expected close date',
|
label: 'Expected close date',
|
||||||
Icon: IconCalendarEvent,
|
Icon: IconCalendarEvent,
|
||||||
},
|
},
|
||||||
@ -2,12 +2,12 @@ import { CompanyBoardCard } from '@/companies/components/CompanyBoardCard';
|
|||||||
import { NewCompanyProgressButton } from '@/companies/components/NewCompanyProgressButton';
|
import { NewCompanyProgressButton } from '@/companies/components/NewCompanyProgressButton';
|
||||||
import { BoardOptions } from '@/ui/layout/board/types/BoardOptions';
|
import { BoardOptions } from '@/ui/layout/board/types/BoardOptions';
|
||||||
|
|
||||||
import { opportunitiesFilters } from './opportunities-filters';
|
import { opportunityBoardFilterDefinitions } from './constants/opportunityBoardFilterDefinitions';
|
||||||
import { opportunitiesSorts } from './opportunities-sorts';
|
import { opportunityBoardSortDefinitions } from './constants/opportunityBoardSortDefinitions';
|
||||||
|
|
||||||
export const opportunitiesBoardOptions: BoardOptions = {
|
export const opportunitiesBoardOptions: BoardOptions = {
|
||||||
newCardComponent: <NewCompanyProgressButton />,
|
newCardComponent: <NewCompanyProgressButton />,
|
||||||
CardComponent: CompanyBoardCard,
|
CardComponent: CompanyBoardCard,
|
||||||
filters: opportunitiesFilters,
|
filterDefinitions: opportunityBoardFilterDefinitions,
|
||||||
sorts: opportunitiesSorts,
|
sortDefinitions: opportunityBoardSortDefinitions,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import styled from '@emotion/styled';
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
||||||
import { PeopleTable } from '@/people/table/components/PeopleTable';
|
import { PersonTable } from '@/people/table/components/PersonTable';
|
||||||
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
||||||
import { DataTableActionBar } from '@/ui/data/data-table/action-bar/components/DataTableActionBar';
|
import { DataTableActionBar } from '@/ui/data/data-table/action-bar/components/DataTableActionBar';
|
||||||
import { DataTableContextMenu } from '@/ui/data/data-table/context-menu/components/DataTableContextMenu';
|
import { DataTableContextMenu } from '@/ui/data/data-table/context-menu/components/DataTableContextMenu';
|
||||||
@ -62,7 +62,7 @@ export const People = () => {
|
|||||||
CustomRecoilScopeContext={TableRecoilScopeContext}
|
CustomRecoilScopeContext={TableRecoilScopeContext}
|
||||||
>
|
>
|
||||||
<StyledTableContainer>
|
<StyledTableContainer>
|
||||||
<PeopleTable />
|
<PersonTable />
|
||||||
</StyledTableContainer>
|
</StyledTableContainer>
|
||||||
<DataTableActionBar />
|
<DataTableActionBar />
|
||||||
<DataTableContextMenu />
|
<DataTableContextMenu />
|
||||||
|
|||||||
@ -31,7 +31,7 @@ import {
|
|||||||
import { PeopleFullNameEditableField } from '../../modules/people/editable-field/components/PeopleFullNameEditableField';
|
import { PeopleFullNameEditableField } from '../../modules/people/editable-field/components/PeopleFullNameEditableField';
|
||||||
import { ShowPageContainer } from '../../modules/ui/layout/page/ShowPageContainer';
|
import { ShowPageContainer } from '../../modules/ui/layout/page/ShowPageContainer';
|
||||||
|
|
||||||
import { personShowFieldDefinition } from './constants/personShowFieldDefinition';
|
import { personShowFieldDefinition } from './constants/personShowFieldDefinitions';
|
||||||
|
|
||||||
export const PersonShow = () => {
|
export const PersonShow = () => {
|
||||||
const personId = useParams().personId ?? '';
|
const personId = useParams().personId ?? '';
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user