Toggle credentials in instance detail view

This commit is contained in:
Tobias Kunze 2025-12-09 15:50:46 +01:00
parent 15b5d78c62
commit feede16265
2 changed files with 96 additions and 3 deletions

View file

@ -216,8 +216,17 @@
{% if instance.connection_credentials %}
<div class="col-12">
<div class="card">
<div class="card-header">
<h4>{% translate "Connection Credentials" %}</h4>
<div class="card-header d-flex justify-content-between align-items-center">
<h4 class="mb-0">{% translate "Connection Credentials" %}</h4>
<button type="button"
class="btn btn-sm btn-outline-secondary"
id="toggle-credentials-btn"
data-show-text="{% translate "Show All" %}"
data-hide-text="{% translate "Hide All" %}"
onclick="toggleAllCredentials()">
<i class="bi bi-eye me-1"></i>
<span id="toggle-credentials-text">{% translate "Show All" %}</span>
</button>
</div>
<div class="card-body">
<div class="table-responsive">
@ -226,6 +235,7 @@
<tr>
<th>{% translate "Name" %}</th>
<th>{% translate "Value" %}</th>
<th style="width: 50px;"></th>
</tr>
</thead>
<tbody>
@ -236,7 +246,17 @@
{% if key == "error" %}
<span class="text-danger">{{ value }}</span>
{% else %}
<code>{{ value }}</code>
<code class="credential-value" data-value="{{ value }}">••••••••••••</code>
{% endif %}
</td>
<td class="text-center">
{% if key != "error" %}
<button type="button"
class="btn btn-sm btn-link p-0 credential-toggle"
onclick="toggleCredential(this)"
title="{% translate 'Show/Hide' %}">
<i class="bi bi-eye"></i>
</button>
{% endif %}
</td>
</tr>
@ -244,6 +264,10 @@
</tbody>
</table>
</div>
<div class="text-muted small mt-2">
<i class="bi bi-info-circle me-1"></i>
{% translate "Click the eye icon to reveal individual credentials, or use 'Show All' to reveal all at once." %}
</div>
</div>
</div>
</div>
@ -282,6 +306,7 @@
{% endblock content %}
{% block extra_js %}
<script src="{% static 'js/local-time.js' %}"></script>
<script src="{% static 'js/credentials.js' %}"></script>
<script>
// Initialize Bootstrap popovers for help text
document.addEventListener('DOMContentLoaded', function() {

View file

@ -0,0 +1,68 @@
const CREDENTIAL_MASK = '••••••••••••';
function toggleCredential(button) {
const row = button.closest('tr');
const codeEl = row.querySelector('.credential-value');
const icon = button.querySelector('i');
if (!codeEl) return;
const isHidden = codeEl.textContent === CREDENTIAL_MASK;
if (isHidden) {
codeEl.textContent = codeEl.getAttribute('data-value');
icon.classList.remove('bi-eye');
icon.classList.add('bi-eye-slash');
} else {
codeEl.textContent = CREDENTIAL_MASK;
icon.classList.remove('bi-eye-slash');
icon.classList.add('bi-eye');
}
updateShowAllButton();
}
function toggleAllCredentials() {
const credentials = document.querySelectorAll('.credential-value');
const anyHidden = Array.from(credentials).some(el => el.textContent === CREDENTIAL_MASK);
credentials.forEach(function (codeEl) {
const row = codeEl.closest('tr');
const button = row.querySelector('.credential-toggle');
const icon = button ? button.querySelector('i') : null;
if (anyHidden) {
codeEl.textContent = codeEl.getAttribute('data-value');
if (icon) {
icon.classList.remove('bi-eye');
icon.classList.add('bi-eye-slash');
}
} else {
codeEl.textContent = CREDENTIAL_MASK;
if (icon) {
icon.classList.remove('bi-eye-slash');
icon.classList.add('bi-eye');
}
}
});
updateShowAllButton();
}
function updateShowAllButton() {
const credentials = document.querySelectorAll('.credential-value');
const anyHidden = Array.from(credentials).some(el => el.textContent === CREDENTIAL_MASK);
const toggleBtn = document.getElementById('toggle-credentials-btn');
const toggleText = document.getElementById('toggle-credentials-text');
const toggleIcon = toggleBtn ? toggleBtn.querySelector('i') : null;
if (toggleText && toggleBtn) {
const showText = toggleBtn.getAttribute('data-show-text') || 'Show All';
const hideText = toggleBtn.getAttribute('data-hide-text') || 'Hide All';
toggleText.textContent = anyHidden ? showText : hideText;
}
if (toggleIcon) {
toggleIcon.classList.toggle('bi-eye', anyHidden);
toggleIcon.classList.toggle('bi-eye-slash', !anyHidden);
}
}