feat(connection): allow revealing saved passwords

This commit is contained in:
t8y2 2026-07-02 02:49:02 +08:00
parent d55a708d6a
commit 609f2ef7c7
11 changed files with 588 additions and 436 deletions

View File

@ -3482,7 +3482,7 @@ function openExternalUrl(url: string) {
<template v-if="mqAuthKind === 'token'">
<div class="grid grid-cols-4 items-center gap-4">
<Label :class="connectionLabelClass">Token</Label>
<Input v-model="mqToken" type="password" class="col-span-3" />
<PasswordInput v-model="mqToken" class="col-span-3" />
</div>
</template>
<template v-else-if="mqAuthKind === 'basic'">
@ -3492,7 +3492,7 @@ function openExternalUrl(url: string) {
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label :class="connectionLabelClass">{{ t("connection.password") }}</Label>
<Input v-model="mqBasicPassword" type="password" class="col-span-3" />
<PasswordInput v-model="mqBasicPassword" class="col-span-3" />
</div>
<div v-if="mqSystemKind === 'kafka'" class="grid grid-cols-4 items-center gap-4">
<Label :class="connectionLabelClass">SASL Mechanism</Label>
@ -3515,7 +3515,7 @@ function openExternalUrl(url: string) {
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label :class="connectionLabelClass">Value</Label>
<Input v-model="mqApiKeyValue" type="password" class="col-span-3" />
<PasswordInput v-model="mqApiKeyValue" class="col-span-3" />
</div>
</template>
<template v-else-if="mqAuthKind === 'oauth2'">
@ -3529,7 +3529,7 @@ function openExternalUrl(url: string) {
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label :class="connectionLabelClass">Client Secret</Label>
<Input v-model="mqOauthClientSecret" type="password" class="col-span-3" />
<PasswordInput v-model="mqOauthClientSecret" class="col-span-3" />
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label :class="connectionLabelClass">Audience</Label>

View File

@ -1,26 +1,35 @@
<script setup lang="ts">
import { computed, ref } from "vue";
import { useI18n } from "vue-i18n";
import { Eye, EyeOff } from "@lucide/vue";
import { Input } from "@/components/ui/input";
const model = defineModel<string>();
const props = defineProps<{
placeholder?: string;
disabled?: boolean;
class?: string;
inputClass?: string;
showToggle?: boolean;
}>();
const props = withDefaults(
defineProps<{
placeholder?: string;
disabled?: boolean;
class?: string;
inputClass?: string;
showToggle?: boolean;
showLabel?: string;
hideLabel?: string;
}>(),
{
showToggle: true,
},
);
const visible = ref(false);
const showToggle = computed(() => props.showToggle ?? true);
const { t } = useI18n();
const toggleLabel = computed(() => (visible.value ? props.hideLabel || t("common.hidePassword") : props.showLabel || t("common.showPassword")));
</script>
<template>
<div :class="props.class" class="relative">
<Input v-model="model" :type="visible ? 'text' : 'password'" :placeholder="placeholder" :disabled="disabled" :class="[props.inputClass, showToggle ? 'pr-8' : undefined]" v-bind="$attrs" />
<button v-if="showToggle" type="button" :disabled="disabled" class="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground disabled:pointer-events-none" tabindex="-1" @click="visible = !visible">
<Input v-model="model" :type="visible ? 'text' : 'password'" :placeholder="placeholder" :disabled="disabled" :class="[props.inputClass, props.showToggle ? 'pr-8' : undefined]" v-bind="$attrs" />
<button v-if="props.showToggle" type="button" :disabled="disabled" class="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground disabled:pointer-events-none disabled:opacity-50" :aria-label="toggleLabel" :title="toggleLabel" @click="visible = !visible">
<Eye v-if="!visible" class="size-3.5" />
<EyeOff v-else class="size-3.5" />
</button>

View File

@ -931,6 +931,8 @@ export default {
more: "More",
decrease: "Decrease",
increase: "Increase",
showPassword: "Show password",
hidePassword: "Hide password",
done: "Done",
connection: "Connection",
database: "Database",

View File

@ -916,6 +916,8 @@ export default withEnglishFallback({
remove: "Eliminar",
retry: "Reintentar",
more: "Más",
showPassword: "Mostrar contraseña",
hidePassword: "Ocultar contraseña",
done: "Listo",
connection: "Conexión",
database: "Base de datos",

View File

@ -932,6 +932,8 @@ export default withEnglishFallback({
more: "Altro",
decrease: "Riduci",
increase: "Aumenta",
showPassword: "Mostra password",
hidePassword: "Nascondi password",
done: "Fatto",
connection: "Connessione",
database: "Database",

View File

@ -914,6 +914,8 @@ export default withEnglishFallback({
save: "保存",
retry: "再試行",
more: "もっと見る",
showPassword: "パスワードを表示",
hidePassword: "パスワードを隠す",
done: "完了",
connection: "接続",
database: "データベース",

View File

@ -925,6 +925,8 @@ export default withEnglishFallback({
save: "Salvar",
retry: "Tentar novamente",
more: "Mais",
showPassword: "Mostrar senha",
hidePassword: "Ocultar senha",
done: "Concluído",
copy: "Copiar",
import: "Importar",

View File

@ -934,6 +934,8 @@ export default withEnglishFallback({
more: "更多",
decrease: "减小",
increase: "增大",
showPassword: "显示密码",
hidePassword: "隐藏密码",
done: "完成",
connection: "连接",
database: "数据库",

View File

@ -917,6 +917,8 @@ export default withEnglishFallback({
remove: "移除",
retry: "重試",
more: "更多",
showPassword: "顯示密碼",
hidePassword: "隱藏密碼",
done: "完成",
connection: "連線",
database: "資料庫",

View File

@ -72,8 +72,8 @@
"leaflet": "^1.9.4",
"marked": "^18.0.4",
"pinia": "^3.0.0",
"reka-ui": "^2.9.8",
"shadcn-vue": "^2.7.3",
"reka-ui": "^2.10.1",
"shadcn-vue": "^2.7.4",
"shiki": "^4.2.0",
"splitpanes": "^4.1.2",
"sql-formatter": "^15.8.0",

File diff suppressed because it is too large Load Diff