mirror of
https://github.com/colanode/colanode.git
synced 2025-12-29 00:25:03 +01:00
Improve record settings
This commit is contained in:
@@ -2,13 +2,17 @@ import { RecordName } from '@/renderer/components/records/record-name';
|
||||
import { useDatabase } from '@/renderer/contexts/database';
|
||||
import { RecordField } from '@/renderer/components/records/record-field';
|
||||
import { RecordFieldValue } from '@/renderer/components/records/record-field-value';
|
||||
import { RecordAvatar } from '@/renderer/components/records/record-avatar';
|
||||
|
||||
export const RecordAttributes = () => {
|
||||
const database = useDatabase();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<RecordName />
|
||||
<div className="flex flex-row gap-2">
|
||||
<RecordAvatar />
|
||||
<RecordName />
|
||||
</div>
|
||||
<div className="flex flex-row gap-2">
|
||||
<div className="flex w-60 flex-col gap-2">
|
||||
{database.fields.map((field) => (
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { useRecord } from '@/renderer/contexts/record';
|
||||
import { useMutation } from '@/renderer/hooks/use-mutation';
|
||||
import { useWorkspace } from '@/renderer/contexts/workspace';
|
||||
import { AvatarPopover } from '@/renderer/components/avatars/avatar-popover';
|
||||
import { Button } from '@/renderer/components/ui/button';
|
||||
import { Avatar } from '@/renderer/components/avatars/avatar';
|
||||
|
||||
export const RecordAvatar = () => {
|
||||
const workspace = useWorkspace();
|
||||
const record = useRecord();
|
||||
|
||||
const { mutate, isPending } = useMutation();
|
||||
|
||||
if (!record.canEdit) {
|
||||
return (
|
||||
<Button type="button" variant="outline" size="icon">
|
||||
<Avatar
|
||||
id={record.id}
|
||||
name={record.name}
|
||||
avatar={record.avatar}
|
||||
className="h-6 w-6"
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AvatarPopover
|
||||
onPick={(avatar) => {
|
||||
if (isPending) return;
|
||||
if (avatar === record.avatar) return;
|
||||
|
||||
mutate({
|
||||
input: {
|
||||
type: 'node_attribute_set',
|
||||
nodeId: record.id,
|
||||
path: 'avatar',
|
||||
value: avatar,
|
||||
userId: workspace.userId,
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Button type="button" variant="outline" size="icon">
|
||||
<Avatar
|
||||
id={record.id}
|
||||
name={record.name}
|
||||
avatar={record.avatar}
|
||||
className="h-6 w-6"
|
||||
/>
|
||||
</Button>
|
||||
</AvatarPopover>
|
||||
);
|
||||
};
|
||||
@@ -30,7 +30,7 @@ export const RecordHeader = ({ nodes, record, role }: RecordHeaderProps) => {
|
||||
nodes={nodes}
|
||||
role={role}
|
||||
/>
|
||||
<RecordSettings nodeId={record.id} />
|
||||
<RecordSettings record={record} role={role} />
|
||||
</div>
|
||||
</div>
|
||||
</Header>
|
||||
|
||||
@@ -11,6 +11,7 @@ export const RecordName = () => {
|
||||
return (
|
||||
<SmartTextInput
|
||||
value={record.name}
|
||||
readOnly={!record.canEdit}
|
||||
onChange={(value) => {
|
||||
if (isPending) {
|
||||
return;
|
||||
|
||||
@@ -3,24 +3,36 @@ import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/renderer/components/ui/dropdown-menu';
|
||||
import { Copy, Settings, Trash2 } from 'lucide-react';
|
||||
import { hasEditorAccess, NodeRole, RecordNode } from '@colanode/core';
|
||||
import { NodeCollaboratorAudit } from '@/renderer/components/collaborators/node-collaborator-audit';
|
||||
import { useWorkspace } from '@/renderer/contexts/workspace';
|
||||
import { RecordDeleteDialog } from '@/renderer/components/records/record-delete-dialog';
|
||||
|
||||
interface RecordSettingsProps {
|
||||
nodeId: string;
|
||||
record: RecordNode;
|
||||
role: NodeRole;
|
||||
}
|
||||
|
||||
export const RecordSettings = ({ nodeId }: RecordSettingsProps) => {
|
||||
const [showDeleteModal, setShowDeleteModal] = React.useState(false);
|
||||
export const RecordSettings = ({ record, role }: RecordSettingsProps) => {
|
||||
const workspace = useWorkspace();
|
||||
const [showDeleteDialog, setShowDeleteModal] = React.useState(false);
|
||||
const canDelete =
|
||||
record.createdBy === workspace.userId || hasEditorAccess(role);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Settings className="size-5 cursor-pointer text-muted-foreground hover:text-foreground" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="bottom" className="mr-2 w-56">
|
||||
<DropdownMenuContent side="bottom" className="mr-2 w-80">
|
||||
<DropdownMenuLabel>{record.attributes.name}</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem className="flex items-center gap-2" disabled>
|
||||
<Copy className="size-4" />
|
||||
Duplicate
|
||||
@@ -28,17 +40,42 @@ export const RecordSettings = ({ nodeId }: RecordSettingsProps) => {
|
||||
<DropdownMenuItem
|
||||
className="flex items-center gap-2"
|
||||
onClick={() => {
|
||||
if (!canDelete) {
|
||||
return;
|
||||
}
|
||||
|
||||
setShowDeleteModal(true);
|
||||
}}
|
||||
disabled={!canDelete}
|
||||
>
|
||||
<Trash2 className="size-4" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuLabel>Created by</DropdownMenuLabel>
|
||||
<DropdownMenuItem>
|
||||
<NodeCollaboratorAudit
|
||||
collaboratorId={record.createdBy}
|
||||
date={record.createdAt}
|
||||
/>
|
||||
</DropdownMenuItem>
|
||||
{record.updatedBy && (
|
||||
<React.Fragment>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuLabel>Last updated by</DropdownMenuLabel>
|
||||
<DropdownMenuItem>
|
||||
<NodeCollaboratorAudit
|
||||
collaboratorId={record.updatedBy}
|
||||
date={record.updatedAt}
|
||||
/>
|
||||
</DropdownMenuItem>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<RecordDeleteDialog
|
||||
nodeId={nodeId}
|
||||
open={showDeleteModal}
|
||||
nodeId={record.id}
|
||||
open={showDeleteDialog}
|
||||
onOpenChange={setShowDeleteModal}
|
||||
/>
|
||||
</React.Fragment>
|
||||
|
||||
Reference in New Issue
Block a user