fix admin copy text functions

This commit is contained in:
Chris Lu
2026-01-08 18:44:36 -08:00
parent abfa64456b
commit 6bf0c16862
3 changed files with 75 additions and 25 deletions

View File

@@ -660,14 +660,46 @@ function formatDate(date) {
return new Date(date).toLocaleString(); return new Date(date).toLocaleString();
} }
// Copy text to clipboard // Copy text to clipboard with fallback for non-secure contexts
function copyToClipboard(text) { function adminCopyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => { if (navigator.clipboard && navigator.clipboard.writeText) {
showAlert('success', 'Copied to clipboard!'); navigator.clipboard.writeText(text).then(() => {
}).catch(err => { showAlert('success', 'Copied to clipboard!');
console.error('Failed to copy text: ', err); }).catch(err => {
console.error('Failed to copy text: ', err);
fallbackCopyText(text);
});
} else {
fallbackCopyText(text);
}
}
function fallbackCopyText(text) {
const textArea = document.createElement("textarea");
textArea.value = text;
// Ensure textArea is not visible but part of the DOM
textArea.style.position = "fixed";
textArea.style.left = "-9999px";
textArea.style.top = "0";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand('copy');
if (successful) {
showAlert('success', 'Copied to clipboard!');
} else {
showAlert('danger', 'Failed to copy to clipboard');
}
} catch (err) {
console.error('Fallback copy failed: ', err);
showAlert('danger', 'Failed to copy to clipboard'); showAlert('danger', 'Failed to copy to clipboard');
}); }
document.body.removeChild(textArea);
} }
// Dashboard refresh functionality // Dashboard refresh functionality
@@ -2359,7 +2391,7 @@ function createAccessKeysManagementContent(accessKeys) {
<tr> <tr>
<td> <td>
<code>${key.access_key}</code> <code>${key.access_key}</code>
<button class="btn btn-sm btn-outline-secondary ms-2" onclick="copyToClipboard('${key.access_key}')"> <button class="btn btn-sm btn-outline-secondary ms-2" onclick="adminCopyToClipboard('${key.access_key}')">
<i class="fas fa-copy"></i> <i class="fas fa-copy"></i>
</button> </button>
</td> </td>
@@ -2454,7 +2486,7 @@ function showSecretKey(accessKey, secretKey) {
<label class="form-label"><strong>Access Key:</strong></label> <label class="form-label"><strong>Access Key:</strong></label>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" value="${accessKey}" readonly> <input type="text" class="form-control" value="${accessKey}" readonly>
<button class="btn btn-outline-secondary" onclick="copyToClipboard('${accessKey}')"> <button class="btn btn-outline-secondary" onclick="adminCopyToClipboard('${accessKey}')">
<i class="fas fa-copy"></i> <i class="fas fa-copy"></i>
</button> </button>
</div> </div>
@@ -2463,7 +2495,7 @@ function showSecretKey(accessKey, secretKey) {
<label class="form-label"><strong>Secret Key:</strong></label> <label class="form-label"><strong>Secret Key:</strong></label>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" value="${secretKey}" readonly> <input type="text" class="form-control" value="${secretKey}" readonly>
<button class="btn btn-outline-secondary" onclick="copyToClipboard('${secretKey}')"> <button class="btn btn-outline-secondary" onclick="adminCopyToClipboard('${secretKey}')">
<i class="fas fa-copy"></i> <i class="fas fa-copy"></i>
</button> </button>
</div> </div>
@@ -2487,7 +2519,7 @@ function showNewAccessKeyModal(accessKeyData) {
<label class="form-label"><strong>Access Key:</strong></label> <label class="form-label"><strong>Access Key:</strong></label>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" value="${accessKeyData.access_key}" readonly> <input type="text" class="form-control" value="${accessKeyData.access_key}" readonly>
<button class="btn btn-outline-secondary" onclick="copyToClipboard('${accessKeyData.access_key}')"> <button class="btn btn-outline-secondary" onclick="adminCopyToClipboard('${accessKeyData.access_key}')">
<i class="fas fa-copy"></i> <i class="fas fa-copy"></i>
</button> </button>
</div> </div>
@@ -2496,7 +2528,7 @@ function showNewAccessKeyModal(accessKeyData) {
<label class="form-label"><strong>Secret Key:</strong></label> <label class="form-label"><strong>Secret Key:</strong></label>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" value="${accessKeyData.secret_key}" readonly> <input type="text" class="form-control" value="${accessKeyData.secret_key}" readonly>
<button class="btn btn-outline-secondary" onclick="copyToClipboard('${accessKeyData.secret_key}')"> <button class="btn btn-outline-secondary" onclick="adminCopyToClipboard('${accessKeyData.secret_key}')">
<i class="fas fa-copy"></i> <i class="fas fa-copy"></i>
</button> </button>
</div> </div>

View File

@@ -270,7 +270,7 @@ templ ServiceAccounts(data dash.ServiceAccountsData) {
<label class="form-label fw-bold">AWS_ACCESS_KEY_ID</label> <label class="form-label fw-bold">AWS_ACCESS_KEY_ID</label>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control font-monospace" id="displayAccessKey" readonly> <input type="text" class="form-control font-monospace" id="displayAccessKey" readonly>
<button class="btn btn-outline-secondary" type="button" onclick="copyToClipboard(event, 'displayAccessKey')"> <button class="btn btn-outline-secondary" type="button" onclick="copyCredentialToClipboard(this, 'displayAccessKey')">
<i class="fas fa-copy"></i> Copy <i class="fas fa-copy"></i> Copy
</button> </button>
</div> </div>
@@ -280,7 +280,7 @@ templ ServiceAccounts(data dash.ServiceAccountsData) {
<label class="form-label fw-bold">AWS_SECRET_ACCESS_KEY</label> <label class="form-label fw-bold">AWS_SECRET_ACCESS_KEY</label>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control font-monospace" id="displaySecretKey" readonly> <input type="text" class="form-control font-monospace" id="displaySecretKey" readonly>
<button class="btn btn-outline-secondary" type="button" onclick="copyToClipboard(event, 'displaySecretKey')"> <button class="btn btn-outline-secondary" type="button" onclick="copyCredentialToClipboard(this, 'displaySecretKey')">
<i class="fas fa-copy"></i> Copy <i class="fas fa-copy"></i> Copy
</button> </button>
</div> </div>
@@ -474,27 +474,25 @@ templ ServiceAccounts(data dash.ServiceAccountsData) {
setTimeout(() => window.location.reload(), 500); setTimeout(() => window.location.reload(), 500);
} }
function copyToClipboard(event, elementId) { function copyCredentialToClipboard(button, elementId) {
const element = document.getElementById(elementId); const element = document.getElementById(elementId);
const textToCopy = element.value;
// Use modern Clipboard API if available // Use modern Clipboard API if available
if (navigator.clipboard) { if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(element.value).then(() => { navigator.clipboard.writeText(textToCopy).then(() => {
// Success feedback could be added here showSuccessMessage('Copied to clipboard!');
}).catch(err => { }).catch(err => {
console.warn('Clipboard API failed:', err); console.warn('Clipboard API failed:', err);
// Fallback // Fallback
element.select(); fallbackCopyTextToClipboard(element);
document.execCommand('copy');
}); });
} else { } else {
// Fallback for older browsers // Fallback for older browsers or non-secure contexts
element.select(); fallbackCopyTextToClipboard(element);
document.execCommand('copy');
} }
// Visual feedback // Visual feedback
const button = event.target.closest('button');
const originalHTML = button.innerHTML; const originalHTML = button.innerHTML;
button.innerHTML = '<i class="fas fa-check"></i>'; button.innerHTML = '<i class="fas fa-check"></i>';
@@ -508,6 +506,26 @@ templ ServiceAccounts(data dash.ServiceAccountsData) {
}, 1000); }, 1000);
} }
function fallbackCopyTextToClipboard(element) {
element.select();
element.setSelectionRange(0, 99999); // For mobile devices
try {
const successful = document.execCommand('copy');
if (successful) {
showSuccessMessage('Copied to clipboard!');
} else {
showErrorMessage('Failed to copy to clipboard');
}
} catch (err) {
console.error('Fallback copy failed:', err);
showErrorMessage('Failed to copy to clipboard');
}
// Clear selection
window.getSelection().removeAllRanges();
}
function createSADetailsContent(sa) { function createSADetailsContent(sa) {
// Create DOM elements safely to prevent XSS // Create DOM elements safely to prevent XSS

File diff suppressed because one or more lines are too long