feat: delete views from views dropdown (#1234)
Closes #1129 Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
This commit is contained in:
@ -43,7 +43,8 @@ export function CompanyTable() {
|
||||
objectName: objectId,
|
||||
viewFieldDefinitions: companyViewFields,
|
||||
});
|
||||
const { updateSorts } = useViewSorts({ availableSorts });
|
||||
|
||||
const { handleSortsChange } = useViewSorts({ availableSorts });
|
||||
const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport();
|
||||
|
||||
const filters = useRecoilScopedValue(
|
||||
@ -85,7 +86,7 @@ export function CompanyTable() {
|
||||
viewName="All Companies"
|
||||
availableSorts={availableSorts}
|
||||
onColumnsChange={handleColumnsChange}
|
||||
onSortsUpdate={currentViewId ? updateSorts : undefined}
|
||||
onSortsUpdate={currentViewId ? handleSortsChange : undefined}
|
||||
onViewsChange={handleViewsChange}
|
||||
onImport={handleImport}
|
||||
updateEntityMutation={({
|
||||
|
||||
@ -44,7 +44,7 @@ export function PeopleTable() {
|
||||
objectName: objectId,
|
||||
viewFieldDefinitions: peopleViewFields,
|
||||
});
|
||||
const { updateSorts } = useViewSorts({ availableSorts });
|
||||
const { handleSortsChange } = useViewSorts({ availableSorts });
|
||||
|
||||
const filters = useRecoilScopedValue(
|
||||
filtersScopedState,
|
||||
@ -85,7 +85,7 @@ export function PeopleTable() {
|
||||
viewName="All People"
|
||||
availableSorts={availableSorts}
|
||||
onColumnsChange={handleColumnsChange}
|
||||
onSortsUpdate={currentViewId ? updateSorts : undefined}
|
||||
onSortsUpdate={currentViewId ? handleSortsChange : undefined}
|
||||
onViewsChange={handleViewsChange}
|
||||
onImport={handleImport}
|
||||
updateEntityMutation={({
|
||||
|
||||
@ -129,8 +129,7 @@ export function EntityTableHeader({ onColumnsChange }: EntityTableHeaderProps) {
|
||||
: column,
|
||||
);
|
||||
|
||||
setColumns(nextColumns);
|
||||
onColumnsChange?.(nextColumns);
|
||||
(onColumnsChange ?? setColumns)(nextColumns);
|
||||
}
|
||||
|
||||
set(resizeFieldOffsetState, 0);
|
||||
@ -159,8 +158,7 @@ export function EntityTableHeader({ onColumnsChange }: EntityTableHeaderProps) {
|
||||
column.id === columnId ? { ...column, isVisible: true } : column,
|
||||
);
|
||||
|
||||
setColumns(nextColumns);
|
||||
onColumnsChange?.(nextColumns);
|
||||
(onColumnsChange ?? setColumns)(nextColumns);
|
||||
},
|
||||
[columns, onColumnsChange, setColumns],
|
||||
);
|
||||
|
||||
@ -101,8 +101,7 @@ export const TableOptionsDropdownButton = ({
|
||||
: column,
|
||||
);
|
||||
|
||||
setColumns(nextColumns);
|
||||
onColumnsChange?.(nextColumns);
|
||||
(onColumnsChange ?? setColumns)(nextColumns);
|
||||
},
|
||||
[columns, onColumnsChange, setColumns],
|
||||
);
|
||||
|
||||
@ -8,10 +8,17 @@ import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
||||
import DropdownButton from '@/ui/filter-n-sort/components/DropdownButton';
|
||||
import { IconChevronDown, IconList, IconPencil, IconPlus } from '@/ui/icon';
|
||||
import {
|
||||
IconChevronDown,
|
||||
IconList,
|
||||
IconPencil,
|
||||
IconPlus,
|
||||
IconTrash,
|
||||
} from '@/ui/icon';
|
||||
import {
|
||||
currentTableViewIdState,
|
||||
currentTableViewState,
|
||||
type TableView,
|
||||
tableViewEditModeState,
|
||||
tableViewsState,
|
||||
} from '@/ui/table/states/tableViewsState';
|
||||
@ -41,11 +48,13 @@ const StyledViewIcon = styled(IconList)`
|
||||
type TableViewsDropdownButtonProps = {
|
||||
defaultViewName: string;
|
||||
HotkeyScope: TableViewsHotkeyScope;
|
||||
onViewsChange?: (views: TableView[]) => void;
|
||||
};
|
||||
|
||||
export const TableViewsDropdownButton = ({
|
||||
defaultViewName,
|
||||
HotkeyScope,
|
||||
onViewsChange,
|
||||
}: TableViewsDropdownButtonProps) => {
|
||||
const theme = useTheme();
|
||||
const [isUnfolded, setIsUnfolded] = useState(false);
|
||||
@ -54,7 +63,10 @@ export const TableViewsDropdownButton = ({
|
||||
currentTableViewState,
|
||||
TableRecoilScopeContext,
|
||||
);
|
||||
const views = useRecoilScopedValue(tableViewsState, TableRecoilScopeContext);
|
||||
const [views, setViews] = useRecoilScopedState(
|
||||
tableViewsState,
|
||||
TableRecoilScopeContext,
|
||||
);
|
||||
const [, setCurrentViewId] = useRecoilScopedState(
|
||||
currentTableViewIdState,
|
||||
TableRecoilScopeContext,
|
||||
@ -88,6 +100,18 @@ export const TableViewsDropdownButton = ({
|
||||
[setViewEditMode],
|
||||
);
|
||||
|
||||
const handleDeleteViewButtonClick = useCallback(
|
||||
(event: MouseEvent<HTMLButtonElement>, viewId: string) => {
|
||||
event.stopPropagation();
|
||||
|
||||
if (currentView?.id === viewId) setCurrentViewId(undefined);
|
||||
|
||||
(onViewsChange ?? setViews)(views.filter((view) => view.id !== viewId));
|
||||
setIsUnfolded(false);
|
||||
},
|
||||
[currentView?.id, onViewsChange, setCurrentViewId, setViews, views],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
isUnfolded
|
||||
? setHotkeyScopeAndMemorizePreviousScope(HotkeyScope)
|
||||
@ -124,12 +148,18 @@ export const TableViewsDropdownButton = ({
|
||||
{views.map((view) => (
|
||||
<DropdownMenuItem
|
||||
key={view.id}
|
||||
actions={
|
||||
actions={[
|
||||
<IconButton
|
||||
key="edit"
|
||||
onClick={(event) => handleEditViewButtonClick(event, view.id)}
|
||||
icon={<IconPencil size={theme.icon.size.sm} />}
|
||||
/>
|
||||
}
|
||||
/>,
|
||||
<IconButton
|
||||
key="delete"
|
||||
onClick={(event) => handleDeleteViewButtonClick(event, view.id)}
|
||||
icon={<IconTrash size={theme.icon.size.sm} />}
|
||||
/>,
|
||||
]}
|
||||
onClick={() => handleViewSelect(view.id)}
|
||||
>
|
||||
<IconList size={theme.icon.size.md} />
|
||||
|
||||
@ -64,6 +64,7 @@ export function TableHeader<SortField>({
|
||||
leftComponent={
|
||||
<TableViewsDropdownButton
|
||||
defaultViewName={viewName}
|
||||
onViewsChange={onViewsChange}
|
||||
HotkeyScope={TableViewsHotkeyScope.Dropdown}
|
||||
/>
|
||||
}
|
||||
|
||||
9
front/src/modules/views/graphql/mutations/deleteView.ts
Normal file
9
front/src/modules/views/graphql/mutations/deleteView.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const DELETE_VIEWS = gql`
|
||||
mutation DeleteViews($where: ViewWhereInput!) {
|
||||
deleteManyView(where: $where) {
|
||||
count
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -131,6 +131,8 @@ export const useTableViewFields = ({
|
||||
|
||||
const handleColumnsChange = useCallback(
|
||||
async (nextColumns: ViewFieldDefinition<ViewFieldMetadata>[]) => {
|
||||
setColumns(nextColumns);
|
||||
|
||||
const viewFieldsToCreate = nextColumns.filter(
|
||||
(nextColumn) => !columnsById[nextColumn.id],
|
||||
);
|
||||
@ -144,7 +146,7 @@ export const useTableViewFields = ({
|
||||
);
|
||||
await updateViewFields(viewFieldsToUpdate);
|
||||
},
|
||||
[columnsById, createViewFields, updateViewFields],
|
||||
[columnsById, createViewFields, setColumns, updateViewFields],
|
||||
);
|
||||
|
||||
return { handleColumnsChange };
|
||||
|
||||
@ -11,6 +11,7 @@ import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoi
|
||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||
import {
|
||||
useCreateViewsMutation,
|
||||
useDeleteViewsMutation,
|
||||
useGetViewsQuery,
|
||||
useUpdateViewMutation,
|
||||
ViewType,
|
||||
@ -34,6 +35,7 @@ export const useTableViews = ({
|
||||
|
||||
const [createViewsMutation] = useCreateViewsMutation();
|
||||
const [updateViewMutation] = useUpdateViewMutation();
|
||||
const [deleteViewsMutation] = useDeleteViewsMutation();
|
||||
|
||||
const createViews = useCallback(
|
||||
(views: TableView[]) => {
|
||||
@ -72,6 +74,22 @@ export const useTableViews = ({
|
||||
[updateViewMutation],
|
||||
);
|
||||
|
||||
const deleteViews = useCallback(
|
||||
(viewIds: string[]) => {
|
||||
if (!viewIds.length) return;
|
||||
|
||||
return deleteViewsMutation({
|
||||
variables: {
|
||||
where: {
|
||||
id: { in: viewIds },
|
||||
},
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
|
||||
});
|
||||
},
|
||||
[deleteViewsMutation],
|
||||
);
|
||||
|
||||
useGetViewsQuery({
|
||||
variables: {
|
||||
where: {
|
||||
@ -90,6 +108,8 @@ export const useTableViews = ({
|
||||
|
||||
const handleViewsChange = useCallback(
|
||||
async (nextViews: TableView[]) => {
|
||||
setViews(nextViews);
|
||||
|
||||
const viewsToCreate = nextViews.filter(
|
||||
(nextView) => !viewsById[nextView.id],
|
||||
);
|
||||
@ -101,8 +121,14 @@ export const useTableViews = ({
|
||||
viewsById[nextView.id].name !== nextView.name,
|
||||
);
|
||||
await updateViewFields(viewsToUpdate);
|
||||
|
||||
const nextViewIds = nextViews.map((nextView) => nextView.id);
|
||||
const viewIdsToDelete = Object.keys(viewsById).filter(
|
||||
(previousViewId) => !nextViewIds.includes(previousViewId),
|
||||
);
|
||||
return deleteViews(viewIdsToDelete);
|
||||
},
|
||||
[createViews, updateViewFields, viewsById],
|
||||
[createViews, deleteViews, setViews, updateViewFields, viewsById],
|
||||
);
|
||||
|
||||
return { handleViewsChange };
|
||||
|
||||
@ -136,10 +136,12 @@ export const useViewSorts = <SortField>({
|
||||
[currentViewId, deleteViewSortsMutation],
|
||||
);
|
||||
|
||||
const updateSorts = useCallback(
|
||||
const handleSortsChange = useCallback(
|
||||
async (nextSorts: SelectedSortType<SortField>[]) => {
|
||||
if (!currentViewId) return;
|
||||
|
||||
setSorts(nextSorts);
|
||||
|
||||
const sortsToCreate = nextSorts.filter(
|
||||
(nextSort) => !sortsByKey[nextSort.key],
|
||||
);
|
||||
@ -162,10 +164,11 @@ export const useViewSorts = <SortField>({
|
||||
createViewSorts,
|
||||
currentViewId,
|
||||
deleteViewSorts,
|
||||
setSorts,
|
||||
sortsByKey,
|
||||
updateViewSorts,
|
||||
],
|
||||
);
|
||||
|
||||
return { updateSorts };
|
||||
return { handleSortsChange };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user