Add test connection feature for database targets
This commit introduces a new endpoint to test database connection. The frontend now includes a button to test the connection before creating a target, with real-time feedback on success or failure. Related styles and components were updated for better user experience.
This commit is contained in:
@@ -20,6 +20,7 @@ export function TargetsPage() {
|
||||
const [form, setForm] = useState(emptyForm);
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [testState, setTestState] = useState({ loading: false, message: "", ok: null });
|
||||
|
||||
const canManage = me?.role === "admin" || me?.role === "operator";
|
||||
|
||||
@@ -50,6 +51,31 @@ export function TargetsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const testConnection = async () => {
|
||||
setTestState({ loading: true, message: "", ok: null });
|
||||
try {
|
||||
const result = await apiFetch(
|
||||
"/targets/test-connection",
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
host: form.host,
|
||||
port: form.port,
|
||||
dbname: form.dbname,
|
||||
username: form.username,
|
||||
password: form.password,
|
||||
sslmode: form.sslmode,
|
||||
}),
|
||||
},
|
||||
tokens,
|
||||
refresh
|
||||
);
|
||||
setTestState({ loading: false, message: `${result.message} (PostgreSQL ${result.server_version})`, ok: true });
|
||||
} catch (e) {
|
||||
setTestState({ loading: false, message: String(e.message || e), ok: false });
|
||||
}
|
||||
};
|
||||
|
||||
const deleteTarget = async (id) => {
|
||||
if (!confirm("Delete target?")) return;
|
||||
try {
|
||||
@@ -66,7 +92,7 @@ export function TargetsPage() {
|
||||
{error && <div className="card error">{error}</div>}
|
||||
|
||||
{canManage && (
|
||||
<details className="card collapsible" open>
|
||||
<details className="card collapsible">
|
||||
<summary className="collapse-head">
|
||||
<div>
|
||||
<h3>New Target</h3>
|
||||
@@ -111,9 +137,17 @@ export function TargetsPage() {
|
||||
</small>
|
||||
</div>
|
||||
<div className="field submit-field">
|
||||
<button className="primary-btn">Create target</button>
|
||||
<div className="target-actions">
|
||||
<button type="button" className="secondary-btn" onClick={testConnection} disabled={testState.loading}>
|
||||
{testState.loading ? "Testing..." : "Test connection"}
|
||||
</button>
|
||||
<button className="primary-btn">Create target</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{testState.message && (
|
||||
<div className={`test-connection-result ${testState.ok ? "ok" : "fail"}`}>{testState.message}</div>
|
||||
)}
|
||||
</details>
|
||||
)}
|
||||
|
||||
|
||||
@@ -269,8 +269,8 @@ button {
|
||||
border-color: #3384cb;
|
||||
background: linear-gradient(180deg, #15528d, #114170);
|
||||
box-shadow: inset 0 1px 0 #5f8de144;
|
||||
padding: 7px 12px;
|
||||
min-height: 38px;
|
||||
padding: 6px 12px;
|
||||
min-height: 34px;
|
||||
}
|
||||
|
||||
.primary-btn:hover {
|
||||
@@ -278,6 +278,48 @@ button {
|
||||
background: linear-gradient(180deg, #1a63a9, #14558f);
|
||||
}
|
||||
|
||||
.submit-field {
|
||||
align-self: end;
|
||||
}
|
||||
|
||||
.target-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
font-weight: 600;
|
||||
border-color: #3f6ea9;
|
||||
background: linear-gradient(180deg, #14365f, #102c4f);
|
||||
padding: 6px 12px;
|
||||
min-height: 34px;
|
||||
}
|
||||
|
||||
.secondary-btn:hover {
|
||||
border-color: #69a9de;
|
||||
}
|
||||
|
||||
.test-connection-result {
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
border-radius: 10px;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.test-connection-result.ok {
|
||||
color: #b9f3cf;
|
||||
border-color: #2f8f63;
|
||||
background: #123727;
|
||||
}
|
||||
|
||||
.test-connection-result.fail {
|
||||
color: #fecaca;
|
||||
border-color: #b64a4a;
|
||||
background: #3a1c22;
|
||||
}
|
||||
|
||||
.collapsible {
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user