v0.6.0: release workflow, constraint-aware cell editing, pending-cell styling (#9)

* feat: demo DB seed/regenerate, backup/restore/sync refinements, SSH/SSL polish

- Demo SQLite DB: feature-rich seed (12 objects, 500-row audit log) + regenerate action in Settings
- Backup/restore: headless-testable core logic, psql -f for plain dumps, sync passes --clean --if-exists
- SSH/SSL runtime refinements and connection testing improvements
- Data grid: DataTypeIcon component, FK popover, table tree polish
- Docs: AGENTS.md/README updates, new screenshots, MIT LICENSE

* chore: optimize README screenshots (4.7 MB → 916 KB via pngquant, quality 70-90)

* v0.6.0: release workflow, constraint-aware cell editing, pending-cell styling

- Bump version to 0.6.0 across package.json, Cargo.toml, tauri.conf.json
- Add .github/workflows/release.yml: tag-triggered CI builds macOS (aarch64
  + x64), Windows, and Linux installers into a draft GitHub Release
- README: installer download table (unsigned note, per-platform files),
  "how releases are made" section
- CellEditor: constraint-aware commit — empty input on nullable columns
  becomes NULL, NOT NULL text-like types fall back to empty string, all
  other types blocked with an inline error bubble; replace "Set NULL"
  checkbox with a NULL row in the FK dropdown / empty enum option
- VirtualDataGrid: pending-edit dot → animated pending outline (ring) on
  staged cells; matching test updates
- docs-coverage test: align with rewritten README comparison table
This commit is contained in:
2026-08-04 17:20:14 +08:00
committed by GitHub
parent a9dbf60ed5
commit 002d8345ae
66 changed files with 3591 additions and 1602 deletions
+13 -11
View File
@@ -3,8 +3,8 @@ import { createPortal } from "react-dom";
import { Key, X, ExternalLink, Loader2 } from "lucide-react";
import * as cmd from "../../lib/commands";
import type { QueryResult } from "../../lib/types";
import { abbreviateType } from "../../lib/utils";
import { useDbViewerStore } from "../../stores/dbViewerStore";
import { DataTypeIcon } from "../ui/DataTypeIcon";
interface FkPreviewPopoverProps {
connectionId: string;
@@ -168,7 +168,7 @@ export function FkPreviewPopover({
</div>
)}
{data && data.rows.length > 0 && (
<table className="w-full text-xs">
<table className="w-full text-xs" style={{ tableLayout: "fixed" }}>
<tbody>
{data.columns.map((col, ci) => {
const cell = data.rows[0][ci];
@@ -178,20 +178,22 @@ export function FkPreviewPopover({
key={col.name}
className="border-b border-border last:border-0 hover:bg-surface/30"
>
<td className="px-3 py-1.5 text-text-muted font-heading whitespace-nowrap w-1/3">
<div className="flex items-center gap-1">
<td
className="px-3 py-1.5 text-text-muted font-heading whitespace-nowrap overflow-hidden align-top"
style={{ width: 100, maxWidth: 100 }}
>
<div className="flex items-center gap-1 min-w-0">
{col.is_pk && <Key size={9} className="text-accent shrink-0" />}
{col.is_fk && <Key size={9} className="text-amber-400 shrink-0" />}
<span className="truncate">{col.name}</span>
<span
className="text-[10px] text-text-muted/50 shrink-0"
title={col.data_type}
>
{abbreviateType(col.data_type)}
</span>
<DataTypeIcon
dataType={col.data_type}
size={9}
className="text-text-muted/60 shrink-0"
/>
</div>
</td>
<td className="px-3 py-1.5 text-text">
<td className="px-3 py-1.5 text-text align-top break-all">
{isNull ? (
<span className="italic text-text-muted">NULL</span>
) : (