Improve table views

This commit is contained in:
Hakan Shehu
2024-11-20 12:24:37 +01:00
parent e596d6494a
commit 1049c69046
7 changed files with 94 additions and 34 deletions

View File

@@ -14,23 +14,19 @@ import {
TooltipTrigger,
} from '@/renderer/components/ui/tooltip';
import { FieldDeleteDialog } from '@/renderer/components/databases/fields/field-delete-dialog';
import { useMutation } from '@/renderer/hooks/use-mutation';
import { ViewDeleteDialog } from '@/renderer/components/databases/view-delete-dialog';
import { SmartTextInput } from '@/renderer/components/ui/smart-text-input';
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';
import { Eye, EyeOff, Settings, Trash2 } from 'lucide-react';
import { FieldIcon } from '@/renderer/components/databases/fields/field-icon';
import { ViewIcon } from '../view-icon';
export const TableViewSettingsPopover = () => {
const workspace = useWorkspace();
const database = useDatabase();
const view = useView();
const { mutate, isPending } = useMutation();
const [open, setOpen] = React.useState(false);
const [openDelete, setOpenDelete] = React.useState(false);
const [deleteFieldId, setDeleteFieldId] = React.useState<string | null>(null);
@@ -48,36 +44,27 @@ export const TableViewSettingsPopover = () => {
{database.canEdit ? (
<AvatarPopover
onPick={(avatar) => {
if (isPending) return;
if (avatar === view.avatar) return;
mutate({
input: {
type: 'node_attribute_set',
nodeId: view.id,
path: 'avatar',
value: avatar,
userId: workspace.userId,
},
});
view.updateAvatar(avatar);
}}
>
<Button type="button" variant="outline" size="icon">
<Avatar
<ViewIcon
id={view.id}
name={view.name}
avatar={view.avatar}
className="h-6 w-6"
type={view.type}
className="size-4"
/>
</Button>
</AvatarPopover>
) : (
<Button type="button" variant="outline" size="icon">
<Avatar
<ViewIcon
id={view.id}
name={view.name}
avatar={view.avatar}
className="h-6 w-6"
type={view.type}
className="size-4"
/>
</Button>
)}
@@ -85,18 +72,9 @@ export const TableViewSettingsPopover = () => {
value={view.name}
readOnly={!database.canEdit}
onChange={(newName) => {
if (isPending) return;
if (newName === view.name) return;
mutate({
input: {
type: 'node_attribute_set',
nodeId: view.id,
path: 'name',
value: newName,
userId: workspace.userId,
},
});
view.rename(newName);
}}
/>
</div>

View File

@@ -0,0 +1,36 @@
import { Avatar } from '@/renderer/components/avatars/avatar';
import { Calendar, Database, SquareKanban, Table } from 'lucide-react';
interface ViewIconProps {
id: string;
name: string;
avatar: string | null;
type: 'table' | 'board' | 'calendar';
className?: string;
}
export const ViewIcon = ({
id,
name,
avatar,
type,
className,
}: ViewIconProps) => {
if (avatar) {
return <Avatar id={id} name={name} avatar={avatar} className={className} />;
}
if (type === 'table') {
return <Table className={className} />;
}
if (type === 'calendar') {
return <Calendar className={className} />;
}
if (type === 'board') {
return <SquareKanban className={className} />;
}
return <Database className={className} />;
};

View File

@@ -1,6 +1,6 @@
import { cn } from '@/shared/lib/utils';
import { Avatar } from '@/renderer/components/avatars/avatar';
import { ViewAttributes } from '@colanode/core';
import { ViewIcon } from '@/renderer/components/databases/view-icon';
interface ViewTabProps {
view: ViewAttributes;
@@ -19,7 +19,13 @@ export const ViewTab = ({ view, isActive, onClick }: ViewTabProps) => {
onClick={() => onClick()}
onKeyDown={() => onClick()}
>
<Avatar id={view.id} name={view.name} avatar={view.avatar} size="small" />
<ViewIcon
id={view.id}
name={view.name}
avatar={view.avatar}
type={view.type}
className="size-4"
/>
{view.name}
</div>
);

View File

@@ -61,6 +61,7 @@ export const View = ({ view }: ViewProps) => {
id: view.id,
name: view.name,
avatar: view.avatar,
type: view.type,
fields,
filters: Object.values(view.filters),
sorts: Object.values(view.sorts),
@@ -68,6 +69,40 @@ export const View = ({ view }: ViewProps) => {
nameWidth: view.nameWidth ?? getDefaultNameWidth(),
isSearchBarOpened,
isSortsOpened,
rename: (name: string) => {
if (!database.canEdit) {
return;
}
const viewCopy = { ...view };
viewCopy.name = name;
mutate({
input: {
type: 'view_update',
userId: workspace.userId,
databaseId: database.id,
view: viewCopy,
},
});
},
updateAvatar: (avatar: string) => {
if (!database.canEdit) {
return;
}
const viewCopy = { ...view };
viewCopy.avatar = avatar;
mutate({
input: {
type: 'view_update',
userId: workspace.userId,
databaseId: database.id,
view: viewCopy,
},
});
},
setFieldDisplay: (id: string, display: boolean) => {
if (!database.canEdit) {
return;

View File

@@ -34,7 +34,7 @@ interface RecordContext {
getCollaboratorValue: (field: CollaboratorFieldAttributes) => string[] | null;
getDateValue: (field: DateFieldAttributes) => Date | null;
getEmailValue: (field: EmailFieldAttributes) => string | null;
getFileValue: (field: FileFieldAttributes) => string | null;
getFileValue: (field: FileFieldAttributes) => string[] | null;
getMultiSelectValue: (field: MultiSelectFieldAttributes) => string[];
getNumberValue: (field: NumberFieldAttributes) => number | null;
getPhoneValue: (field: PhoneFieldAttributes) => string | null;

View File

@@ -2,6 +2,7 @@ import {
SortDirection,
ViewFilterAttributes,
ViewSortAttributes,
ViewType,
} from '@colanode/core';
import { ViewField } from '@/shared/types/databases';
import { createContext, useContext } from 'react';
@@ -10,6 +11,7 @@ interface ViewContext {
id: string;
name: string;
avatar: string | null;
type: ViewType;
fields: ViewField[];
filters: ViewFilterAttributes[];
sorts: ViewSortAttributes[];
@@ -17,6 +19,8 @@ interface ViewContext {
nameWidth: number;
isSearchBarOpened: boolean;
isSortsOpened: boolean;
rename: (name: string) => void;
updateAvatar: (avatar: string) => void;
setFieldDisplay: (id: string, display: boolean) => void;
resizeField: (id: string, width: number) => void;
resizeName: (width: number) => void;

View File

@@ -78,6 +78,7 @@ export const databaseAttributesSchema = z.object({
});
export type DatabaseAttributes = z.infer<typeof databaseAttributesSchema>;
export type ViewType = 'table' | 'board' | 'calendar';
export const databaseModel: NodeModel = {
type: 'database',