Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/e2e/src/tests/sql-editor-sqlite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ describe.skipIf(!ready)('SQL Editor · SQLite multi-credential', () => {
expect(anyDiff).toBeGreaterThanOrEqual(modified);

const results = await sql.resultsText();
expect(results).toMatch(/baseline|source/i);
expect(results).toMatch(/differ|match/i);
expect(results).toMatch(/original|baseline|source/i);
expect(results).toMatch(/aligned by|edit|match/i);

// Data migrate bar: Add / Edit / Delete (user opts in; none checked by default).
await driver.waitForSelector('[data-testid="sql-data-migrate-bar-0"]', {
Expand Down
10 changes: 5 additions & 5 deletions apps/web/src/frontend/components/ObjectDetailPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ export const ObjectDetailPanel: React.FC = () => {
<thead>
<tr className="bg-slate-900 border-b border-slate-800 text-slate-300">
<th className="p-3 text-[11px] font-bold uppercase tracking-wider">Attribute</th>
<th className="p-3 text-[11px] font-bold uppercase tracking-wider">Source</th>
<th className="p-3 text-[11px] font-bold uppercase tracking-wider">Original Server</th>
<th className="p-3 text-[11px] font-bold uppercase tracking-wider text-center">Compare</th>
<th className="p-3 text-[11px] font-bold uppercase tracking-wider">Target</th>
</tr>
Expand Down Expand Up @@ -813,7 +813,7 @@ export const ObjectDetailPanel: React.FC = () => {
<thead>
<tr className="bg-slate-900 border-b border-slate-800 text-slate-300">
<th className="p-3 text-[11px] font-bold uppercase tracking-wider">Attribute</th>
<th className="p-3 text-[11px] font-bold uppercase tracking-wider">Source Type</th>
<th className="p-3 text-[11px] font-bold uppercase tracking-wider">Original Type</th>
<th className="p-3 text-[11px] font-bold uppercase tracking-wider text-center">Compare</th>
<th className="p-3 text-[11px] font-bold uppercase tracking-wider">Target Type</th>
</tr>
Expand Down Expand Up @@ -867,7 +867,7 @@ export const ObjectDetailPanel: React.FC = () => {
<thead>
<tr className="bg-slate-900 border-b border-slate-800 text-slate-400">
<th className="p-3 font-semibold">{selectedTable.objectType === 'ROLE' ? 'Member' : 'Column Name'}</th>
<th className="p-3 font-semibold">Source State</th>
<th className="p-3 font-semibold">Original State</th>
<th className="p-3 font-semibold text-center">Compare</th>
<th className="p-3 font-semibold">Target State</th>
<th className="p-3 font-semibold text-right">Operation</th>
Expand Down Expand Up @@ -972,7 +972,7 @@ export const ObjectDetailPanel: React.FC = () => {
<thead>
<tr className="bg-slate-900 border-b border-slate-800 text-slate-400">
<th className="p-3 font-semibold">Constraint Name</th>
<th className="p-3 font-semibold">Source Columns</th>
<th className="p-3 font-semibold">Original Columns</th>
<th className="p-3 font-semibold text-center">Compare</th>
<th className="p-3 font-semibold">Target Columns</th>
<th className="p-3 font-semibold text-right">Operation</th>
Expand Down Expand Up @@ -1150,7 +1150,7 @@ export const ObjectDetailPanel: React.FC = () => {
<thead>
<tr className="bg-slate-900 border-b border-slate-800 text-slate-400">
<th className="p-3 font-semibold">Trigger Name</th>
<th className="p-3 font-semibold">Source State</th>
<th className="p-3 font-semibold">Original State</th>
<th className="p-3 font-semibold text-center">Compare</th>
<th className="p-3 font-semibold">Target State</th>
<th className="p-3 font-semibold text-right">Operation</th>
Expand Down
24 changes: 17 additions & 7 deletions apps/web/src/frontend/components/TopToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,11 @@ export const TopToolbar: React.FC = () => {
<>
{/* Database Connection Control Grid */}
<div className="grid grid-cols-1 xl:grid-cols-11 gap-3 items-stretch">
{/* Source Configuration */}
{/* Source Configuration — left side is the Original Server (read / compare from). */}
<div className="xl:col-span-5 bg-slate-950/60 p-3 rounded-lg border border-slate-800/80 flex flex-col gap-2">
<div className="text-[10px] font-bold uppercase tracking-wider text-cyan-500/80">
Original Server
</div>
{/* Label + Add/Edit Connection + status, all inline */}
<div className="flex items-center gap-2">
{connections.length > 0 && (
Expand Down Expand Up @@ -269,22 +272,29 @@ export const TopToolbar: React.FC = () => {
</div>
</div>

{/* Direction / Swap control — migration always flows Source → Target */}
{/* Direction / Swap control — migration always flows Original Server → Target */}
<div className="flex xl:col-span-1 justify-center items-center">
<button
onClick={swapSourceTarget}
title="Swap Source and Target (reverse migration direction)"
title="Swap Original Server and Target (reverse migration direction)"
className="group flex flex-col items-center gap-0.5 transition cursor-pointer"
>
<span className="text-sm font-bold uppercase tracking-wider text-cyan-500/70 group-hover:text-cyan-400"/>
<span className="text-[9px] font-bold uppercase tracking-wider text-cyan-500/70 group-hover:text-cyan-400">
Original
</span>
<ArrowRight className="w-6 h-6 text-indigo-500/80 group-hover:hidden transition" />
<ArrowLeftRight className="w-6 h-6 text-cyan-400 hidden group-hover:block" />
<span className="text-sm font-bold uppercase tracking-wider text-purple-400/70 group-hover:text-cyan-400"/>
<span className="text-[9px] font-bold uppercase tracking-wider text-purple-400/70 group-hover:text-cyan-400">
Target
</span>
</button>
</div>

{/* Target Configuration */}
<div className="xl:col-span-5 bg-slate-950/60 p-3 rounded-lg border border-slate-800/80 flex flex-col gap-2">
<div className="text-[10px] font-bold uppercase tracking-wider text-purple-400/80">
Target
</div>
{/* Label + Add/Edit Connection + status, all inline */}
<div className="flex items-center gap-2">
{connections.length > 0 && (
Expand Down Expand Up @@ -445,7 +455,7 @@ export const TopToolbar: React.FC = () => {
<div className="flex items-center gap-3">
{sameConfig && (
<span className="flex items-center gap-1.5 text-sm font-medium text-amber-400 bg-amber-950/30 border border-amber-500/20 px-3 py-1.5 rounded-lg">
<AlertCircle className="w-4 h-4 shrink-0" /> Source and target are the same
<AlertCircle className="w-4 h-4 shrink-0" /> Original Server and Target are the same
</span>
)}

Expand All @@ -464,7 +474,7 @@ export const TopToolbar: React.FC = () => {
!canSchemaCompare
? 'Your role cannot compare schemas'
: sameConfig
? 'Source and target point to the same database and schema'
? 'Original Server and Target point to the same database and schema'
: undefined
}
className={`flex items-center gap-2 px-5 py-2 rounded-lg text-base font-bold transition shadow-lg ${
Expand Down
23 changes: 15 additions & 8 deletions apps/web/src/frontend/components/sql-editor/DataMigrateBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ interface Props {
dest: DataMigrateGrid;
/** Trigger/audit columns excluded from UPDATE detection and INSERT/UPDATE SET. */
ignoreColumns?: string[];
/** Controlled key columns (shared with Compare alignment). */
keyNames?: string[];
onKeyNamesChange?: (names: string[]) => void;
onAfterMigrate?: () => void;
onOpenServerBeamSample?: () => void;
}
Expand All @@ -66,6 +69,8 @@ export const DataMigrateBar: React.FC<Props> = ({
source,
dest,
ignoreColumns = [],
keyNames: keyNamesProp,
onKeyNamesChange,
onAfterMigrate,
onOpenServerBeamSample,
}) => {
Expand All @@ -91,10 +96,13 @@ export const DataMigrateBar: React.FC<Props> = ({
[table, source.columns]
);

const [keyNames, setKeyNames] = useState<string[]>([]);
const [keyNamesLocal, setKeyNamesLocal] = useState<string[]>([]);
const keyNames = keyNamesProp ?? keyNamesLocal;
const setKeyNames = onKeyNamesChange ?? setKeyNamesLocal;
useEffect(() => {
setKeyNames(defaultKeys.length ? defaultKeys : source.columns.slice(0, 1));
}, [defaultKeys.join('\0'), source.columns.join('\0')]);
if (keyNamesProp) return;
setKeyNamesLocal(defaultKeys.length ? defaultKeys : source.columns.slice(0, 1));
}, [defaultKeys.join('\0'), source.columns.join('\0'), keyNamesProp]);

/** User opts into each op — nothing selected until they choose. */
const [doInsert, setDoInsert] = useState(false);
Expand Down Expand Up @@ -139,11 +147,10 @@ export const DataMigrateBar: React.FC<Props> = ({
);

const toggleKey = (name: string) => {
setKeyNames((prev) =>
prev.some((k) => k.toLowerCase() === name.toLowerCase())
? prev.filter((k) => k.toLowerCase() !== name.toLowerCase())
: [...prev, name]
);
const next = keyNames.some((k) => k.toLowerCase() === name.toLowerCase())
? keyNames.filter((k) => k.toLowerCase() !== name.toLowerCase())
: [...keyNames, name];
setKeyNames(next);
};

const openHistory = async () => {
Expand Down
Loading
Loading