mirror of
https://github.com/colanode/colanode.git
synced 2025-12-16 11:47:47 +01:00
Use tanstackdb for some field mutations
This commit is contained in:
@@ -1,47 +0,0 @@
|
||||
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import { MutationError, MutationErrorCode } from '@colanode/client/mutations';
|
||||
import {
|
||||
DatabaseNameFieldUpdateMutationInput,
|
||||
DatabaseNameFieldUpdateMutationOutput,
|
||||
} from '@colanode/client/mutations/databases/database-name-field-update';
|
||||
import { DatabaseAttributes } from '@colanode/core';
|
||||
|
||||
export class DatabaseNameFieldUpdateMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<DatabaseNameFieldUpdateMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: DatabaseNameFieldUpdateMutationInput
|
||||
): Promise<DatabaseNameFieldUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
(attributes) => {
|
||||
attributes.nameField = {
|
||||
name: input.name,
|
||||
};
|
||||
|
||||
return attributes;
|
||||
}
|
||||
);
|
||||
|
||||
if (result === 'unauthorized') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.DatabaseUpdateForbidden,
|
||||
"You don't have permission to update this database."
|
||||
);
|
||||
}
|
||||
|
||||
if (result !== 'success') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.DatabaseUpdateFailed,
|
||||
'Something went wrong while updating the database.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import { fetchNode } from '@colanode/client/lib/utils';
|
||||
import { MutationError, MutationErrorCode } from '@colanode/client/mutations';
|
||||
import {
|
||||
FieldCreateMutationInput,
|
||||
FieldCreateMutationOutput,
|
||||
} from '@colanode/client/mutations/databases/field-create';
|
||||
import {
|
||||
compareString,
|
||||
DatabaseAttributes,
|
||||
FieldAttributes,
|
||||
FieldType,
|
||||
generateId,
|
||||
generateFractionalIndex,
|
||||
IdType,
|
||||
} from '@colanode/core';
|
||||
|
||||
export class FieldCreateMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<FieldCreateMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: FieldCreateMutationInput
|
||||
): Promise<FieldCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
if (input.fieldType === 'relation') {
|
||||
if (!input.relationDatabaseId) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.RelationDatabaseNotFound,
|
||||
'Relation database not found.'
|
||||
);
|
||||
}
|
||||
|
||||
const relationDatabase = await fetchNode(
|
||||
workspace.database,
|
||||
input.relationDatabaseId
|
||||
);
|
||||
|
||||
if (!relationDatabase || relationDatabase.type !== 'database') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.RelationDatabaseNotFound,
|
||||
'Relation database not found.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const fieldId = generateId(IdType.Field);
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
(attributes) => {
|
||||
const maxIndex = Object.values(attributes.fields)
|
||||
.map((field) => field.index)
|
||||
.sort((a, b) => -compareString(a, b))[0];
|
||||
|
||||
const index = generateFractionalIndex(maxIndex, null);
|
||||
|
||||
const newField: FieldAttributes = {
|
||||
id: fieldId,
|
||||
type: input.fieldType as FieldType,
|
||||
name: input.name,
|
||||
index,
|
||||
};
|
||||
|
||||
if (newField.type === 'relation') {
|
||||
newField.databaseId = input.relationDatabaseId;
|
||||
}
|
||||
|
||||
attributes.fields[fieldId] = newField;
|
||||
|
||||
return attributes;
|
||||
}
|
||||
);
|
||||
|
||||
if (result === 'unauthorized') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldCreateForbidden,
|
||||
"You don't have permission to create a field in this database."
|
||||
);
|
||||
}
|
||||
|
||||
if (result !== 'success') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldCreateFailed,
|
||||
'Something went wrong while creating the field.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
id: fieldId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import { MutationError, MutationErrorCode } from '@colanode/client/mutations';
|
||||
import {
|
||||
FieldDeleteMutationInput,
|
||||
FieldDeleteMutationOutput,
|
||||
} from '@colanode/client/mutations/databases/field-delete';
|
||||
import { DatabaseAttributes } from '@colanode/core';
|
||||
|
||||
export class FieldDeleteMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<FieldDeleteMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: FieldDeleteMutationInput
|
||||
): Promise<FieldDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
(attributes) => {
|
||||
delete attributes.fields[input.fieldId];
|
||||
|
||||
return attributes;
|
||||
}
|
||||
);
|
||||
|
||||
if (result === 'unauthorized') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldDeleteForbidden,
|
||||
"You don't have permission to delete this field."
|
||||
);
|
||||
}
|
||||
|
||||
if (result !== 'success') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldDeleteFailed,
|
||||
'Something went wrong while deleting the field.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
id: input.fieldId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import { MutationError, MutationErrorCode } from '@colanode/client/mutations';
|
||||
import {
|
||||
FieldNameUpdateMutationInput,
|
||||
FieldNameUpdateMutationOutput,
|
||||
} from '@colanode/client/mutations/databases/field-name-update';
|
||||
import { DatabaseAttributes } from '@colanode/core';
|
||||
|
||||
export class FieldNameUpdateMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<FieldNameUpdateMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: FieldNameUpdateMutationInput
|
||||
): Promise<FieldNameUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
(attributes) => {
|
||||
const field = attributes.fields[input.fieldId];
|
||||
if (!field) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldNotFound,
|
||||
'The field you are trying to update does not exist.'
|
||||
);
|
||||
}
|
||||
|
||||
field.name = input.name;
|
||||
return attributes;
|
||||
}
|
||||
);
|
||||
|
||||
if (result === 'unauthorized') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldUpdateForbidden,
|
||||
"You don't have permission to update this field."
|
||||
);
|
||||
}
|
||||
|
||||
if (result !== 'success') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldUpdateFailed,
|
||||
'Something went wrong while updating the field.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
id: input.fieldId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,6 @@ import { EmailVerifyMutationHandler } from './auth/email-verify';
|
||||
import { GoogleLoginMutationHandler } from './auth/google-login';
|
||||
import { AvatarUploadMutationHandler } from './avatars/avatar-upload';
|
||||
import { ChatCreateMutationHandler } from './chats/chat-create';
|
||||
import { DatabaseNameFieldUpdateMutationHandler } from './databases/database-name-field-update';
|
||||
import { FieldCreateMutationHandler } from './databases/field-create';
|
||||
import { FieldDeleteMutationHandler } from './databases/field-delete';
|
||||
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';
|
||||
@@ -67,12 +63,6 @@ export const buildMutationHandlerMap = (
|
||||
'node.create': new NodeCreateMutationHandler(app),
|
||||
'node.update': new NodeUpdateMutationHandler(app),
|
||||
'chat.create': new ChatCreateMutationHandler(app),
|
||||
'database.name.field.update': new DatabaseNameFieldUpdateMutationHandler(
|
||||
app
|
||||
),
|
||||
'field.create': new FieldCreateMutationHandler(app),
|
||||
'field.delete': new FieldDeleteMutationHandler(app),
|
||||
'field.name.update': new FieldNameUpdateMutationHandler(app),
|
||||
'message.create': new MessageCreateMutationHandler(app),
|
||||
'node.collaborator.create': new NodeCollaboratorCreateMutationHandler(app),
|
||||
'node.collaborator.delete': new NodeCollaboratorDeleteMutationHandler(app),
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
export type DatabaseNameFieldUpdateMutationInput = {
|
||||
type: 'database.name.field.update';
|
||||
userId: string;
|
||||
databaseId: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type DatabaseNameFieldUpdateMutationOutput = {
|
||||
success: boolean;
|
||||
};
|
||||
|
||||
declare module '@colanode/client/mutations' {
|
||||
interface MutationMap {
|
||||
'database.name.field.update': {
|
||||
input: DatabaseNameFieldUpdateMutationInput;
|
||||
output: DatabaseNameFieldUpdateMutationOutput;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import { FieldType } from '@colanode/core';
|
||||
|
||||
export type FieldCreateMutationInput = {
|
||||
type: 'field.create';
|
||||
userId: string;
|
||||
databaseId: string;
|
||||
name: string;
|
||||
fieldType: FieldType;
|
||||
relationDatabaseId?: string | null;
|
||||
};
|
||||
|
||||
export type FieldCreateMutationOutput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
declare module '@colanode/client/mutations' {
|
||||
interface MutationMap {
|
||||
'field.create': {
|
||||
input: FieldCreateMutationInput;
|
||||
output: FieldCreateMutationOutput;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
export type FieldDeleteMutationInput = {
|
||||
type: 'field.delete';
|
||||
userId: string;
|
||||
databaseId: string;
|
||||
fieldId: string;
|
||||
};
|
||||
|
||||
export type FieldDeleteMutationOutput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
declare module '@colanode/client/mutations' {
|
||||
interface MutationMap {
|
||||
'field.delete': {
|
||||
input: FieldDeleteMutationInput;
|
||||
output: FieldDeleteMutationOutput;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
export type FieldNameUpdateMutationInput = {
|
||||
type: 'field.name.update';
|
||||
userId: string;
|
||||
databaseId: string;
|
||||
fieldId: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type FieldNameUpdateMutationOutput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
declare module '@colanode/client/mutations' {
|
||||
interface MutationMap {
|
||||
'field.name.update': {
|
||||
input: FieldNameUpdateMutationInput;
|
||||
output: FieldNameUpdateMutationOutput;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -10,14 +10,10 @@ export * from './apps/metadata-delete';
|
||||
export * from './apps/metadata-update';
|
||||
export * from './avatars/avatar-upload';
|
||||
export * from './chats/chat-create';
|
||||
export * from './databases/field-create';
|
||||
export * from './databases/field-delete';
|
||||
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-update';
|
||||
export * from './databases/database-name-field-update';
|
||||
export * from './documents/document-update';
|
||||
export * from './files/file-create';
|
||||
export * from './files/file-download';
|
||||
|
||||
@@ -49,7 +49,7 @@ export const DatabaseCreateDialog = ({
|
||||
name: values.name,
|
||||
parentId: spaceId,
|
||||
fields: {
|
||||
[generateId(IdType.Field)]: {
|
||||
[fieldId]: {
|
||||
id: fieldId,
|
||||
type: 'text',
|
||||
index: generateFractionalIndex(null, null),
|
||||
|
||||
@@ -28,64 +28,6 @@ export const Database = ({ database, role, children }: DatabaseProps) => {
|
||||
canEdit,
|
||||
canCreateRecord,
|
||||
rootId: database.rootId,
|
||||
createField: async (type, name) => {
|
||||
if (!canEdit) return;
|
||||
|
||||
const result = await window.colanode.executeMutation({
|
||||
type: 'field.create',
|
||||
databaseId: database.id,
|
||||
name,
|
||||
fieldType: type,
|
||||
userId: workspace.userId,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(result.error.message);
|
||||
}
|
||||
},
|
||||
renameField: async (id, name) => {
|
||||
if (!canEdit) return;
|
||||
|
||||
const result = await window.colanode.executeMutation({
|
||||
type: 'field.name.update',
|
||||
databaseId: database.id,
|
||||
fieldId: id,
|
||||
name,
|
||||
userId: workspace.userId,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(result.error.message);
|
||||
}
|
||||
},
|
||||
updateNameField: async (name) => {
|
||||
if (!canEdit) return;
|
||||
|
||||
const result = await window.colanode.executeMutation({
|
||||
type: 'database.name.field.update',
|
||||
databaseId: database.id,
|
||||
name,
|
||||
userId: workspace.userId,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(result.error.message);
|
||||
}
|
||||
},
|
||||
deleteField: async (id) => {
|
||||
if (!canEdit) return;
|
||||
|
||||
const result = await window.colanode.executeMutation({
|
||||
type: 'field.delete',
|
||||
databaseId: database.id,
|
||||
fieldId: id,
|
||||
userId: workspace.userId,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(result.error.message);
|
||||
}
|
||||
},
|
||||
createSelectOption: async (fieldId, name, color) => {
|
||||
if (!canEdit) return;
|
||||
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { toast } from 'sonner';
|
||||
import { z } from 'zod/v4';
|
||||
|
||||
import { FieldType } from '@colanode/core';
|
||||
import { MutationError, MutationErrorCode } from '@colanode/client/mutations';
|
||||
import {
|
||||
compareString,
|
||||
FieldAttributes,
|
||||
FieldType,
|
||||
generateFractionalIndex,
|
||||
generateId,
|
||||
IdType,
|
||||
} from '@colanode/core';
|
||||
import { collections } from '@colanode/ui/collections';
|
||||
import { DatabaseSelect } from '@colanode/ui/components/databases/database-select';
|
||||
import { FieldTypeSelect } from '@colanode/ui/components/databases/fields/field-type-select';
|
||||
import { Button } from '@colanode/ui/components/ui/button';
|
||||
@@ -25,7 +35,6 @@ import {
|
||||
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';
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(1, { message: 'Name is required' }),
|
||||
@@ -50,6 +59,8 @@ const formSchema = z.object({
|
||||
relationDatabaseId: z.string().optional().nullable(),
|
||||
});
|
||||
|
||||
type FieldCreateFormValues = z.infer<typeof formSchema>;
|
||||
|
||||
interface FieldCreatePopoverProps {
|
||||
button: React.ReactNode;
|
||||
onSuccess?: (fieldId: string) => void;
|
||||
@@ -65,9 +76,7 @@ export const FieldCreatePopover = ({
|
||||
const workspace = useWorkspace();
|
||||
const database = useDatabase();
|
||||
|
||||
const { mutate, isPending } = useMutation();
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
const form = useForm<FieldCreateFormValues>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
name: '',
|
||||
@@ -82,26 +91,71 @@ export const FieldCreatePopover = ({
|
||||
form.reset();
|
||||
};
|
||||
|
||||
const handleSubmit = (values: z.infer<typeof formSchema>) => {
|
||||
mutate({
|
||||
input: {
|
||||
type: 'field.create',
|
||||
databaseId: database.id,
|
||||
name: values.name,
|
||||
fieldType: values.type,
|
||||
userId: workspace.userId,
|
||||
relationDatabaseId: values.relationDatabaseId,
|
||||
},
|
||||
onSuccess: (output) => {
|
||||
setOpen(false);
|
||||
form.reset();
|
||||
onSuccess?.(output.id);
|
||||
},
|
||||
onError(error) {
|
||||
toast.error(error.message);
|
||||
},
|
||||
});
|
||||
};
|
||||
const { mutate, isPending } = useMutation({
|
||||
mutationFn: async (values: FieldCreateFormValues) => {
|
||||
const nodes = collections.workspace(workspace.userId).nodes;
|
||||
|
||||
if (values.type === 'relation') {
|
||||
if (!values.relationDatabaseId) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.RelationDatabaseNotFound,
|
||||
'Relation database not found.'
|
||||
);
|
||||
}
|
||||
|
||||
const relationDatabase = nodes.get(values.relationDatabaseId);
|
||||
if (!relationDatabase || relationDatabase.type !== 'database') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.RelationDatabaseNotFound,
|
||||
'Relation database not found.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!nodes.has(database.id)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fieldId = generateId(IdType.Field);
|
||||
nodes.update(database.id, (draft) => {
|
||||
if (draft.type !== 'database') {
|
||||
return;
|
||||
}
|
||||
|
||||
const maxIndex = Object.values(draft.fields)
|
||||
.map((field) => field.index)
|
||||
.sort((a, b) => -compareString(a, b))[0];
|
||||
|
||||
const index = generateFractionalIndex(maxIndex, null);
|
||||
|
||||
const newField: FieldAttributes = {
|
||||
id: fieldId,
|
||||
type: values.type as FieldType,
|
||||
name: values.name,
|
||||
index,
|
||||
};
|
||||
|
||||
if (newField.type === 'relation') {
|
||||
newField.databaseId = values.relationDatabaseId;
|
||||
}
|
||||
|
||||
draft.fields[fieldId] = newField;
|
||||
});
|
||||
|
||||
return fieldId;
|
||||
},
|
||||
onSuccess: (fieldId) => {
|
||||
form.reset();
|
||||
setOpen(false);
|
||||
|
||||
if (fieldId) {
|
||||
onSuccess?.(fieldId);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(error.message as string);
|
||||
},
|
||||
});
|
||||
|
||||
if (!database.canEdit) {
|
||||
return null;
|
||||
@@ -114,7 +168,7 @@ export const FieldCreatePopover = ({
|
||||
<Form {...form}>
|
||||
<form
|
||||
className="flex flex-col gap-2"
|
||||
onSubmit={form.handleSubmit(handleSubmit)}
|
||||
onSubmit={form.handleSubmit((values) => mutate(values))}
|
||||
>
|
||||
<div className="grow space-y-4 py-2 pb-4">
|
||||
<FormField
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { collections } from '@colanode/ui/collections';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogCancel,
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
} from '@colanode/ui/components/ui/alert-dialog';
|
||||
import { Button } from '@colanode/ui/components/ui/button';
|
||||
import { useDatabase } from '@colanode/ui/contexts/database';
|
||||
import { useWorkspace } from '@colanode/ui/contexts/workspace';
|
||||
|
||||
interface FieldDeleteDialogProps {
|
||||
id: string;
|
||||
@@ -21,6 +23,7 @@ export const FieldDeleteDialog = ({
|
||||
open,
|
||||
onOpenChange,
|
||||
}: FieldDeleteDialogProps) => {
|
||||
const workspace = useWorkspace();
|
||||
const database = useDatabase();
|
||||
|
||||
return (
|
||||
@@ -40,7 +43,15 @@ export const FieldDeleteDialog = ({
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={async () => {
|
||||
database.deleteField(id);
|
||||
const nodes = collections.workspace(workspace.userId).nodes;
|
||||
nodes.update(database.id, (draft) => {
|
||||
if (draft.type !== 'database') {
|
||||
return;
|
||||
}
|
||||
|
||||
const { [id]: _removed, ...rest } = draft.fields;
|
||||
draft.fields = rest;
|
||||
});
|
||||
onOpenChange(false);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { FieldAttributes } from '@colanode/core';
|
||||
import { collections } from '@colanode/ui/collections';
|
||||
import { SmartTextInput } from '@colanode/ui/components/ui/smart-text-input';
|
||||
import { useDatabase } from '@colanode/ui/contexts/database';
|
||||
import { useWorkspace } from '@colanode/ui/contexts/workspace';
|
||||
|
||||
interface FieldRenameInputProps {
|
||||
field: FieldAttributes;
|
||||
}
|
||||
|
||||
export const FieldRenameInput = ({ field }: FieldRenameInputProps) => {
|
||||
const workspace = useWorkspace();
|
||||
const database = useDatabase();
|
||||
|
||||
return (
|
||||
@@ -16,7 +19,20 @@ export const FieldRenameInput = ({ field }: FieldRenameInputProps) => {
|
||||
readOnly={!database.canEdit}
|
||||
onChange={(newName) => {
|
||||
if (newName === field.name) return;
|
||||
database.renameField(field.id, newName);
|
||||
|
||||
const nodes = collections.workspace(workspace.userId).nodes;
|
||||
nodes.update(database.id, (draft) => {
|
||||
if (draft.type !== 'database') {
|
||||
return;
|
||||
}
|
||||
|
||||
const fieldAttributes = draft.fields[field.id];
|
||||
if (!fieldAttributes) {
|
||||
return;
|
||||
}
|
||||
|
||||
fieldAttributes.name = newName;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Fragment, useRef, useState } from 'react';
|
||||
import { useDrop } from 'react-dnd';
|
||||
|
||||
import { SpecialId } from '@colanode/core';
|
||||
import { collections } from '@colanode/ui/collections';
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
@@ -13,9 +14,11 @@ import { Separator } from '@colanode/ui/components/ui/separator';
|
||||
import { SmartTextInput } from '@colanode/ui/components/ui/smart-text-input';
|
||||
import { useDatabase } from '@colanode/ui/contexts/database';
|
||||
import { useDatabaseView } from '@colanode/ui/contexts/database-view';
|
||||
import { useWorkspace } from '@colanode/ui/contexts/workspace';
|
||||
import { cn } from '@colanode/ui/lib/utils';
|
||||
|
||||
export const TableViewNameHeader = () => {
|
||||
const workspace = useWorkspace();
|
||||
const database = useDatabase();
|
||||
const view = useDatabaseView();
|
||||
|
||||
@@ -90,7 +93,14 @@ export const TableViewNameHeader = () => {
|
||||
readOnly={!database.canEdit}
|
||||
onChange={(newName) => {
|
||||
if (newName === database.nameField?.name) return;
|
||||
database.updateNameField(newName);
|
||||
const nodes = collections.workspace(workspace.userId).nodes;
|
||||
nodes.update(database.id, (draft) => {
|
||||
if (draft.type !== 'database') {
|
||||
return;
|
||||
}
|
||||
|
||||
draft.nameField = { name: newName };
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { createContext, useContext } from 'react';
|
||||
import {
|
||||
DatabaseNameFieldAttributes,
|
||||
FieldAttributes,
|
||||
FieldType,
|
||||
NodeRole,
|
||||
SelectOptionAttributes,
|
||||
} from '@colanode/core';
|
||||
@@ -17,10 +16,6 @@ interface DatabaseContext {
|
||||
canCreateRecord: boolean;
|
||||
role: NodeRole;
|
||||
rootId: string;
|
||||
createField: (type: FieldType, name: string) => void;
|
||||
renameField: (id: string, name: string) => void;
|
||||
updateNameField: (name: string) => void;
|
||||
deleteField: (id: string) => void;
|
||||
createSelectOption: (fieldId: string, name: string, color: string) => void;
|
||||
updateSelectOption: (
|
||||
fieldId: string,
|
||||
|
||||
@@ -32,7 +32,7 @@ export const DatabaseInlineCommand: EditorCommand = {
|
||||
name: 'Untitled',
|
||||
parentId: documentId,
|
||||
fields: {
|
||||
[generateId(IdType.Field)]: {
|
||||
[fieldId]: {
|
||||
id: fieldId,
|
||||
type: 'text',
|
||||
index: generateFractionalIndex(null, null),
|
||||
|
||||
@@ -32,7 +32,7 @@ export const DatabaseCommand: EditorCommand = {
|
||||
name: 'Untitled',
|
||||
parentId: documentId,
|
||||
fields: {
|
||||
[generateId(IdType.Field)]: {
|
||||
[fieldId]: {
|
||||
id: fieldId,
|
||||
type: 'text',
|
||||
index: generateFractionalIndex(null, null),
|
||||
|
||||
Reference in New Issue
Block a user