Skip to content

Commit

Permalink
feat: support rearrange column
Browse files Browse the repository at this point in the history
  • Loading branch information
invisal committed Sep 30, 2024
1 parent 8dcd50b commit da28c7a
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 13 deletions.
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-sql": "^6.5.5",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0",
"@justmiracle/result": "^1.2.0",
"@lezer/common": "^1.2.1",
Expand Down
1 change: 1 addition & 0 deletions src/components/gui/schema-editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default function SchemaEditor({
columns: [
...value.columns,
{
key: window.crypto.randomUUID(),
old: null,
new: newColumn,
},
Expand Down
96 changes: 83 additions & 13 deletions src/components/gui/schema-editor/schema-editor-column-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SelectTrigger,
SelectValue,
} from "../../ui/select";
import { CSS } from "@dnd-kit/utilities";
import { convertSqliteType } from "@/drivers/sqlite/sql-helper";
import { Checkbox } from "@/components/ui/checkbox";
import ColumnDefaultValueInput from "./column-default-value-input";
Expand All @@ -33,6 +34,14 @@ import ColumnForeignKeyPopup from "./column-fk-popup";
import ColumnGeneratingPopup from "./column-generate-popup";
import ColumnCheckPopup from "./column-check-popup";
import { Button } from "@/components/ui/button";
import { DndContext, DragEndEvent } from "@dnd-kit/core";
import {
SortableContext,
arrayMove,
useSortable,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";

export type ColumnChangeEvent = (
newValue: Partial<DatabaseTableColumn> | null
Expand Down Expand Up @@ -92,8 +101,21 @@ function ColumnItem({
schemaName?: string;
onChange: Dispatch<SetStateAction<DatabaseTableSchemaChange>>;
}) {
const {
setNodeRef,
attributes,
listeners,
transform,
transition,
setActivatorNodeRef,
} = useSortable({ id: value.key, disabled: !!value.old });
const disabled = !!value.old;

const style = {
transform: CSS.Transform.toString(transform),
transition,
};

const change = useCallback(
(newValue: Partial<DatabaseTableColumn> | null) => {
changeColumnOnIndex(idx, newValue, onChange);
Expand Down Expand Up @@ -121,13 +143,30 @@ function ColumnItem({
}

return (
<tr>
<td className={cn("border-l border-t border-b", highlightClassName)}></td>
<tr
style={style}
{...attributes}
ref={setNodeRef}
className={
value.new === null
? "bg-red-100 dark:bg-red-400 dark:text-black"
: "bg-background"
}
>
<td
ref={setActivatorNodeRef}
{...listeners}
className={cn("border-l border-t border-b")}
>
<div
className={cn("w-[12px] h-[30px] ml-1 rounded", highlightClassName)}
></div>
</td>
<td className="border-r border-t border-b">
<input
value={column.name}
onChange={(e) => change({ name: e.currentTarget.value })}
className="p-2 text-sm outline-none bg-background w-[150px]"
className="p-2 text-sm outline-none w-[150px] bg-inherit"
spellCheck={false}
/>
</td>
Expand All @@ -137,7 +176,7 @@ function ColumnItem({
onValueChange={(newType) => change({ type: newType })}
disabled={disabled}
>
<SelectTrigger className="bg-background border-0 rounded-none shadow-none text-sm">
<SelectTrigger className="bg-inherit border-0 rounded-none shadow-none text-sm">
<SelectValue placeholder="Select datatype" />
</SelectTrigger>
<SelectContent>
Expand Down Expand Up @@ -307,6 +346,27 @@ export default function SchemaEditorColumnList({
}>) {
const headerStyle = "text-xs p-2 text-left bg-secondary border";

const handleDragEnd = useCallback(
(event: DragEndEvent) => {
const { active, over } = event;
if (active.id !== over?.id) {
const oldIndex = columns.findIndex((c) => c.key === active.id);
const newIndex = columns.findIndex((c) => c.key === over?.id);

// You cannot change the order of existing column
if (!!columns[newIndex].old) return;

const newColumns = arrayMove(columns, oldIndex, newIndex);

onChange((prev) => ({
...prev,
columns: newColumns,
}));
}
},
[columns, onChange]
);

return (
<div className="p-4">
<table className="w-full rounded overflow-hidden">
Expand All @@ -322,15 +382,25 @@ export default function SchemaEditorColumnList({
</tr>
</thead>
<tbody>
{columns.map((col, idx) => (
<ColumnItem
idx={idx}
value={col}
key={idx}
onChange={onChange}
schemaName={schemaName}
/>
))}
<DndContext
onDragEnd={handleDragEnd}
modifiers={[restrictToVerticalAxis]}
>
<SortableContext
items={columns.map((c) => c.key)}
strategy={verticalListSortingStrategy}
>
{columns.map((col, idx) => (
<ColumnItem
idx={idx}
value={col}
key={col.key}
onChange={onChange}
schemaName={schemaName}
/>
))}
</SortableContext>
</DndContext>
</tbody>
<tfoot>
<tr>
Expand Down
2 changes: 2 additions & 0 deletions src/components/gui/tabs/schema-editor-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default function SchemaEditorTab({
new: schema.tableName,
},
columns: schema.columns.map((col) => ({
key: window.crypto.randomUUID(),
old: col,
new: structuredClone(col),
})),
Expand Down Expand Up @@ -82,6 +83,7 @@ export default function SchemaEditorTab({
name: { ...prev.name, new: prev.name.old },
columns: prev.columns
.map((col) => ({
key: col.key,
old: col.old,
new: structuredClone(col.old),
}))
Expand Down
1 change: 1 addition & 0 deletions src/drivers/base-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export interface DriverFlags {
}

export interface DatabaseTableColumnChange {
key: string;
old: DatabaseTableColumn | null;
new: DatabaseTableColumn | null;
}
Expand Down

0 comments on commit da28c7a

Please sign in to comment.