mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-01 10:21:53 +00:00
feat: add required acknowledgement warning to install copy button
- Adds a modal to `landing/index.html` warning users about the "freshly vibecoded" nature of the project. - Intercepts the "Install via NPM" copy button to require acknowledgement before copying. - Styles the modal with a danger theme consistent with the warning. - Verified with Playwright. Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
14002a7bf9
commit
ac7ba2a895
7 files changed
+221
-2
No files matched your search
+124
-2
@@ -439,6 +439,75 @@
|
|||||||
.copy-install-btn:active {
|
.copy-install-btn:active {
|
||||||
transform: scale(0.98);
|
transform: scale(0.98);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Acknowledgement Modal Styles */
|
||||||
|
#ackModal .modal-content {
|
||||||
|
border-color: var(--danger);
|
||||||
|
max-width: 500px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ackModal h2 {
|
||||||
|
color: var(--danger);
|
||||||
|
margin-top: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ackModal .modal-body {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: var(--text);
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ackModal .modal-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ackModal .btn-cancel {
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
color: var(--text);
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ackModal .btn-cancel:hover {
|
||||||
|
background: var(--surface-alt);
|
||||||
|
color: var(--text-strong);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ackModal .btn-confirm {
|
||||||
|
background: var(--danger);
|
||||||
|
border: 1px solid var(--danger);
|
||||||
|
color: white;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 50, 50, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ackModal .btn-confirm:hover {
|
||||||
|
background: #ff4d4d; /* lighter red */
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(255, 50, 50, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define danger color if not exists in dashboard/styles.css */
|
||||||
|
:root {
|
||||||
|
--danger: #ef4444;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -469,7 +538,7 @@
|
|||||||
<p class="install-label">Install via NPM</p>
|
<p class="install-label">Install via NPM</p>
|
||||||
<div class="install-code-wrapper">
|
<div class="install-code-wrapper">
|
||||||
<code id="install-cmd">npm install torch-lock</code>
|
<code id="install-cmd">npm install torch-lock</code>
|
||||||
<button class="copy-install-btn" onclick="copyToClipboard('install-cmd', this)">
|
<button class="copy-install-btn" onclick="copyToClipboard('install-cmd', this, true)">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||||
@@ -539,6 +608,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Acknowledgement Modal -->
|
||||||
|
<div id="ackModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<h2>
|
||||||
|
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
|
||||||
|
<line x1="12" y1="9" x2="12" y2="13"></line>
|
||||||
|
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
||||||
|
</svg>
|
||||||
|
Warning: Vibecoded Project
|
||||||
|
</h2>
|
||||||
|
<div class="modal-body">
|
||||||
|
This is a freshly vibecoded project and that using this in a valuable production repo is reckless.
|
||||||
|
</div>
|
||||||
|
<div class="modal-actions">
|
||||||
|
<button class="btn-cancel" onclick="dismissAckModal()">Cancel</button>
|
||||||
|
<button class="btn-confirm" onclick="confirmAck()">I Understand, Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Modal Logic
|
// Modal Logic
|
||||||
const modal = document.getElementById("docsModal");
|
const modal = document.getElementById("docsModal");
|
||||||
@@ -562,6 +652,9 @@
|
|||||||
if (event.target == modal) {
|
if (event.target == modal) {
|
||||||
modal.classList.remove("show");
|
modal.classList.remove("show");
|
||||||
}
|
}
|
||||||
|
if (event.target == ackModal) {
|
||||||
|
dismissAckModal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch and Render Markdown
|
// Fetch and Render Markdown
|
||||||
@@ -609,7 +702,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyToClipboard(elementId, btn) {
|
// Acknowledgement Logic
|
||||||
|
let hasAcknowledged = false;
|
||||||
|
let pendingCopy = null;
|
||||||
|
const ackModal = document.getElementById('ackModal');
|
||||||
|
|
||||||
|
function showAckModal(callback) {
|
||||||
|
pendingCopy = callback;
|
||||||
|
ackModal.classList.add('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissAckModal() {
|
||||||
|
ackModal.classList.remove('show');
|
||||||
|
pendingCopy = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmAck() {
|
||||||
|
hasAcknowledged = true;
|
||||||
|
ackModal.classList.remove('show');
|
||||||
|
if (pendingCopy) {
|
||||||
|
pendingCopy();
|
||||||
|
pendingCopy = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyToClipboard(elementId, btn, requiresAck = false) {
|
||||||
|
if (requiresAck && !hasAcknowledged) {
|
||||||
|
showAckModal(() => copyToClipboard(elementId, btn, false));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const code = document.getElementById(elementId).textContent;
|
const code = document.getElementById(elementId).textContent;
|
||||||
navigator.clipboard.writeText(code).then(() => {
|
navigator.clipboard.writeText(code).then(() => {
|
||||||
const originalContent = btn.innerHTML;
|
const originalContent = btn.innerHTML;
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
@@ -0,0 +1,63 @@
|
|||||||
|
from playwright.sync_api import sync_playwright, expect
|
||||||
|
|
||||||
|
def test_ack_modal():
|
||||||
|
with sync_playwright() as p:
|
||||||
|
browser = p.chromium.launch(headless=True)
|
||||||
|
# Grant clipboard permissions
|
||||||
|
context = browser.new_context(permissions=["clipboard-read", "clipboard-write"])
|
||||||
|
page = context.new_page()
|
||||||
|
|
||||||
|
page.on("console", lambda msg: print(f"Console: {msg.text}"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
page.goto("http://localhost:8000/landing/index.html")
|
||||||
|
|
||||||
|
copy_btn = page.locator(".copy-install-btn")
|
||||||
|
ack_modal = page.locator("#ackModal")
|
||||||
|
|
||||||
|
# 1. Click Copy
|
||||||
|
print("Clicking Copy...")
|
||||||
|
copy_btn.click()
|
||||||
|
|
||||||
|
# 2. Verify Modal Appears
|
||||||
|
expect(ack_modal).to_be_visible()
|
||||||
|
print("Modal appeared.")
|
||||||
|
|
||||||
|
# Verify text is NOT copied yet (button text hasn't changed)
|
||||||
|
expect(copy_btn).not_to_have_text("Copied!", timeout=500)
|
||||||
|
print("Copy deferred.")
|
||||||
|
|
||||||
|
page.screenshot(path="verification/modal_visible.png")
|
||||||
|
|
||||||
|
# 3. Click Cancel
|
||||||
|
cancel_btn = page.locator("#ackModal .btn-cancel")
|
||||||
|
cancel_btn.click()
|
||||||
|
|
||||||
|
expect(ack_modal).not_to_be_visible()
|
||||||
|
expect(copy_btn).not_to_have_text("Copied!")
|
||||||
|
print("Cancelled correctly.")
|
||||||
|
|
||||||
|
# 4. Click Copy Again
|
||||||
|
copy_btn.click()
|
||||||
|
expect(ack_modal).to_be_visible()
|
||||||
|
|
||||||
|
# 5. Click Confirm
|
||||||
|
confirm_btn = page.locator("#ackModal .btn-confirm")
|
||||||
|
confirm_btn.click()
|
||||||
|
|
||||||
|
expect(ack_modal).not_to_be_visible()
|
||||||
|
expect(copy_btn).to_have_text("Copied!", timeout=2000)
|
||||||
|
print("Confirmed and copied.")
|
||||||
|
|
||||||
|
page.screenshot(path="verification/after_ack.png")
|
||||||
|
print("Verification successful.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Verification failed: {e}")
|
||||||
|
page.screenshot(path="verification/failure.png")
|
||||||
|
raise e
|
||||||
|
finally:
|
||||||
|
browser.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_ack_modal()
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
from playwright.sync_api import sync_playwright, expect
|
||||||
|
|
||||||
|
def test_copy_button():
|
||||||
|
with sync_playwright() as p:
|
||||||
|
browser = p.chromium.launch(headless=True)
|
||||||
|
# Grant clipboard permissions
|
||||||
|
context = browser.new_context(permissions=["clipboard-read", "clipboard-write"])
|
||||||
|
page = context.new_page()
|
||||||
|
|
||||||
|
page.on("console", lambda msg: print(f"Console: {msg.text}"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
page.goto("http://localhost:8000/landing/index.html")
|
||||||
|
|
||||||
|
copy_btn = page.locator(".copy-install-btn")
|
||||||
|
expect(copy_btn).to_be_visible()
|
||||||
|
|
||||||
|
copy_btn.click()
|
||||||
|
|
||||||
|
# Verify text changes to "Copied!"
|
||||||
|
expect(copy_btn).to_have_text("Copied!", timeout=2000)
|
||||||
|
|
||||||
|
page.screenshot(path="verification/before_change.png")
|
||||||
|
print("Successfully verified copy button works without warning.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Verification failed: {e}")
|
||||||
|
page.screenshot(path="verification/failure.png")
|
||||||
|
raise e
|
||||||
|
finally:
|
||||||
|
browser.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_copy_button()
|
||||||
Reference in new issue
Block a user