Use tanstackdb for node deletes

This commit is contained in:
Hakan Shehu
2025-10-24 11:56:38 +02:00
parent 6b4ff24852
commit 0e1b658b7d
29 changed files with 179 additions and 529 deletions

View File

@@ -1,22 +0,0 @@
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
ChannelDeleteMutationInput,
ChannelDeleteMutationOutput,
} from '@colanode/client/mutations/channels/channel-delete';
export class ChannelDeleteMutationHandler
extends WorkspaceMutationHandlerBase
implements MutationHandler<ChannelDeleteMutationInput>
{
async handleMutation(
input: ChannelDeleteMutationInput
): Promise<ChannelDeleteMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.deleteNode(input.channelId);
return {
success: true,
};
}
}

View File

@@ -1,22 +0,0 @@
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
DatabaseDeleteMutationInput,
DatabaseDeleteMutationOutput,
} from '@colanode/client/mutations/databases/database-delete';
export class DatabaseDeleteMutationHandler
extends WorkspaceMutationHandlerBase
implements MutationHandler<DatabaseDeleteMutationInput>
{
async handleMutation(
input: DatabaseDeleteMutationInput
): Promise<DatabaseDeleteMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.deleteNode(input.databaseId);
return {
success: true,
};
}
}

View File

@@ -1,22 +0,0 @@
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
ViewDeleteMutationInput,
ViewDeleteMutationOutput,
} from '@colanode/client/mutations/databases/view-delete';
export class ViewDeleteMutationHandler
extends WorkspaceMutationHandlerBase
implements MutationHandler<ViewDeleteMutationInput>
{
async handleMutation(
input: ViewDeleteMutationInput
): Promise<ViewDeleteMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.deleteNode(input.viewId);
return {
id: input.viewId,
};
}
}

View File

@@ -1,23 +0,0 @@
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
FolderDeleteMutationInput,
FolderDeleteMutationOutput,
} from '@colanode/client/mutations';
export class FolderDeleteMutationHandler
extends WorkspaceMutationHandlerBase
implements MutationHandler<FolderDeleteMutationInput>
{
async handleMutation(
input: FolderDeleteMutationInput
): Promise<FolderDeleteMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.deleteNode(input.folderId);
return {
success: true,
};
}
}

View File

@@ -16,9 +16,7 @@ import { TabCreateMutationHandler } from './apps/tab-create';
import { TabDeleteMutationHandler } from './apps/tab-delete';
import { TabUpdateMutationHandler } from './apps/tab-update';
import { AvatarUploadMutationHandler } from './avatars/avatar-upload';
import { ChannelDeleteMutationHandler } from './channels/channel-delete';
import { ChannelUpdateMutationHandler } from './channels/channel-update';
import { DatabaseDeleteMutationHandler } from './databases/database-delete';
import { DatabaseNameFieldUpdateMutationHandler } from './databases/database-name-field-update';
import { DatabaseUpdateMutationHandler } from './databases/database-update';
import { FieldCreateMutationHandler } from './databases/field-create';
@@ -27,7 +25,6 @@ import { FieldNameUpdateMutationHandler } from './databases/field-name-update';
import { SelectOptionCreateMutationHandler } from './databases/select-option-create';
import { SelectOptionDeleteMutationHandler } from './databases/select-option-delete';
import { SelectOptionUpdateMutationHandler } from './databases/select-option-update';
import { ViewDeleteMutationHandler } from './databases/view-delete';
import { ViewNameUpdateMutationHandler } from './databases/view-name-update';
import { ViewUpdateMutationHandler } from './databases/view-update';
import { DocumentUpdateMutationHandler } from './documents/document-update';
@@ -35,28 +32,24 @@ import { FileCreateMutationHandler } from './files/file-create';
import { FileDeleteMutationHandler } from './files/file-delete';
import { FileDownloadMutationHandler } from './files/file-download';
import { TempFileCreateMutationHandler } from './files/temp-file-create';
import { FolderDeleteMutationHandler } from './folders/folder-delete';
import { FolderUpdateMutationHandler } from './folders/folder-update';
import { MessageDeleteMutationHandler } from './messages/message-delete';
import { NodeCollaboratorCreateMutationHandler } from './nodes/node-collaborator-create';
import { NodeCollaboratorDeleteMutationHandler } from './nodes/node-collaborator-delete';
import { NodeCollaboratorUpdateMutationHandler } from './nodes/node-collaborator-update';
import { NodeCreateMutationHandler } from './nodes/node-create';
import { NodeDeleteMutationHandler } from './nodes/node-delete';
import { NodeInteractionOpenedMutationHandler } from './nodes/node-interaction-opened';
import { NodeInteractionSeenMutationHandler } from './nodes/node-interaction-seen';
import { NodeReactionCreateMutationHandler } from './nodes/node-reaction-create';
import { NodeReactionDeleteMutationHandler } from './nodes/node-reaction-delete';
import { PageDeleteMutationHandler } from './pages/page-delete';
import { PageUpdateMutationHandler } from './pages/page-update';
import { RecordAvatarUpdateMutationHandler } from './records/record-avatar-update';
import { RecordDeleteMutationHandler } from './records/record-delete';
import { RecordFieldValueDeleteMutationHandler } from './records/record-field-value-delete';
import { RecordFieldValueSetMutationHandler } from './records/record-field-value-set';
import { RecordNameUpdateMutationHandler } from './records/record-name-update';
import { ServerCreateMutationHandler } from './servers/server-create';
import { ServerDeleteMutationHandler } from './servers/server-delete';
import { SpaceChildReorderMutationHandler } from './spaces/space-child-reorder';
import { SpaceDeleteMutationHandler } from './spaces/space-delete';
import { SpaceUpdateMutationHandler } from './spaces/space-update';
import { UserRoleUpdateMutationHandler } from './users/user-role-update';
import { UserStorageUpdateMutationHandler } from './users/user-storage-update';
@@ -78,8 +71,6 @@ export const buildMutationHandlerMap = (
'email.register': new EmailRegisterMutationHandler(app),
'email.verify': new EmailVerifyMutationHandler(app),
'google.login': new GoogleLoginMutationHandler(app),
'channel.delete': new ChannelDeleteMutationHandler(app),
'database.delete': new DatabaseDeleteMutationHandler(app),
'database.name.field.update': new DatabaseNameFieldUpdateMutationHandler(
app
),
@@ -87,17 +78,13 @@ export const buildMutationHandlerMap = (
'field.delete': new FieldDeleteMutationHandler(app),
'field.name.update': new FieldNameUpdateMutationHandler(app),
'file.delete': new FileDeleteMutationHandler(app),
'folder.delete': new FolderDeleteMutationHandler(app),
'node.collaborator.create': new NodeCollaboratorCreateMutationHandler(app),
'node.collaborator.delete': new NodeCollaboratorDeleteMutationHandler(app),
'node.collaborator.update': new NodeCollaboratorUpdateMutationHandler(app),
'node.interaction.opened': new NodeInteractionOpenedMutationHandler(app),
'node.interaction.seen': new NodeInteractionSeenMutationHandler(app),
'page.delete': new PageDeleteMutationHandler(app),
'node.reaction.create': new NodeReactionCreateMutationHandler(app),
'node.reaction.delete': new NodeReactionDeleteMutationHandler(app),
'message.delete': new MessageDeleteMutationHandler(app),
'record.delete': new RecordDeleteMutationHandler(app),
'record.avatar.update': new RecordAvatarUpdateMutationHandler(app),
'record.name.update': new RecordNameUpdateMutationHandler(app),
'record.field.value.delete': new RecordFieldValueDeleteMutationHandler(app),
@@ -107,7 +94,6 @@ export const buildMutationHandlerMap = (
'select.option.update': new SelectOptionUpdateMutationHandler(app),
'server.create': new ServerCreateMutationHandler(app),
'server.delete': new ServerDeleteMutationHandler(app),
'space.delete': new SpaceDeleteMutationHandler(app),
'user.role.update': new UserRoleUpdateMutationHandler(app),
'users.create': new UsersCreateMutationHandler(app),
'workspace.create': new WorkspaceCreateMutationHandler(app),
@@ -120,7 +106,6 @@ export const buildMutationHandlerMap = (
'space.child.reorder': new SpaceChildReorderMutationHandler(app),
'account.update': new AccountUpdateMutationHandler(app),
'view.update': new ViewUpdateMutationHandler(app),
'view.delete': new ViewDeleteMutationHandler(app),
'view.name.update': new ViewNameUpdateMutationHandler(app),
'channel.update': new ChannelUpdateMutationHandler(app),
'page.update': new PageUpdateMutationHandler(app),
@@ -138,5 +123,6 @@ export const buildMutationHandlerMap = (
'tab.create': new TabCreateMutationHandler(app),
'tab.update': new TabUpdateMutationHandler(app),
'tab.delete': new TabDeleteMutationHandler(app),
'node.delete': new NodeDeleteMutationHandler(app),
};
};

View File

@@ -1,22 +0,0 @@
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
MessageDeleteMutationInput,
MessageDeleteMutationOutput,
} from '@colanode/client/mutations';
export class MessageDeleteMutationHandler
extends WorkspaceMutationHandlerBase
implements MutationHandler<MessageDeleteMutationInput>
{
async handleMutation(
input: MessageDeleteMutationInput
): Promise<MessageDeleteMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.deleteNode(input.messageId);
return {
success: true,
};
}
}

View File

@@ -1,19 +1,19 @@
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
PageDeleteMutationInput,
PageDeleteMutationOutput,
} from '@colanode/client/mutations/pages/page-delete';
NodeDeleteMutationInput,
NodeDeleteMutationOutput,
} from '@colanode/client/mutations/nodes/node-delete';
export class PageDeleteMutationHandler
export class NodeDeleteMutationHandler
extends WorkspaceMutationHandlerBase
implements MutationHandler<PageDeleteMutationInput>
implements MutationHandler<NodeDeleteMutationInput>
{
async handleMutation(
input: PageDeleteMutationInput
): Promise<PageDeleteMutationOutput> {
input: NodeDeleteMutationInput
): Promise<NodeDeleteMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.deleteNode(input.pageId);
await workspace.nodes.deleteNode(input.nodeId);
return {
success: true,

View File

@@ -1,22 +0,0 @@
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
RecordDeleteMutationInput,
RecordDeleteMutationOutput,
} from '@colanode/client/mutations/records/record-delete';
export class RecordDeleteMutationHandler
extends WorkspaceMutationHandlerBase
implements MutationHandler<RecordDeleteMutationInput>
{
async handleMutation(
input: RecordDeleteMutationInput
): Promise<RecordDeleteMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.deleteNode(input.recordId);
return {
success: true,
};
}
}

View File

@@ -1,22 +0,0 @@
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
SpaceDeleteMutationInput,
SpaceDeleteMutationOutput,
} from '@colanode/client/mutations/spaces/space-delete';
export class SpaceDeleteMutationHandler
extends WorkspaceMutationHandlerBase
implements MutationHandler<SpaceDeleteMutationInput>
{
async handleMutation(
input: SpaceDeleteMutationInput
): Promise<SpaceDeleteMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.deleteNode(input.spaceId);
return {
success: true,
};
}
}

View File

@@ -1,18 +0,0 @@
export type ChannelDeleteMutationInput = {
type: 'channel.delete';
userId: string;
channelId: string;
};
export type ChannelDeleteMutationOutput = {
success: boolean;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'channel.delete': {
input: ChannelDeleteMutationInput;
output: ChannelDeleteMutationOutput;
};
}
}

View File

@@ -1,18 +0,0 @@
export type DatabaseDeleteMutationInput = {
type: 'database.delete';
userId: string;
databaseId: string;
};
export type DatabaseDeleteMutationOutput = {
success: boolean;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'database.delete': {
input: DatabaseDeleteMutationInput;
output: DatabaseDeleteMutationOutput;
};
}
}

View File

@@ -1,18 +0,0 @@
export type ViewDeleteMutationInput = {
type: 'view.delete';
userId: string;
viewId: string;
};
export type ViewDeleteMutationOutput = {
id: string;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'view.delete': {
input: ViewDeleteMutationInput;
output: ViewDeleteMutationOutput;
};
}
}

View File

@@ -1,18 +0,0 @@
export type FolderDeleteMutationInput = {
type: 'folder.delete';
userId: string;
folderId: string;
};
export type FolderDeleteMutationOutput = {
success: boolean;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'folder.delete': {
input: FolderDeleteMutationInput;
output: FolderDeleteMutationOutput;
};
}
}

View File

@@ -9,9 +9,7 @@ export * from './accounts/google-login';
export * from './apps/metadata-delete';
export * from './apps/metadata-update';
export * from './avatars/avatar-upload';
export * from './channels/channel-delete';
export * from './channels/channel-update';
export * from './databases/database-delete';
export * from './databases/database-update';
export * from './databases/field-create';
export * from './databases/field-delete';
@@ -19,7 +17,6 @@ export * from './databases/field-name-update';
export * from './databases/select-option-create';
export * from './databases/select-option-delete';
export * from './databases/select-option-update';
export * from './databases/view-delete';
export * from './databases/view-name-update';
export * from './databases/view-update';
export * from './databases/database-name-field-update';
@@ -27,9 +24,7 @@ export * from './documents/document-update';
export * from './files/file-create';
export * from './files/file-delete';
export * from './files/file-download';
export * from './folders/folder-delete';
export * from './folders/folder-update';
export * from './messages/message-delete';
export * from './nodes/node-collaborator-create';
export * from './nodes/node-collaborator-delete';
export * from './nodes/node-collaborator-update';
@@ -37,16 +32,13 @@ export * from './nodes/node-interaction-opened';
export * from './nodes/node-interaction-seen';
export * from './nodes/node-reaction-create';
export * from './nodes/node-reaction-delete';
export * from './pages/page-delete';
export * from './pages/page-update';
export * from './records/record-avatar-update';
export * from './records/record-delete';
export * from './records/record-field-value-delete';
export * from './records/record-field-value-set';
export * from './records/record-name-update';
export * from './servers/server-create';
export * from './servers/server-delete';
export * from './spaces/space-delete';
export * from './spaces/space-update';
export * from './spaces/space-child-reorder';
export * from './workspaces/workspace-create';
@@ -60,6 +52,7 @@ export * from './apps/tab-create';
export * from './apps/tab-update';
export * from './apps/tab-delete';
export * from './nodes/node-create';
export * from './nodes/node-delete';
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface MutationMap {}

View File

@@ -1,18 +0,0 @@
export type MessageDeleteMutationInput = {
type: 'message.delete';
userId: string;
messageId: string;
};
export type MessageDeleteMutationOutput = {
success: boolean;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'message.delete': {
input: MessageDeleteMutationInput;
output: MessageDeleteMutationOutput;
};
}
}

View File

@@ -0,0 +1,18 @@
export type NodeDeleteMutationInput = {
type: 'node.delete';
userId: string;
nodeId: string;
};
export type NodeDeleteMutationOutput = {
success: boolean;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'node.delete': {
input: NodeDeleteMutationInput;
output: NodeDeleteMutationOutput;
};
}
}

View File

@@ -1,18 +0,0 @@
export type PageDeleteMutationInput = {
type: 'page.delete';
userId: string;
pageId: string;
};
export type PageDeleteMutationOutput = {
success: boolean;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'page.delete': {
input: PageDeleteMutationInput;
output: PageDeleteMutationOutput;
};
}
}

View File

@@ -1,18 +0,0 @@
export type RecordDeleteMutationInput = {
type: 'record.delete';
userId: string;
recordId: string;
};
export type RecordDeleteMutationOutput = {
success: boolean;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'record.delete': {
input: RecordDeleteMutationInput;
output: RecordDeleteMutationOutput;
};
}
}

View File

@@ -1,18 +0,0 @@
export type SpaceDeleteMutationInput = {
type: 'space.delete';
userId: string;
spaceId: string;
};
export type SpaceDeleteMutationOutput = {
success: boolean;
};
declare module '@colanode/client/mutations' {
interface MutationMap {
'space.delete': {
input: SpaceDeleteMutationInput;
output: SpaceDeleteMutationOutput;
};
}
}

View File

@@ -1,3 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';
import { toast } from 'sonner';
@@ -11,9 +12,8 @@ import {
AlertDialogTitle,
} from '@colanode/ui/components/ui/alert-dialog';
import { Button } from '@colanode/ui/components/ui/button';
import { Spinner } from '@colanode/ui/components/ui/spinner';
import { useWorkspace } from '@colanode/ui/contexts/workspace';
import { useMutation } from '@colanode/ui/hooks/use-mutation';
import { database } from '@colanode/ui/data';
interface ChannelDeleteDialogProps {
open: boolean;
@@ -28,7 +28,19 @@ export const ChannelDeleteDialog = ({
}: ChannelDeleteDialogProps) => {
const workspace = useWorkspace();
const navigate = useNavigate({ from: '/workspace/$userId' });
const { mutate, isPending } = useMutation();
const { mutate, isPending } = useMutation({
mutationFn: async () => {
const nodes = database.workspace(workspace.userId).nodes;
nodes.delete(channelId);
},
onSuccess: () => {
navigate({ to: 'home', replace: true });
onOpenChange(false);
},
onError: (error) => {
toast.error(error.message);
},
});
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
@@ -43,31 +55,12 @@ export const ChannelDeleteDialog = ({
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={isPending}>Cancel</AlertDialogCancel>
<Button
variant="destructive"
disabled={isPending}
onClick={() => {
mutate({
input: {
type: 'channel.delete',
channelId,
userId: workspace.userId,
},
onSuccess() {
onOpenChange(false);
navigate({
to: '/',
replace: true,
});
},
onError(error) {
toast.error(error.message);
},
});
}}
onClick={() => mutate()}
>
{isPending && <Spinner className="mr-1" />}
Delete
</Button>
</AlertDialogFooter>

View File

@@ -1,3 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';
import { toast } from 'sonner';
@@ -11,9 +12,8 @@ import {
AlertDialogTitle,
} from '@colanode/ui/components/ui/alert-dialog';
import { Button } from '@colanode/ui/components/ui/button';
import { Spinner } from '@colanode/ui/components/ui/spinner';
import { useWorkspace } from '@colanode/ui/contexts/workspace';
import { useMutation } from '@colanode/ui/hooks/use-mutation';
import { database } from '@colanode/ui/data';
interface DatabaseDeleteDialogProps {
open: boolean;
@@ -28,7 +28,19 @@ export const DatabaseDeleteDialog = ({
}: DatabaseDeleteDialogProps) => {
const workspace = useWorkspace();
const navigate = useNavigate({ from: '/workspace/$userId' });
const { mutate, isPending } = useMutation();
const { mutate, isPending } = useMutation({
mutationFn: async () => {
const nodes = database.workspace(workspace.userId).nodes;
nodes.delete(databaseId);
},
onSuccess: () => {
navigate({ to: 'home', replace: true });
onOpenChange(false);
},
onError: (error) => {
toast.error(error.message);
},
});
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
@@ -43,31 +55,12 @@ export const DatabaseDeleteDialog = ({
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={isPending}>Cancel</AlertDialogCancel>
<Button
variant="destructive"
disabled={isPending}
onClick={() => {
mutate({
input: {
type: 'database.delete',
databaseId,
userId: workspace.userId,
},
onSuccess() {
onOpenChange(false);
navigate({
to: '/',
replace: true,
});
},
onError(error) {
toast.error(error.message);
},
});
}}
onClick={() => mutate()}
>
{isPending && <Spinner className="mr-1" />}
Delete
</Button>
</AlertDialogFooter>

View File

@@ -1,3 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { toast } from 'sonner';
import {
@@ -10,10 +11,8 @@ import {
AlertDialogTitle,
} from '@colanode/ui/components/ui/alert-dialog';
import { Button } from '@colanode/ui/components/ui/button';
import { Spinner } from '@colanode/ui/components/ui/spinner';
import { useDatabase } from '@colanode/ui/contexts/database';
import { useWorkspace } from '@colanode/ui/contexts/workspace';
import { useMutation } from '@colanode/ui/hooks/use-mutation';
import { database } from '@colanode/ui/data';
interface ViewDeleteDialogProps {
id: string;
@@ -27,12 +26,18 @@ export const ViewDeleteDialog = ({
onOpenChange,
}: ViewDeleteDialogProps) => {
const workspace = useWorkspace();
const database = useDatabase();
const { mutate, isPending } = useMutation();
if (!database.canEdit) {
return null;
}
const { mutate, isPending } = useMutation({
mutationFn: async () => {
const nodes = database.workspace(workspace.userId).nodes;
nodes.delete(id);
},
onSuccess: () => {
onOpenChange(false);
},
onError: (error) => {
toast.error(error.message);
},
});
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
@@ -47,28 +52,12 @@ export const ViewDeleteDialog = ({
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={isPending}>Cancel</AlertDialogCancel>
<Button
variant="destructive"
disabled={isPending}
onClick={() => {
mutate({
input: {
type: 'view.delete',
viewId: id,
databaseId: database.id,
userId: workspace.userId,
},
onSuccess() {
onOpenChange(false);
},
onError(error) {
toast.error(error.message);
},
});
}}
onClick={() => mutate()}
>
{isPending && <Spinner className="mr-1" />}
Delete
</Button>
</AlertDialogFooter>

View File

@@ -1,3 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';
import { toast } from 'sonner';
@@ -11,9 +12,8 @@ import {
AlertDialogTitle,
} from '@colanode/ui/components/ui/alert-dialog';
import { Button } from '@colanode/ui/components/ui/button';
import { Spinner } from '@colanode/ui/components/ui/spinner';
import { useWorkspace } from '@colanode/ui/contexts/workspace';
import { useMutation } from '@colanode/ui/hooks/use-mutation';
import { database } from '@colanode/ui/data';
interface FolderDeleteDialogProps {
open: boolean;
@@ -28,7 +28,19 @@ export const FolderDeleteDialog = ({
}: FolderDeleteDialogProps) => {
const workspace = useWorkspace();
const navigate = useNavigate({ from: '/workspace/$userId' });
const { mutate, isPending } = useMutation();
const { mutate, isPending } = useMutation({
mutationFn: async () => {
const nodes = database.workspace(workspace.userId).nodes;
nodes.delete(folderId);
},
onSuccess: () => {
navigate({ to: 'home', replace: true });
onOpenChange(false);
},
onError: (error) => {
toast.error(error.message);
},
});
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
@@ -43,30 +55,12 @@ export const FolderDeleteDialog = ({
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={isPending}>Cancel</AlertDialogCancel>
<Button
variant="destructive"
disabled={isPending}
onClick={() => {
mutate({
input: {
type: 'folder.delete',
folderId: folderId,
userId: workspace.userId,
},
onSuccess() {
onOpenChange(false);
navigate({
to: '/',
});
},
onError(error) {
toast.error(error.message);
},
});
}}
onClick={() => mutate()}
>
{isPending && <Spinner className="mr-1" />}
Delete
</Button>
</AlertDialogFooter>

View File

@@ -1,3 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { toast } from 'sonner';
import {
@@ -10,9 +11,8 @@ import {
AlertDialogTitle,
} from '@colanode/ui/components/ui/alert-dialog';
import { Button } from '@colanode/ui/components/ui/button';
import { Spinner } from '@colanode/ui/components/ui/spinner';
import { useWorkspace } from '@colanode/ui/contexts/workspace';
import { useMutation } from '@colanode/ui/hooks/use-mutation';
import { database } from '@colanode/ui/data';
interface MessageDeleteDialogProps {
id: string;
@@ -26,7 +26,18 @@ export const MessageDeleteDialog = ({
onOpenChange,
}: MessageDeleteDialogProps) => {
const workspace = useWorkspace();
const { mutate, isPending } = useMutation();
const { mutate, isPending } = useMutation({
mutationFn: async () => {
const nodes = database.workspace(workspace.userId).nodes;
nodes.delete(id);
},
onSuccess: () => {
onOpenChange(false);
},
onError: (error) => {
toast.error(error.message);
},
});
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
@@ -41,27 +52,12 @@ export const MessageDeleteDialog = ({
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={isPending}>Cancel</AlertDialogCancel>
<Button
variant="destructive"
disabled={isPending}
onClick={() => {
mutate({
input: {
type: 'message.delete',
messageId: id,
userId: workspace.userId,
},
onSuccess() {
onOpenChange(false);
},
onError(error) {
toast.error(error.message);
},
});
}}
onClick={() => mutate()}
>
{isPending && <Spinner className="mr-1" />}
Delete
</Button>
</AlertDialogFooter>

View File

@@ -1,3 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';
import { toast } from 'sonner';
@@ -11,9 +12,8 @@ import {
AlertDialogTitle,
} from '@colanode/ui/components/ui/alert-dialog';
import { Button } from '@colanode/ui/components/ui/button';
import { Spinner } from '@colanode/ui/components/ui/spinner';
import { useWorkspace } from '@colanode/ui/contexts/workspace';
import { useMutation } from '@colanode/ui/hooks/use-mutation';
import { database } from '@colanode/ui/data';
interface PageDeleteDialogProps {
open: boolean;
@@ -28,7 +28,19 @@ export const PageDeleteDialog = ({
}: PageDeleteDialogProps) => {
const workspace = useWorkspace();
const navigate = useNavigate({ from: '/workspace/$userId' });
const { mutate, isPending } = useMutation();
const { mutate, isPending } = useMutation({
mutationFn: async () => {
const nodes = database.workspace(workspace.userId).nodes;
nodes.delete(pageId);
},
onSuccess: () => {
navigate({ to: 'home', replace: true });
onOpenChange(false);
},
onError: (error) => {
toast.error(error.message);
},
});
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
@@ -43,30 +55,12 @@ export const PageDeleteDialog = ({
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={isPending}>Cancel</AlertDialogCancel>
<Button
variant="destructive"
disabled={isPending}
onClick={() => {
mutate({
input: {
type: 'page.delete',
pageId,
userId: workspace.userId,
},
onSuccess() {
onOpenChange(false);
navigate({
to: '/',
});
},
onError(error) {
toast.error(error.message);
},
});
}}
onClick={() => mutate()}
>
{isPending && <Spinner className="mr-1" />}
Delete
</Button>
</AlertDialogFooter>

View File

@@ -1,3 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';
import { toast } from 'sonner';
@@ -11,9 +12,8 @@ import {
AlertDialogTitle,
} from '@colanode/ui/components/ui/alert-dialog';
import { Button } from '@colanode/ui/components/ui/button';
import { Spinner } from '@colanode/ui/components/ui/spinner';
import { useWorkspace } from '@colanode/ui/contexts/workspace';
import { useMutation } from '@colanode/ui/hooks/use-mutation';
import { database } from '@colanode/ui/data';
interface RecordDeleteDialogProps {
open: boolean;
@@ -28,7 +28,19 @@ export const RecordDeleteDialog = ({
}: RecordDeleteDialogProps) => {
const workspace = useWorkspace();
const navigate = useNavigate({ from: '/workspace/$userId' });
const { mutate, isPending } = useMutation();
const { mutate, isPending } = useMutation({
mutationFn: async () => {
const nodes = database.workspace(workspace.userId).nodes;
nodes.delete(recordId);
},
onSuccess: () => {
navigate({ to: 'home', replace: true });
onOpenChange(false);
},
onError: (error) => {
toast.error(error.message);
},
});
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
@@ -43,30 +55,12 @@ export const RecordDeleteDialog = ({
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={isPending}>Cancel</AlertDialogCancel>
<Button
variant="destructive"
disabled={isPending}
onClick={() => {
mutate({
input: {
type: 'record.delete',
recordId: recordId,
userId: workspace.userId,
},
onSuccess() {
onOpenChange(false);
navigate({
to: '/',
});
},
onError(error) {
toast.error(error.message);
},
});
}}
onClick={() => mutate()}
>
{isPending && <Spinner className="mr-1" />}
Delete
</Button>
</AlertDialogFooter>

View File

@@ -1,4 +1,3 @@
import { useNavigate } from '@tanstack/react-router';
import { toast } from 'sonner';
import { LocalSpaceNode } from '@colanode/client/types';
@@ -17,7 +16,6 @@ interface SpaceBodyProps {
export const SpaceBody = ({ space, role }: SpaceBodyProps) => {
const workspace = useWorkspace();
const navigate = useNavigate({ from: '/workspace/$userId' });
const { mutate, isPending } = useMutation();
const canEdit = hasNodeRole(role, 'admin');
@@ -78,14 +76,7 @@ export const SpaceBody = ({ space, role }: SpaceBodyProps) => {
</h2>
<Separator className="mt-3" />
</div>
<SpaceDelete
id={space.id}
onDeleted={() => {
navigate({
to: '/',
});
}}
/>
<SpaceDelete id={space.id} />
</div>
)}
</div>

View File

@@ -1,3 +1,5 @@
import { useMutation } from '@tanstack/react-query';
import { useNavigate } from '@tanstack/react-router';
import { useState } from 'react';
import { toast } from 'sonner';
@@ -11,18 +13,30 @@ import {
AlertDialogTitle,
} from '@colanode/ui/components/ui/alert-dialog';
import { Button } from '@colanode/ui/components/ui/button';
import { Spinner } from '@colanode/ui/components/ui/spinner';
import { useWorkspace } from '@colanode/ui/contexts/workspace';
import { useMutation } from '@colanode/ui/hooks/use-mutation';
import { database } from '@colanode/ui/data';
interface SpaceDeleteProps {
id: string;
onDeleted: () => void;
}
export const SpaceDelete = ({ id, onDeleted }: SpaceDeleteProps) => {
export const SpaceDelete = ({ id }: SpaceDeleteProps) => {
const workspace = useWorkspace();
const { mutate, isPending } = useMutation();
const navigate = useNavigate({ from: '/workspace/$userId' });
const { mutate, isPending } = useMutation({
mutationFn: async () => {
const nodes = database.workspace(workspace.userId).nodes;
nodes.delete(id);
},
onSuccess: () => {
navigate({ to: 'home', replace: true });
setShowDeleteModal(false);
},
onError: (error) => {
toast.error(error.message);
},
});
const [showDeleteModal, setShowDeleteModal] = useState(false);
@@ -59,29 +73,12 @@ export const SpaceDelete = ({ id, onDeleted }: SpaceDeleteProps) => {
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={isPending}>Cancel</AlertDialogCancel>
<Button
variant="destructive"
disabled={isPending}
onClick={() => {
mutate({
input: {
type: 'space.delete',
userId: workspace.userId,
spaceId: id,
},
onSuccess() {
setShowDeleteModal(false);
onDeleted();
toast.success('Space deleted');
},
onError(error) {
toast.error(error.message);
},
});
}}
onClick={() => mutate()}
>
{isPending && <Spinner className="mr-1" />}
Delete
</Button>
</AlertDialogFooter>

View File

@@ -59,5 +59,16 @@ export const createNodesCollection = (userId: string) => {
})
);
},
onDelete: async ({ transaction }) => {
await Promise.all(
transaction.mutations.map(async (mutation) => {
return await window.colanode.executeMutation({
type: 'node.delete',
userId,
nodeId: mutation.key,
});
})
);
},
});
};