feat: delete views from views dropdown (#1234)
Closes #1129 Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
This commit is contained in:
@ -982,6 +982,7 @@ export type Mutation = {
|
|||||||
deleteManyCompany: AffectedRows;
|
deleteManyCompany: AffectedRows;
|
||||||
deleteManyPerson: AffectedRows;
|
deleteManyPerson: AffectedRows;
|
||||||
deleteManyPipelineProgress: AffectedRows;
|
deleteManyPipelineProgress: AffectedRows;
|
||||||
|
deleteManyView: AffectedRows;
|
||||||
deleteManyViewSort: AffectedRows;
|
deleteManyViewSort: AffectedRows;
|
||||||
deleteUserAccount: User;
|
deleteUserAccount: User;
|
||||||
deleteWorkspaceMember: WorkspaceMember;
|
deleteWorkspaceMember: WorkspaceMember;
|
||||||
@ -1120,6 +1121,11 @@ export type MutationDeleteManyPipelineProgressArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationDeleteManyViewArgs = {
|
||||||
|
where?: InputMaybe<ViewWhereInput>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationDeleteManyViewSortArgs = {
|
export type MutationDeleteManyViewSortArgs = {
|
||||||
where?: InputMaybe<ViewSortWhereInput>;
|
where?: InputMaybe<ViewSortWhereInput>;
|
||||||
};
|
};
|
||||||
@ -3224,6 +3230,15 @@ export type CreateViewsMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type CreateViewsMutation = { __typename?: 'Mutation', createManyView: { __typename?: 'AffectedRows', count: number } };
|
export type CreateViewsMutation = { __typename?: 'Mutation', createManyView: { __typename?: 'AffectedRows', count: number } };
|
||||||
|
|
||||||
|
|
||||||
|
export type DeleteViewsMutationVariables = Exact<{
|
||||||
|
where: ViewWhereInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type DeleteViewsMutation = { __typename?: 'Mutation', deleteManyView: { __typename?: 'AffectedRows', count: number } };
|
||||||
|
|
||||||
|
|
||||||
export type DeleteViewSortsMutationVariables = Exact<{
|
export type DeleteViewSortsMutationVariables = Exact<{
|
||||||
where: ViewSortWhereInput;
|
where: ViewSortWhereInput;
|
||||||
}>;
|
}>;
|
||||||
@ -5984,6 +5999,41 @@ export function useCreateViewsMutation(baseOptions?: Apollo.MutationHookOptions<
|
|||||||
export type CreateViewsMutationHookResult = ReturnType<typeof useCreateViewsMutation>;
|
export type CreateViewsMutationHookResult = ReturnType<typeof useCreateViewsMutation>;
|
||||||
export type CreateViewsMutationResult = Apollo.MutationResult<CreateViewsMutation>;
|
export type CreateViewsMutationResult = Apollo.MutationResult<CreateViewsMutation>;
|
||||||
export type CreateViewsMutationOptions = Apollo.BaseMutationOptions<CreateViewsMutation, CreateViewsMutationVariables>;
|
export type CreateViewsMutationOptions = Apollo.BaseMutationOptions<CreateViewsMutation, CreateViewsMutationVariables>;
|
||||||
|
|
||||||
|
export const DeleteViewsDocument = gql`
|
||||||
|
mutation DeleteViews($where: ViewWhereInput!) {
|
||||||
|
deleteManyView(where: $where) {
|
||||||
|
count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type DeleteViewsMutationFn = Apollo.MutationFunction<DeleteViewsMutation, DeleteViewsMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useDeleteViewsMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useDeleteViewsMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useDeleteViewsMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [deleteViewsMutation, { data, loading, error }] = useDeleteViewsMutation({
|
||||||
|
* variables: {
|
||||||
|
* where: // value for 'where'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useDeleteViewsMutation(baseOptions?: Apollo.MutationHookOptions<DeleteViewsMutation, DeleteViewsMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<DeleteViewsMutation, DeleteViewsMutationVariables>(DeleteViewsDocument, options);
|
||||||
|
}
|
||||||
|
export type DeleteViewsMutationHookResult = ReturnType<typeof useDeleteViewsMutation>;
|
||||||
|
export type DeleteViewsMutationResult = Apollo.MutationResult<DeleteViewsMutation>;
|
||||||
|
export type DeleteViewsMutationOptions = Apollo.BaseMutationOptions<DeleteViewsMutation, DeleteViewsMutationVariables>;
|
||||||
|
|
||||||
export const DeleteViewSortsDocument = gql`
|
export const DeleteViewSortsDocument = gql`
|
||||||
mutation DeleteViewSorts($where: ViewSortWhereInput!) {
|
mutation DeleteViewSorts($where: ViewSortWhereInput!) {
|
||||||
deleteManyViewSort(where: $where) {
|
deleteManyViewSort(where: $where) {
|
||||||
|
|||||||
@ -43,7 +43,8 @@ export function CompanyTable() {
|
|||||||
objectName: objectId,
|
objectName: objectId,
|
||||||
viewFieldDefinitions: companyViewFields,
|
viewFieldDefinitions: companyViewFields,
|
||||||
});
|
});
|
||||||
const { updateSorts } = useViewSorts({ availableSorts });
|
|
||||||
|
const { handleSortsChange } = useViewSorts({ availableSorts });
|
||||||
const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport();
|
const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport();
|
||||||
|
|
||||||
const filters = useRecoilScopedValue(
|
const filters = useRecoilScopedValue(
|
||||||
@ -85,7 +86,7 @@ export function CompanyTable() {
|
|||||||
viewName="All Companies"
|
viewName="All Companies"
|
||||||
availableSorts={availableSorts}
|
availableSorts={availableSorts}
|
||||||
onColumnsChange={handleColumnsChange}
|
onColumnsChange={handleColumnsChange}
|
||||||
onSortsUpdate={currentViewId ? updateSorts : undefined}
|
onSortsUpdate={currentViewId ? handleSortsChange : undefined}
|
||||||
onViewsChange={handleViewsChange}
|
onViewsChange={handleViewsChange}
|
||||||
onImport={handleImport}
|
onImport={handleImport}
|
||||||
updateEntityMutation={({
|
updateEntityMutation={({
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export function PeopleTable() {
|
|||||||
objectName: objectId,
|
objectName: objectId,
|
||||||
viewFieldDefinitions: peopleViewFields,
|
viewFieldDefinitions: peopleViewFields,
|
||||||
});
|
});
|
||||||
const { updateSorts } = useViewSorts({ availableSorts });
|
const { handleSortsChange } = useViewSorts({ availableSorts });
|
||||||
|
|
||||||
const filters = useRecoilScopedValue(
|
const filters = useRecoilScopedValue(
|
||||||
filtersScopedState,
|
filtersScopedState,
|
||||||
@ -85,7 +85,7 @@ export function PeopleTable() {
|
|||||||
viewName="All People"
|
viewName="All People"
|
||||||
availableSorts={availableSorts}
|
availableSorts={availableSorts}
|
||||||
onColumnsChange={handleColumnsChange}
|
onColumnsChange={handleColumnsChange}
|
||||||
onSortsUpdate={currentViewId ? updateSorts : undefined}
|
onSortsUpdate={currentViewId ? handleSortsChange : undefined}
|
||||||
onViewsChange={handleViewsChange}
|
onViewsChange={handleViewsChange}
|
||||||
onImport={handleImport}
|
onImport={handleImport}
|
||||||
updateEntityMutation={({
|
updateEntityMutation={({
|
||||||
|
|||||||
@ -129,8 +129,7 @@ export function EntityTableHeader({ onColumnsChange }: EntityTableHeaderProps) {
|
|||||||
: column,
|
: column,
|
||||||
);
|
);
|
||||||
|
|
||||||
setColumns(nextColumns);
|
(onColumnsChange ?? setColumns)(nextColumns);
|
||||||
onColumnsChange?.(nextColumns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set(resizeFieldOffsetState, 0);
|
set(resizeFieldOffsetState, 0);
|
||||||
@ -159,8 +158,7 @@ export function EntityTableHeader({ onColumnsChange }: EntityTableHeaderProps) {
|
|||||||
column.id === columnId ? { ...column, isVisible: true } : column,
|
column.id === columnId ? { ...column, isVisible: true } : column,
|
||||||
);
|
);
|
||||||
|
|
||||||
setColumns(nextColumns);
|
(onColumnsChange ?? setColumns)(nextColumns);
|
||||||
onColumnsChange?.(nextColumns);
|
|
||||||
},
|
},
|
||||||
[columns, onColumnsChange, setColumns],
|
[columns, onColumnsChange, setColumns],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -101,8 +101,7 @@ export const TableOptionsDropdownButton = ({
|
|||||||
: column,
|
: column,
|
||||||
);
|
);
|
||||||
|
|
||||||
setColumns(nextColumns);
|
(onColumnsChange ?? setColumns)(nextColumns);
|
||||||
onColumnsChange?.(nextColumns);
|
|
||||||
},
|
},
|
||||||
[columns, onColumnsChange, setColumns],
|
[columns, onColumnsChange, setColumns],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -8,10 +8,17 @@ import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
|||||||
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
||||||
import DropdownButton from '@/ui/filter-n-sort/components/DropdownButton';
|
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 {
|
import {
|
||||||
currentTableViewIdState,
|
currentTableViewIdState,
|
||||||
currentTableViewState,
|
currentTableViewState,
|
||||||
|
type TableView,
|
||||||
tableViewEditModeState,
|
tableViewEditModeState,
|
||||||
tableViewsState,
|
tableViewsState,
|
||||||
} from '@/ui/table/states/tableViewsState';
|
} from '@/ui/table/states/tableViewsState';
|
||||||
@ -41,11 +48,13 @@ const StyledViewIcon = styled(IconList)`
|
|||||||
type TableViewsDropdownButtonProps = {
|
type TableViewsDropdownButtonProps = {
|
||||||
defaultViewName: string;
|
defaultViewName: string;
|
||||||
HotkeyScope: TableViewsHotkeyScope;
|
HotkeyScope: TableViewsHotkeyScope;
|
||||||
|
onViewsChange?: (views: TableView[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TableViewsDropdownButton = ({
|
export const TableViewsDropdownButton = ({
|
||||||
defaultViewName,
|
defaultViewName,
|
||||||
HotkeyScope,
|
HotkeyScope,
|
||||||
|
onViewsChange,
|
||||||
}: TableViewsDropdownButtonProps) => {
|
}: TableViewsDropdownButtonProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [isUnfolded, setIsUnfolded] = useState(false);
|
const [isUnfolded, setIsUnfolded] = useState(false);
|
||||||
@ -54,7 +63,10 @@ export const TableViewsDropdownButton = ({
|
|||||||
currentTableViewState,
|
currentTableViewState,
|
||||||
TableRecoilScopeContext,
|
TableRecoilScopeContext,
|
||||||
);
|
);
|
||||||
const views = useRecoilScopedValue(tableViewsState, TableRecoilScopeContext);
|
const [views, setViews] = useRecoilScopedState(
|
||||||
|
tableViewsState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
const [, setCurrentViewId] = useRecoilScopedState(
|
const [, setCurrentViewId] = useRecoilScopedState(
|
||||||
currentTableViewIdState,
|
currentTableViewIdState,
|
||||||
TableRecoilScopeContext,
|
TableRecoilScopeContext,
|
||||||
@ -88,6 +100,18 @@ export const TableViewsDropdownButton = ({
|
|||||||
[setViewEditMode],
|
[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(() => {
|
useEffect(() => {
|
||||||
isUnfolded
|
isUnfolded
|
||||||
? setHotkeyScopeAndMemorizePreviousScope(HotkeyScope)
|
? setHotkeyScopeAndMemorizePreviousScope(HotkeyScope)
|
||||||
@ -124,12 +148,18 @@ export const TableViewsDropdownButton = ({
|
|||||||
{views.map((view) => (
|
{views.map((view) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
key={view.id}
|
key={view.id}
|
||||||
actions={
|
actions={[
|
||||||
<IconButton
|
<IconButton
|
||||||
|
key="edit"
|
||||||
onClick={(event) => handleEditViewButtonClick(event, view.id)}
|
onClick={(event) => handleEditViewButtonClick(event, view.id)}
|
||||||
icon={<IconPencil size={theme.icon.size.sm} />}
|
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)}
|
onClick={() => handleViewSelect(view.id)}
|
||||||
>
|
>
|
||||||
<IconList size={theme.icon.size.md} />
|
<IconList size={theme.icon.size.md} />
|
||||||
|
|||||||
@ -64,6 +64,7 @@ export function TableHeader<SortField>({
|
|||||||
leftComponent={
|
leftComponent={
|
||||||
<TableViewsDropdownButton
|
<TableViewsDropdownButton
|
||||||
defaultViewName={viewName}
|
defaultViewName={viewName}
|
||||||
|
onViewsChange={onViewsChange}
|
||||||
HotkeyScope={TableViewsHotkeyScope.Dropdown}
|
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(
|
const handleColumnsChange = useCallback(
|
||||||
async (nextColumns: ViewFieldDefinition<ViewFieldMetadata>[]) => {
|
async (nextColumns: ViewFieldDefinition<ViewFieldMetadata>[]) => {
|
||||||
|
setColumns(nextColumns);
|
||||||
|
|
||||||
const viewFieldsToCreate = nextColumns.filter(
|
const viewFieldsToCreate = nextColumns.filter(
|
||||||
(nextColumn) => !columnsById[nextColumn.id],
|
(nextColumn) => !columnsById[nextColumn.id],
|
||||||
);
|
);
|
||||||
@ -144,7 +146,7 @@ export const useTableViewFields = ({
|
|||||||
);
|
);
|
||||||
await updateViewFields(viewFieldsToUpdate);
|
await updateViewFields(viewFieldsToUpdate);
|
||||||
},
|
},
|
||||||
[columnsById, createViewFields, updateViewFields],
|
[columnsById, createViewFields, setColumns, updateViewFields],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { handleColumnsChange };
|
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 { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import {
|
import {
|
||||||
useCreateViewsMutation,
|
useCreateViewsMutation,
|
||||||
|
useDeleteViewsMutation,
|
||||||
useGetViewsQuery,
|
useGetViewsQuery,
|
||||||
useUpdateViewMutation,
|
useUpdateViewMutation,
|
||||||
ViewType,
|
ViewType,
|
||||||
@ -34,6 +35,7 @@ export const useTableViews = ({
|
|||||||
|
|
||||||
const [createViewsMutation] = useCreateViewsMutation();
|
const [createViewsMutation] = useCreateViewsMutation();
|
||||||
const [updateViewMutation] = useUpdateViewMutation();
|
const [updateViewMutation] = useUpdateViewMutation();
|
||||||
|
const [deleteViewsMutation] = useDeleteViewsMutation();
|
||||||
|
|
||||||
const createViews = useCallback(
|
const createViews = useCallback(
|
||||||
(views: TableView[]) => {
|
(views: TableView[]) => {
|
||||||
@ -72,6 +74,22 @@ export const useTableViews = ({
|
|||||||
[updateViewMutation],
|
[updateViewMutation],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const deleteViews = useCallback(
|
||||||
|
(viewIds: string[]) => {
|
||||||
|
if (!viewIds.length) return;
|
||||||
|
|
||||||
|
return deleteViewsMutation({
|
||||||
|
variables: {
|
||||||
|
where: {
|
||||||
|
id: { in: viewIds },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[deleteViewsMutation],
|
||||||
|
);
|
||||||
|
|
||||||
useGetViewsQuery({
|
useGetViewsQuery({
|
||||||
variables: {
|
variables: {
|
||||||
where: {
|
where: {
|
||||||
@ -90,6 +108,8 @@ export const useTableViews = ({
|
|||||||
|
|
||||||
const handleViewsChange = useCallback(
|
const handleViewsChange = useCallback(
|
||||||
async (nextViews: TableView[]) => {
|
async (nextViews: TableView[]) => {
|
||||||
|
setViews(nextViews);
|
||||||
|
|
||||||
const viewsToCreate = nextViews.filter(
|
const viewsToCreate = nextViews.filter(
|
||||||
(nextView) => !viewsById[nextView.id],
|
(nextView) => !viewsById[nextView.id],
|
||||||
);
|
);
|
||||||
@ -101,8 +121,14 @@ export const useTableViews = ({
|
|||||||
viewsById[nextView.id].name !== nextView.name,
|
viewsById[nextView.id].name !== nextView.name,
|
||||||
);
|
);
|
||||||
await updateViewFields(viewsToUpdate);
|
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 };
|
return { handleViewsChange };
|
||||||
|
|||||||
@ -136,10 +136,12 @@ export const useViewSorts = <SortField>({
|
|||||||
[currentViewId, deleteViewSortsMutation],
|
[currentViewId, deleteViewSortsMutation],
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateSorts = useCallback(
|
const handleSortsChange = useCallback(
|
||||||
async (nextSorts: SelectedSortType<SortField>[]) => {
|
async (nextSorts: SelectedSortType<SortField>[]) => {
|
||||||
if (!currentViewId) return;
|
if (!currentViewId) return;
|
||||||
|
|
||||||
|
setSorts(nextSorts);
|
||||||
|
|
||||||
const sortsToCreate = nextSorts.filter(
|
const sortsToCreate = nextSorts.filter(
|
||||||
(nextSort) => !sortsByKey[nextSort.key],
|
(nextSort) => !sortsByKey[nextSort.key],
|
||||||
);
|
);
|
||||||
@ -162,10 +164,11 @@ export const useViewSorts = <SortField>({
|
|||||||
createViewSorts,
|
createViewSorts,
|
||||||
currentViewId,
|
currentViewId,
|
||||||
deleteViewSorts,
|
deleteViewSorts,
|
||||||
|
setSorts,
|
||||||
sortsByKey,
|
sortsByKey,
|
||||||
updateViewSorts,
|
updateViewSorts,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { updateSorts };
|
return { handleSortsChange };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -140,17 +140,17 @@ export class AbilityFactory {
|
|||||||
can(AbilityAction.Read, 'View', { workspaceId: workspace.id });
|
can(AbilityAction.Read, 'View', { workspaceId: workspace.id });
|
||||||
can(AbilityAction.Create, 'View', { workspaceId: workspace.id });
|
can(AbilityAction.Create, 'View', { workspaceId: workspace.id });
|
||||||
can(AbilityAction.Update, 'View', { workspaceId: workspace.id });
|
can(AbilityAction.Update, 'View', { workspaceId: workspace.id });
|
||||||
|
can(AbilityAction.Delete, 'View', { workspaceId: workspace.id });
|
||||||
|
|
||||||
// ViewField
|
// ViewField
|
||||||
can(AbilityAction.Read, 'ViewField', { workspaceId: workspace.id });
|
can(AbilityAction.Read, 'ViewField', { workspaceId: workspace.id });
|
||||||
can(AbilityAction.Create, 'ViewField', { workspaceId: workspace.id });
|
can(AbilityAction.Create, 'ViewField', { workspaceId: workspace.id });
|
||||||
can(AbilityAction.Update, 'ViewField', { workspaceId: workspace.id });
|
can(AbilityAction.Update, 'ViewField', { workspaceId: workspace.id });
|
||||||
|
|
||||||
//Favorite
|
//Favorite
|
||||||
can(AbilityAction.Read, 'Favorite', { workspaceId: workspace.id });
|
can(AbilityAction.Read, 'Favorite', { workspaceId: workspace.id });
|
||||||
can(AbilityAction.Create, 'Favorite');
|
can(AbilityAction.Create, 'Favorite');
|
||||||
can(AbilityAction.Delete, 'Favorite', {
|
can(AbilityAction.Delete, 'Favorite', { workspaceId: workspace.id });
|
||||||
workspaceId: workspace.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
// ViewSort
|
// ViewSort
|
||||||
can(AbilityAction.Read, 'ViewSort', { workspaceId: workspace.id });
|
can(AbilityAction.Read, 'ViewSort', { workspaceId: workspace.id });
|
||||||
|
|||||||
@ -114,6 +114,7 @@ import {
|
|||||||
CreateViewAbilityHandler,
|
CreateViewAbilityHandler,
|
||||||
ReadViewAbilityHandler,
|
ReadViewAbilityHandler,
|
||||||
UpdateViewAbilityHandler,
|
UpdateViewAbilityHandler,
|
||||||
|
DeleteViewAbilityHandler,
|
||||||
} from './handlers/view.ability-handler';
|
} from './handlers/view.ability-handler';
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@ -207,6 +208,7 @@ import {
|
|||||||
ReadViewAbilityHandler,
|
ReadViewAbilityHandler,
|
||||||
CreateViewAbilityHandler,
|
CreateViewAbilityHandler,
|
||||||
UpdateViewAbilityHandler,
|
UpdateViewAbilityHandler,
|
||||||
|
DeleteViewAbilityHandler,
|
||||||
// ViewField
|
// ViewField
|
||||||
ReadViewFieldAbilityHandler,
|
ReadViewFieldAbilityHandler,
|
||||||
CreateViewFieldAbilityHandler,
|
CreateViewFieldAbilityHandler,
|
||||||
@ -305,6 +307,7 @@ import {
|
|||||||
ReadViewAbilityHandler,
|
ReadViewAbilityHandler,
|
||||||
CreateViewAbilityHandler,
|
CreateViewAbilityHandler,
|
||||||
UpdateViewAbilityHandler,
|
UpdateViewAbilityHandler,
|
||||||
|
DeleteViewAbilityHandler,
|
||||||
// ViewField
|
// ViewField
|
||||||
ReadViewFieldAbilityHandler,
|
ReadViewFieldAbilityHandler,
|
||||||
CreateViewFieldAbilityHandler,
|
CreateViewFieldAbilityHandler,
|
||||||
|
|||||||
@ -77,3 +77,19 @@ export class UpdateViewAbilityHandler implements IAbilityHandler {
|
|||||||
return ability.can(AbilityAction.Update, subject('View', view));
|
return ability.can(AbilityAction.Update, subject('View', view));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DeleteViewAbilityHandler implements IAbilityHandler {
|
||||||
|
constructor(private readonly prismaService: PrismaService) {}
|
||||||
|
|
||||||
|
async handle(ability: AppAbility, context: ExecutionContext) {
|
||||||
|
const gqlContext = GqlExecutionContext.create(context);
|
||||||
|
const args = gqlContext.getArgs<ViewArgs>();
|
||||||
|
const view = await this.prismaService.client.view.findFirst({
|
||||||
|
where: args.where,
|
||||||
|
});
|
||||||
|
assert(view, '', NotFoundException);
|
||||||
|
|
||||||
|
return ability.can(AbilityAction.Delete, subject('View', view));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { Prisma, Workspace } from '@prisma/client';
|
|||||||
import { AppAbility } from 'src/ability/ability.factory';
|
import { AppAbility } from 'src/ability/ability.factory';
|
||||||
import {
|
import {
|
||||||
CreateViewAbilityHandler,
|
CreateViewAbilityHandler,
|
||||||
|
DeleteViewAbilityHandler,
|
||||||
ReadViewAbilityHandler,
|
ReadViewAbilityHandler,
|
||||||
UpdateViewAbilityHandler,
|
UpdateViewAbilityHandler,
|
||||||
} from 'src/ability/handlers/view.ability-handler';
|
} from 'src/ability/handlers/view.ability-handler';
|
||||||
@ -25,6 +26,7 @@ import { UpdateOneViewArgs } from 'src/core/@generated/view/update-one-view.args
|
|||||||
import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator';
|
import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator';
|
||||||
import { AffectedRows } from 'src/core/@generated/prisma/affected-rows.output';
|
import { AffectedRows } from 'src/core/@generated/prisma/affected-rows.output';
|
||||||
import { CreateManyViewArgs } from 'src/core/@generated/view/create-many-view.args';
|
import { CreateManyViewArgs } from 'src/core/@generated/view/create-many-view.args';
|
||||||
|
import { DeleteManyViewArgs } from 'src/core/@generated/view/delete-many-view.args';
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Resolver(() => View)
|
@Resolver(() => View)
|
||||||
@ -84,4 +86,17 @@ export class ViewResolver {
|
|||||||
select: prismaSelect.value,
|
select: prismaSelect.value,
|
||||||
} as Prisma.ViewUpdateArgs);
|
} as Prisma.ViewUpdateArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mutation(() => AffectedRows, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
@UseGuards(AbilityGuard)
|
||||||
|
@CheckAbilities(DeleteViewAbilityHandler)
|
||||||
|
async deleteManyView(
|
||||||
|
@Args() args: DeleteManyViewArgs,
|
||||||
|
): Promise<AffectedRows> {
|
||||||
|
return this.viewService.deleteMany({
|
||||||
|
where: args.where,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "viewFields" DROP CONSTRAINT "viewFields_viewId_fkey";
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "viewSorts" DROP CONSTRAINT "viewSorts_viewId_fkey";
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "viewSorts" ADD CONSTRAINT "viewSorts_viewId_fkey" FOREIGN KEY ("viewId") REFERENCES "views"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "viewFields" ADD CONSTRAINT "viewFields_viewId_fkey" FOREIGN KEY ("viewId") REFERENCES "views"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
@ -606,7 +606,7 @@ model ViewSort {
|
|||||||
key String
|
key String
|
||||||
name String
|
name String
|
||||||
|
|
||||||
view View @relation(fields: [viewId], references: [id])
|
view View @relation(fields: [viewId], references: [id], onDelete: Cascade)
|
||||||
viewId String
|
viewId String
|
||||||
|
|
||||||
/// @TypeGraphQL.omit(input: true, output: true)
|
/// @TypeGraphQL.omit(input: true, output: true)
|
||||||
@ -629,7 +629,7 @@ model ViewField {
|
|||||||
objectName String
|
objectName String
|
||||||
sizeInPx Int
|
sizeInPx Int
|
||||||
|
|
||||||
view View? @relation(fields: [viewId], references: [id])
|
view View? @relation(fields: [viewId], references: [id], onDelete: Cascade)
|
||||||
viewId String?
|
viewId String?
|
||||||
|
|
||||||
/// @TypeGraphQL.omit(input: true, output: true)
|
/// @TypeGraphQL.omit(input: true, output: true)
|
||||||
|
|||||||
Reference in New Issue
Block a user