feat: add copy to clipboard functionality and update button styles in raw request modal

This commit is contained in:
Lorenzo Venerandi
2026-03-04 12:37:55 +01:00
parent a385381dbd
commit ddc5dcade3
3 changed files with 59 additions and 11 deletions

View File

@@ -14,7 +14,14 @@
<pre class="raw-request-content" x-text="rawModal.content"></pre>
</div>
<div class="raw-request-modal-footer">
<button class="raw-request-download-btn" @click="downloadRawRequest()">Download as .txt</button>
<button class="raw-request-icon-btn" @click="copyRawRequest($event)" title="Copy to clipboard">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/></svg>
<span class="raw-request-icon-tooltip">Copy to clipboard</span>
</button>
<button class="raw-request-icon-btn" @click="downloadRawRequest()" title="Download as .txt">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"/><path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06Z"/></svg>
<span class="raw-request-icon-tooltip">Download as .txt</span>
</button>
</div>
</div>
</div>

View File

@@ -1108,20 +1108,47 @@ tbody {
border-top: 1px solid #30363d;
border-radius: 0 0 6px 6px;
text-align: right;
display: flex;
justify-content: flex-end;
gap: 8px;
}
.raw-request-download-btn {
padding: 8px 16px;
background: #238636;
color: #ffffff;
border: none;
.raw-request-icon-btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
background: #21262d;
color: #8b949e;
border: 1px solid #30363d;
border-radius: 6px;
font-weight: 500;
font-size: 13px;
cursor: pointer;
transition: background 0.2s;
transition: all 0.2s;
}
.raw-request-download-btn:hover {
background: #2ea043;
.raw-request-icon-btn:hover {
background: #30363d;
color: #58a6ff;
border-color: #58a6ff;
}
.raw-request-icon-tooltip {
position: absolute;
bottom: calc(100% + 6px);
left: 50%;
transform: translateX(-50%);
padding: 4px 8px;
background: #1c2128;
color: #e6edf3;
border: 1px solid #30363d;
border-radius: 4px;
font-size: 11px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.15s;
}
.raw-request-icon-btn:hover .raw-request-icon-tooltip {
opacity: 1;
}
/* Attack Types Cell Styling */

View File

@@ -111,6 +111,20 @@ document.addEventListener('alpine:init', () => {
this.rawModal.logId = null;
},
async copyRawRequest(event) {
if (!this.rawModal.content) return;
const btn = event.currentTarget;
const originalHTML = btn.innerHTML;
const checkIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="#3fb950"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>';
try {
await navigator.clipboard.writeText(this.rawModal.content);
btn.innerHTML = checkIcon;
} catch {
btn.style.color = '#f85149';
}
setTimeout(() => { btn.innerHTML = originalHTML; btn.style.color = ''; }, 1500);
},
downloadRawRequest() {
if (!this.rawModal.content) return;
const blob = new Blob([this.rawModal.content], { type: 'text/plain' });