diff --git a/front/src/modules/ui/table/options/components/TableViewsDropdownButton.tsx b/front/src/modules/ui/table/options/components/TableViewsDropdownButton.tsx
index 20ec286b76..beed828e08 100644
--- a/front/src/modules/ui/table/options/components/TableViewsDropdownButton.tsx
+++ b/front/src/modules/ui/table/options/components/TableViewsDropdownButton.tsx
@@ -31,6 +31,7 @@ import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousH
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
+import { assertNotNull } from '~/utils/assert';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsScopedState } from '../../states/savedTableColumnsScopedState';
@@ -184,12 +185,16 @@ export const TableViewsDropdownButton = ({
onClick={(event) => handleEditViewButtonClick(event, view.id)}
icon={}
/>,
- handleDeleteViewButtonClick(event, view.id)}
- icon={}
- />,
- ]}
+ views.length > 1 ? (
+
+ handleDeleteViewButtonClick(event, view.id)
+ }
+ icon={}
+ />
+ ) : null,
+ ].filter(assertNotNull)}
onClick={() => handleViewSelect(view.id)}
>
diff --git a/server/src/core/view/resolvers/view.resolver.ts b/server/src/core/view/resolvers/view.resolver.ts
index fd96564fff..ab439ad71e 100644
--- a/server/src/core/view/resolvers/view.resolver.ts
+++ b/server/src/core/view/resolvers/view.resolver.ts
@@ -1,4 +1,8 @@
-import { UseGuards } from '@nestjs/common';
+import {
+ BadRequestException,
+ ForbiddenException,
+ UseGuards,
+} from '@nestjs/common';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { accessibleBy } from '@casl/prisma';
@@ -94,7 +98,35 @@ export class ViewResolver {
@CheckAbilities(DeleteViewAbilityHandler)
async deleteManyView(
@Args() args: DeleteManyViewArgs,
+ @AuthWorkspace() workspace: Workspace,
): Promise {
+ const viewsToDelete = await this.viewService.findMany({
+ where: args.where,
+ });
+
+ if (!viewsToDelete.length) return { count: 0 };
+
+ const { objectId } = viewsToDelete[0];
+
+ if (viewsToDelete.some((view) => view.objectId !== objectId)) {
+ throw new BadRequestException(
+ `Views must have the same objectId '${objectId}'`,
+ );
+ }
+
+ const viewsNb = await this.viewService.count({
+ where: {
+ objectId: { equals: objectId },
+ workspaceId: { equals: workspace.id },
+ },
+ });
+
+ if (viewsNb - viewsToDelete.length <= 0) {
+ throw new ForbiddenException(
+ `Deleting last '${objectId}' view is not allowed`,
+ );
+ }
+
return this.viewService.deleteMany({
where: args.where,
});