mirror of
https://github.com/colanode/colanode.git
synced 2025-12-16 11:47:47 +01:00
Use tanstackdb for select option mutations
This commit is contained in:
@@ -1,83 +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 {
|
||||
SelectOptionCreateMutationInput,
|
||||
SelectOptionCreateMutationOutput,
|
||||
} from '@colanode/client/mutations/databases/select-option-create';
|
||||
import {
|
||||
compareString,
|
||||
DatabaseAttributes,
|
||||
generateId,
|
||||
generateFractionalIndex,
|
||||
IdType,
|
||||
} from '@colanode/core';
|
||||
|
||||
export class SelectOptionCreateMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<SelectOptionCreateMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: SelectOptionCreateMutationInput
|
||||
): Promise<SelectOptionCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const id = generateId(IdType.SelectOption);
|
||||
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 create a select option in does not exist.'
|
||||
);
|
||||
}
|
||||
|
||||
if (field.type !== 'multi_select' && field.type !== 'select') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldTypeInvalid,
|
||||
'The field you are trying to create a select option in is not a "Select" or "Multi-Select" field.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!field.options) {
|
||||
field.options = {};
|
||||
}
|
||||
|
||||
const maxIndex = Object.values(field.options)
|
||||
.map((selectOption) => selectOption.index)
|
||||
.sort((a, b) => -compareString(a, b))[0];
|
||||
|
||||
const index = generateFractionalIndex(maxIndex, null);
|
||||
|
||||
field.options[id] = {
|
||||
name: input.name,
|
||||
id: id,
|
||||
color: input.color,
|
||||
index: index,
|
||||
};
|
||||
|
||||
return attributes;
|
||||
}
|
||||
);
|
||||
|
||||
if (result === 'unauthorized') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionCreateForbidden,
|
||||
"You don't have permission to create a select option in this field."
|
||||
);
|
||||
}
|
||||
|
||||
if (result !== 'success') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionCreateFailed,
|
||||
'Something went wrong while creating the select option.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
id: id,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,75 +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 {
|
||||
SelectOptionDeleteMutationInput,
|
||||
SelectOptionDeleteMutationOutput,
|
||||
} from '@colanode/client/mutations/databases/select-option-delete';
|
||||
import { DatabaseAttributes } from '@colanode/core';
|
||||
|
||||
export class SelectOptionDeleteMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<SelectOptionDeleteMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: SelectOptionDeleteMutationInput
|
||||
): Promise<SelectOptionDeleteMutationOutput> {
|
||||
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 delete a select option from does not exist.'
|
||||
);
|
||||
}
|
||||
|
||||
if (field.type !== 'multi_select' && field.type !== 'select') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldTypeInvalid,
|
||||
'The field you are trying to delete a select option from is not a "Select" or "Multi-Select" field.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!field.options) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionNotFound,
|
||||
'The field you are trying to delete a select option from does not have any select options.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!field.options[input.optionId]) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionNotFound,
|
||||
'The select option you are trying to delete does not exist.'
|
||||
);
|
||||
}
|
||||
|
||||
delete field.options[input.optionId];
|
||||
|
||||
return attributes;
|
||||
}
|
||||
);
|
||||
|
||||
if (result === 'unauthorized') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionDeleteForbidden,
|
||||
"You don't have permission to delete this select option."
|
||||
);
|
||||
}
|
||||
|
||||
if (result !== 'success') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionDeleteFailed,
|
||||
'Something went wrong while deleting the select option.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
id: input.optionId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,73 +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 {
|
||||
SelectOptionUpdateMutationInput,
|
||||
SelectOptionUpdateMutationOutput,
|
||||
} from '@colanode/client/mutations/databases/select-option-update';
|
||||
import { DatabaseAttributes } from '@colanode/core';
|
||||
|
||||
export class SelectOptionUpdateMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<SelectOptionUpdateMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: SelectOptionUpdateMutationInput
|
||||
): Promise<SelectOptionUpdateMutationOutput> {
|
||||
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 a select option in does not exist.'
|
||||
);
|
||||
}
|
||||
|
||||
if (field.type !== 'multi_select' && field.type !== 'select') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.FieldTypeInvalid,
|
||||
'The field you are trying to update a select option in is not a "Select" or "Multi-Select" field.'
|
||||
);
|
||||
}
|
||||
|
||||
if (!field.options) {
|
||||
field.options = {};
|
||||
}
|
||||
|
||||
const option = field.options[input.optionId];
|
||||
if (!option) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionNotFound,
|
||||
'The select option you are trying to update does not exist.'
|
||||
);
|
||||
}
|
||||
|
||||
option.name = input.name;
|
||||
option.color = input.color;
|
||||
return attributes;
|
||||
}
|
||||
);
|
||||
|
||||
if (result === 'unauthorized') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionUpdateForbidden,
|
||||
"You don't have permission to update this select option."
|
||||
);
|
||||
}
|
||||
|
||||
if (result !== 'success') {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.SelectOptionUpdateFailed,
|
||||
'Something went wrong while updating the select option.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
id: input.optionId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -17,9 +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 { SelectOptionCreateMutationHandler } from './databases/select-option-create';
|
||||
import { SelectOptionDeleteMutationHandler } from './databases/select-option-delete';
|
||||
import { SelectOptionUpdateMutationHandler } from './databases/select-option-update';
|
||||
import { ViewUpdateMutationHandler } from './databases/view-update';
|
||||
import { DocumentUpdateMutationHandler } from './documents/document-update';
|
||||
import { FileCreateMutationHandler } from './files/file-create';
|
||||
@@ -71,9 +68,6 @@ export const buildMutationHandlerMap = (
|
||||
'node.interaction.seen': new NodeInteractionSeenMutationHandler(app),
|
||||
'node.reaction.create': new NodeReactionCreateMutationHandler(app),
|
||||
'node.reaction.delete': new NodeReactionDeleteMutationHandler(app),
|
||||
'select.option.create': new SelectOptionCreateMutationHandler(app),
|
||||
'select.option.delete': new SelectOptionDeleteMutationHandler(app),
|
||||
'select.option.update': new SelectOptionUpdateMutationHandler(app),
|
||||
'server.create': new ServerCreateMutationHandler(app),
|
||||
'server.delete': new ServerDeleteMutationHandler(app),
|
||||
'server.sync': new ServerSyncMutationHandler(app),
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
export type SelectOptionCreateMutationInput = {
|
||||
type: 'select.option.create';
|
||||
userId: string;
|
||||
databaseId: string;
|
||||
fieldId: string;
|
||||
name: string;
|
||||
color: string;
|
||||
};
|
||||
|
||||
export type SelectOptionCreateMutationOutput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
declare module '@colanode/client/mutations' {
|
||||
interface MutationMap {
|
||||
'select.option.create': {
|
||||
input: SelectOptionCreateMutationInput;
|
||||
output: SelectOptionCreateMutationOutput;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
export type SelectOptionDeleteMutationInput = {
|
||||
type: 'select.option.delete';
|
||||
userId: string;
|
||||
databaseId: string;
|
||||
fieldId: string;
|
||||
optionId: string;
|
||||
};
|
||||
|
||||
export type SelectOptionDeleteMutationOutput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
declare module '@colanode/client/mutations' {
|
||||
interface MutationMap {
|
||||
'select.option.delete': {
|
||||
input: SelectOptionDeleteMutationInput;
|
||||
output: SelectOptionDeleteMutationOutput;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
export type SelectOptionUpdateMutationInput = {
|
||||
type: 'select.option.update';
|
||||
userId: string;
|
||||
databaseId: string;
|
||||
fieldId: string;
|
||||
optionId: string;
|
||||
name: string;
|
||||
color: string;
|
||||
};
|
||||
|
||||
export type SelectOptionUpdateMutationOutput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
declare module '@colanode/client/mutations' {
|
||||
interface MutationMap {
|
||||
'select.option.update': {
|
||||
input: SelectOptionUpdateMutationInput;
|
||||
output: SelectOptionUpdateMutationOutput;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,6 @@ export * from './apps/metadata-delete';
|
||||
export * from './apps/metadata-update';
|
||||
export * from './avatars/avatar-upload';
|
||||
export * from './chats/chat-create';
|
||||
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 './documents/document-update';
|
||||
export * from './files/file-create';
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { LocalDatabaseNode } from '@colanode/client/types';
|
||||
import { NodeRole, hasNodeRole } from '@colanode/core';
|
||||
import { DatabaseContext } from '@colanode/ui/contexts/database';
|
||||
import { useWorkspace } from '@colanode/ui/contexts/workspace';
|
||||
|
||||
interface DatabaseProps {
|
||||
database: LocalDatabaseNode;
|
||||
@@ -13,7 +11,6 @@ interface DatabaseProps {
|
||||
}
|
||||
|
||||
export const Database = ({ database, role, children }: DatabaseProps) => {
|
||||
const workspace = useWorkspace();
|
||||
const canEdit = hasNodeRole(role, 'editor');
|
||||
const canCreateRecord = hasNodeRole(role, 'editor');
|
||||
|
||||
@@ -28,54 +25,6 @@ export const Database = ({ database, role, children }: DatabaseProps) => {
|
||||
canEdit,
|
||||
canCreateRecord,
|
||||
rootId: database.rootId,
|
||||
createSelectOption: async (fieldId, name, color) => {
|
||||
if (!canEdit) return;
|
||||
|
||||
const result = await window.colanode.executeMutation({
|
||||
type: 'select.option.create',
|
||||
databaseId: database.id,
|
||||
fieldId,
|
||||
name,
|
||||
color,
|
||||
userId: workspace.userId,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(result.error.message);
|
||||
}
|
||||
},
|
||||
updateSelectOption: async (fieldId, attributes) => {
|
||||
if (!canEdit) return;
|
||||
|
||||
const result = await window.colanode.executeMutation({
|
||||
type: 'select.option.update',
|
||||
databaseId: database.id,
|
||||
fieldId,
|
||||
optionId: attributes.id,
|
||||
name: attributes.name,
|
||||
color: attributes.color,
|
||||
userId: workspace.userId,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(result.error.message);
|
||||
}
|
||||
},
|
||||
deleteSelectOption: async (fieldId, optionId) => {
|
||||
if (!canEdit) return;
|
||||
|
||||
const result = await window.colanode.executeMutation({
|
||||
type: 'select.option.delete',
|
||||
databaseId: database.id,
|
||||
fieldId,
|
||||
optionId,
|
||||
userId: workspace.userId,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toast.error(result.error.message);
|
||||
}
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { Check, Plus, X } from 'lucide-react';
|
||||
import { Fragment, useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import {
|
||||
compareString,
|
||||
generateFractionalIndex,
|
||||
generateId,
|
||||
IdType,
|
||||
MultiSelectFieldAttributes,
|
||||
SelectFieldAttributes,
|
||||
} from '@colanode/core';
|
||||
import { collections } from '@colanode/ui/collections';
|
||||
import { SelectOptionBadge } from '@colanode/ui/components/databases/fields/select-option-badge';
|
||||
import { SelectOptionSettingsPopover } from '@colanode/ui/components/databases/fields/select-option-settings-popover';
|
||||
import {
|
||||
@@ -18,7 +22,6 @@ import {
|
||||
} from '@colanode/ui/components/ui/command';
|
||||
import { useDatabase } from '@colanode/ui/contexts/database';
|
||||
import { useWorkspace } from '@colanode/ui/contexts/workspace';
|
||||
import { useMutation } from '@colanode/ui/hooks/use-mutation';
|
||||
import { getRandomSelectOptionColor } from '@colanode/ui/lib/databases';
|
||||
|
||||
interface SelectFieldOptionsProps {
|
||||
@@ -36,7 +39,6 @@ export const SelectFieldOptions = ({
|
||||
}: SelectFieldOptionsProps) => {
|
||||
const workspace = useWorkspace();
|
||||
const database = useDatabase();
|
||||
const { mutate, isPending } = useMutation();
|
||||
|
||||
const selectOptions = Object.values(field.options ?? {});
|
||||
|
||||
@@ -104,32 +106,54 @@ export const SelectFieldOptions = ({
|
||||
key={inputValue.trim()}
|
||||
value={inputValue.trim()}
|
||||
onSelect={() => {
|
||||
if (isPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputValue.trim().length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mutate({
|
||||
input: {
|
||||
type: 'select.option.create',
|
||||
databaseId: database.id,
|
||||
fieldId: field.id,
|
||||
const id = generateId(IdType.SelectOption);
|
||||
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;
|
||||
}
|
||||
|
||||
if (
|
||||
fieldAttributes.type !== 'select' &&
|
||||
fieldAttributes.type !== 'multi_select'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectOptions = {
|
||||
...(fieldAttributes.options ?? {}),
|
||||
};
|
||||
|
||||
const maxIndex = Object.values(selectOptions)
|
||||
.map((selectOption) => selectOption.index)
|
||||
.sort((a, b) => -compareString(a, b))[0];
|
||||
|
||||
const index = generateFractionalIndex(maxIndex, null);
|
||||
selectOptions[id] = {
|
||||
id,
|
||||
index,
|
||||
name: inputValue.trim(),
|
||||
color,
|
||||
userId: workspace.userId,
|
||||
},
|
||||
onSuccess(output) {
|
||||
setInputValue('');
|
||||
setColor(getRandomSelectOptionColor());
|
||||
onSelect(output.id);
|
||||
},
|
||||
onError(error) {
|
||||
toast.error(error.message);
|
||||
},
|
||||
};
|
||||
|
||||
draft.fields[field.id] = {
|
||||
...fieldAttributes,
|
||||
options: selectOptions,
|
||||
};
|
||||
});
|
||||
|
||||
onSelect(id);
|
||||
setInputValue('');
|
||||
setColor(getRandomSelectOptionColor());
|
||||
}}
|
||||
className="flex flex-row items-center gap-2"
|
||||
>
|
||||
|
||||
@@ -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 SelectOptionDeleteDialogProps {
|
||||
fieldId: string;
|
||||
@@ -23,6 +25,7 @@ export const SelectOptionDeleteDialog = ({
|
||||
open,
|
||||
onOpenChange,
|
||||
}: SelectOptionDeleteDialogProps) => {
|
||||
const workspace = useWorkspace();
|
||||
const database = useDatabase();
|
||||
|
||||
return (
|
||||
@@ -42,7 +45,36 @@ export const SelectOptionDeleteDialog = ({
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={() => {
|
||||
database.deleteSelectOption(fieldId, optionId);
|
||||
const nodes = collections.workspace(workspace.userId).nodes;
|
||||
nodes.update(database.id, (draft) => {
|
||||
if (draft.type !== 'database') {
|
||||
return;
|
||||
}
|
||||
|
||||
const fieldAttributes = draft.fields[fieldId];
|
||||
if (!fieldAttributes) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
fieldAttributes.type !== 'select' &&
|
||||
fieldAttributes.type !== 'multi_select'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectOptions = {
|
||||
...(fieldAttributes.options ?? {}),
|
||||
};
|
||||
|
||||
const { [optionId]: _removed, ...rest } = selectOptions;
|
||||
draft.fields[fieldId] = {
|
||||
...fieldAttributes,
|
||||
options: rest,
|
||||
};
|
||||
});
|
||||
|
||||
onOpenChange(false);
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Ellipsis, Trash2 } from 'lucide-react';
|
||||
import { Fragment, useState } from 'react';
|
||||
|
||||
import { SelectOptionAttributes } from '@colanode/core';
|
||||
import { collections } from '@colanode/ui/collections';
|
||||
import { SelectOptionDeleteDialog } from '@colanode/ui/components/databases/fields/select-option-delete-dialog';
|
||||
import { Label } from '@colanode/ui/components/ui/label';
|
||||
import {
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
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 { useWorkspace } from '@colanode/ui/contexts/workspace';
|
||||
import { selectOptionColors } from '@colanode/ui/lib/databases';
|
||||
import { cn } from '@colanode/ui/lib/utils';
|
||||
|
||||
@@ -24,6 +26,7 @@ export const SelectOptionSettingsPopover = ({
|
||||
fieldId,
|
||||
option,
|
||||
}: SelectOptionSettingsPopoverProps) => {
|
||||
const workspace = useWorkspace();
|
||||
const database = useDatabase();
|
||||
|
||||
const [openSetttingsPopover, setOpenSetttingsPopover] = useState(false);
|
||||
@@ -46,9 +49,34 @@ export const SelectOptionSettingsPopover = ({
|
||||
onChange={(newName) => {
|
||||
if (newName === option.name) return;
|
||||
|
||||
database.updateSelectOption(fieldId, {
|
||||
...option,
|
||||
name: newName,
|
||||
const nodes = collections.workspace(workspace.userId).nodes;
|
||||
nodes.update(database.id, (draft) => {
|
||||
if (draft.type !== 'database') {
|
||||
return;
|
||||
}
|
||||
|
||||
const fieldAttributes = draft.fields[fieldId];
|
||||
if (!fieldAttributes) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
fieldAttributes.type !== 'select' &&
|
||||
fieldAttributes.type !== 'multi_select'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fieldAttributes.options) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectOption = fieldAttributes.options[option.id];
|
||||
if (!selectOption) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectOption.name = newName;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@@ -61,9 +89,34 @@ export const SelectOptionSettingsPopover = ({
|
||||
key={color.value}
|
||||
className="flex cursor-pointer flex-row items-center gap-2 rounded-md p-1 hover:bg-accent"
|
||||
onClick={() => {
|
||||
database.updateSelectOption(fieldId, {
|
||||
...option,
|
||||
color: color.value,
|
||||
const nodes = collections.workspace(workspace.userId).nodes;
|
||||
nodes.update(database.id, (draft) => {
|
||||
if (draft.type !== 'database') {
|
||||
return;
|
||||
}
|
||||
|
||||
const fieldAttributes = draft.fields[fieldId];
|
||||
if (!fieldAttributes) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
fieldAttributes.type !== 'select' &&
|
||||
fieldAttributes.type !== 'multi_select'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fieldAttributes.options) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectOption = fieldAttributes.options[option.id];
|
||||
if (!selectOption) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectOption.color = color.value;
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
DatabaseNameFieldAttributes,
|
||||
FieldAttributes,
|
||||
NodeRole,
|
||||
SelectOptionAttributes,
|
||||
} from '@colanode/core';
|
||||
|
||||
interface DatabaseContext {
|
||||
@@ -16,12 +15,6 @@ interface DatabaseContext {
|
||||
canCreateRecord: boolean;
|
||||
role: NodeRole;
|
||||
rootId: string;
|
||||
createSelectOption: (fieldId: string, name: string, color: string) => void;
|
||||
updateSelectOption: (
|
||||
fieldId: string,
|
||||
attributes: SelectOptionAttributes
|
||||
) => void;
|
||||
deleteSelectOption: (fieldId: string, optionId: string) => void;
|
||||
}
|
||||
|
||||
export const DatabaseContext = createContext<DatabaseContext>(
|
||||
|
||||
Reference in New Issue
Block a user