mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-28 16:09:17 +00:00
feat(connection): add connection colors and database tab labels
This commit is contained in:
+29
-2
@@ -110,12 +110,33 @@ function connectionDisplayName(connectionId: string): string {
|
||||
return connectionStore.getConfig(connectionId)?.name || connectionId;
|
||||
}
|
||||
|
||||
function connectionColor(connectionId: string): string {
|
||||
return connectionStore.getConfig(connectionId)?.color || "";
|
||||
}
|
||||
|
||||
function databaseDisplayName(database: string): string {
|
||||
const connection = activeConnection.value;
|
||||
if (connection?.db_type === "redis" && database !== "") return `db${database}`;
|
||||
return database || t("editor.noDatabase");
|
||||
}
|
||||
|
||||
function tabDisplayTitle(tab: typeof queryStore.tabs[number]): string {
|
||||
const database = databaseDisplayNameForTab(tab.connectionId, tab.database);
|
||||
if (tab.mode === "data" && tab.tableMeta?.tableName) {
|
||||
return `${database} | ${tab.tableMeta.tableName}`;
|
||||
}
|
||||
if (tab.mode === "query") {
|
||||
return `${connectionDisplayName(tab.connectionId)} | ${database}`;
|
||||
}
|
||||
return tab.title;
|
||||
}
|
||||
|
||||
function databaseDisplayNameForTab(connectionId: string, database: string): string {
|
||||
const connection = connectionStore.getConfig(connectionId);
|
||||
if (connection?.db_type === "redis" && database !== "") return `db${database}`;
|
||||
return database || t("editor.noDatabase");
|
||||
}
|
||||
|
||||
async function loadDatabaseOptions(connectionId: string) {
|
||||
const connection = connectionStore.getConfig(connectionId);
|
||||
if (!connection || loadingDatabaseOptions.value[connectionId]) return;
|
||||
@@ -526,7 +547,8 @@ async function setupFileDrop() {
|
||||
:class="{ 'bg-background font-medium': tab.id === queryStore.activeTabId }"
|
||||
@click="queryStore.activeTabId = tab.id"
|
||||
>
|
||||
<span>{{ tab.title }}</span>
|
||||
<span v-if="connectionColor(tab.connectionId)" class="h-4 w-1 rounded-full shrink-0" :style="{ backgroundColor: connectionColor(tab.connectionId) }" />
|
||||
<span>{{ tabDisplayTitle(tab) }}</span>
|
||||
<button
|
||||
class="ml-1 rounded hover:bg-muted-foreground/20 p-0.5"
|
||||
@click.stop="queryStore.closeTab(tab.id)"
|
||||
@@ -540,6 +562,7 @@ async function setupFileDrop() {
|
||||
<div v-if="activeTab" class="flex flex-col flex-1 min-h-0">
|
||||
<div v-if="activeTab.mode === 'query'" class="h-8 shrink-0 border-b bg-background/80 px-3 flex items-center gap-2 text-xs text-muted-foreground">
|
||||
<Server class="h-3.5 w-3.5 shrink-0" />
|
||||
<span v-if="activeConnection?.color" class="h-4 w-1 rounded-full shrink-0" :style="{ backgroundColor: activeConnection.color }" />
|
||||
<Select
|
||||
:model-value="activeConnectionValue"
|
||||
@update:model-value="changeActiveConnection"
|
||||
@@ -555,7 +578,10 @@ async function setupFileDrop() {
|
||||
:key="connection.id"
|
||||
:value="connection.id"
|
||||
>
|
||||
{{ connection.name }}
|
||||
<div class="flex items-center gap-2">
|
||||
<span v-if="connection.color" class="h-3.5 w-1 rounded-full shrink-0" :style="{ backgroundColor: connection.color }" />
|
||||
<span>{{ connection.name }}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
@@ -710,6 +736,7 @@ async function setupFileDrop() {
|
||||
@click="openConnectionQuery(connection.id)"
|
||||
>
|
||||
<DatabaseIcon :db-type="connection.db_type" class="h-4 w-4" />
|
||||
<span v-if="connection.color" class="h-5 w-1 rounded-full shrink-0" :style="{ backgroundColor: connection.color }" />
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="truncate text-sm font-medium">{{ connection.name }}</div>
|
||||
<div class="truncate text-xs text-muted-foreground">
|
||||
|
||||
@@ -36,6 +36,7 @@ const defaultForm = (): Omit<ConnectionConfig, "id"> => ({
|
||||
username: "root",
|
||||
password: "",
|
||||
database: undefined,
|
||||
color: "",
|
||||
ssh_enabled: false,
|
||||
ssh_host: "",
|
||||
ssh_port: 22,
|
||||
@@ -48,6 +49,16 @@ const defaultForm = (): Omit<ConnectionConfig, "id"> => ({
|
||||
const form = ref(defaultForm());
|
||||
const selectedType = ref("mysql");
|
||||
|
||||
const colorOptions = [
|
||||
{ value: "", class: "bg-transparent border-dashed", labelKey: "connection.colorNone" },
|
||||
{ value: "#22c55e", class: "bg-green-500", labelKey: "connection.colorGreen" },
|
||||
{ value: "#eab308", class: "bg-yellow-500", labelKey: "connection.colorYellow" },
|
||||
{ value: "#f97316", class: "bg-orange-500", labelKey: "connection.colorOrange" },
|
||||
{ value: "#ef4444", class: "bg-red-500", labelKey: "connection.colorRed" },
|
||||
{ value: "#3b82f6", class: "bg-blue-500", labelKey: "connection.colorBlue" },
|
||||
{ value: "#a855f7", class: "bg-purple-500", labelKey: "connection.colorPurple" },
|
||||
];
|
||||
|
||||
watch(() => props.editConfig, (config) => {
|
||||
if (config) {
|
||||
editingId.value = config.id;
|
||||
@@ -59,6 +70,7 @@ watch(() => props.editConfig, (config) => {
|
||||
username: config.username,
|
||||
password: config.password,
|
||||
database: config.database,
|
||||
color: config.color || "",
|
||||
ssh_enabled: config.ssh_enabled || false,
|
||||
ssh_host: config.ssh_host || "",
|
||||
ssh_port: config.ssh_port || 22,
|
||||
@@ -245,6 +257,21 @@ watch([() => editingId.value, () => open.value], () => {
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label class="text-right">{{ t('connection.color') }}</Label>
|
||||
<div class="col-span-3 flex items-center gap-1.5">
|
||||
<button
|
||||
v-for="color in colorOptions"
|
||||
:key="color.value || 'none'"
|
||||
type="button"
|
||||
class="h-6 w-6 rounded-full border ring-offset-background transition hover:scale-105"
|
||||
:class="[color.class, form.color === color.value ? 'ring-2 ring-ring ring-offset-2' : 'border-border']"
|
||||
:title="t(color.labelKey)"
|
||||
@click="form.color = color.value"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SQLite / DuckDB: file path only -->
|
||||
<template v-if="form.db_type === 'sqlite' || form.db_type === 'duckdb'">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
|
||||
@@ -223,6 +223,11 @@ const isConnected = computed(() =>
|
||||
props.node.type === "connection" && !!props.node.connectionId && connectionStore.connectedIds.has(props.node.connectionId)
|
||||
);
|
||||
|
||||
const connectionColor = computed(() => {
|
||||
const connectionId = props.node.connectionId;
|
||||
return connectionId ? connectionStore.getConfig(connectionId)?.color || "" : "";
|
||||
});
|
||||
|
||||
const CHILDREN_PAGE_SIZE = 100;
|
||||
const displayLimit = ref(CHILDREN_PAGE_SIZE);
|
||||
|
||||
@@ -269,6 +274,7 @@ async function showMore() {
|
||||
<span v-else class="w-3.5 h-3.5 shrink-0" />
|
||||
<DatabaseIcon v-if="node.type === 'connection'" :db-type="connectionStore.getConfig(node.connectionId || '')?.db_type || 'postgres'" class="w-3.5 h-3.5 shrink-0" />
|
||||
<component v-else :is="getIconInfo(node)?.icon || Database" class="w-3.5 h-3.5 shrink-0" :class="getIconInfo(node)?.colorClass" />
|
||||
<span v-if="node.type === 'connection' && connectionColor" class="h-3 w-1.5 rounded-full shrink-0" :style="{ backgroundColor: connectionColor }" />
|
||||
<span class="truncate">{{ isGroupLabel(node) ? t(node.label) : node.label }}</span>
|
||||
<span v-if="node.type === 'connection' && node.connectionId && connectionStore.connectedIds.has(node.connectionId)" class="w-1.5 h-1.5 rounded-full bg-green-500 shrink-0" />
|
||||
</div>
|
||||
|
||||
@@ -41,6 +41,14 @@ export default {
|
||||
sshPasswordPlaceholder: "Leave empty to use key",
|
||||
sshKeyPath: "Key Path",
|
||||
compatible: "Compatible",
|
||||
color: "Color",
|
||||
colorNone: "No color",
|
||||
colorGreen: "Green",
|
||||
colorYellow: "Yellow",
|
||||
colorOrange: "Orange",
|
||||
colorRed: "Red",
|
||||
colorBlue: "Blue",
|
||||
colorPurple: "Purple",
|
||||
},
|
||||
editor: {
|
||||
pressToExecute: "Press Cmd+Enter to execute",
|
||||
|
||||
@@ -41,6 +41,14 @@ export default {
|
||||
sshPasswordPlaceholder: "留空则使用密钥",
|
||||
sshKeyPath: "密钥路径",
|
||||
compatible: "兼容",
|
||||
color: "颜色",
|
||||
colorNone: "无颜色",
|
||||
colorGreen: "绿色",
|
||||
colorYellow: "黄色",
|
||||
colorOrange: "橙色",
|
||||
colorRed: "红色",
|
||||
colorBlue: "蓝色",
|
||||
colorPurple: "紫色",
|
||||
},
|
||||
editor: {
|
||||
pressToExecute: "按 Cmd+Enter 执行查询",
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface ConnectionConfig {
|
||||
username: string;
|
||||
password: string;
|
||||
database?: string;
|
||||
color?: string;
|
||||
ssh_enabled?: boolean;
|
||||
ssh_host?: string;
|
||||
ssh_port?: number;
|
||||
|
||||
Reference in New Issue
Block a user