package webui import ( "fmt" "github.com/pogo-vcs/pogo/db" "github.com/pogo-vcs/pogo/server/env" "github.com/pogo-vcs/pogo/server/webui/components" "time" ) script inviteScript() { // Handle create invite form submission document.getElementById("createInviteForm").addEventListener("submit", async (e) => { e.preventDefault(); const hours = document.getElementById("hours").value; const errorDiv = document.getElementById("errorMessage"); const successDiv = document.getElementById("successMessage"); try { const formData = new FormData(); formData.append("hours", hours); const response = await fetch("/api/invites/create", { method: "POST", body: formData, credentials: "same-origin" }); if (response.ok) { const data = await response.json(); successDiv.innerHTML = `
Share this invite URL with the person you want to invite:
This invite expires in ${hours} hours.
`; successDiv.classList.remove("hidden"); errorDiv.classList.add("hidden"); // Refresh the page after a short delay to show the new invite setTimeout(() => window.location.reload(), 1000); } else { const text = await response.text(); errorDiv.textContent = text || "Failed to create invite"; errorDiv.classList.remove("hidden"); successDiv.classList.add("hidden"); } } catch (error) { errorDiv.textContent = error.message || "Network error. Please try again."; errorDiv.classList.remove("hidden"); successDiv.classList.add("hidden"); } }); // Handle copy buttons document.querySelectorAll(".copy-btn").forEach(btn => { btn.addEventListener("click", async () => { const inviteUrl = btn.dataset.inviteUrl; // Helper function to show feedback const showFeedback = (message, isSuccess = true) => { const originalText = btn.textContent; btn.textContent = message; btn.classList.remove("bg-ctp-blue", "hover:bg-ctp-sapphire"); if (isSuccess) { btn.classList.add("bg-ctp-green"); } else { btn.classList.add("bg-ctp-red"); } setTimeout(() => { btn.textContent = originalText; if (isSuccess) { btn.classList.remove("bg-ctp-green"); } else { btn.classList.remove("bg-ctp-red"); } btn.classList.add("bg-ctp-blue", "hover:bg-ctp-sapphire"); }, 2000); }; // Try modern clipboard API first if (navigator.clipboard && navigator.clipboard.writeText) { try { await navigator.clipboard.writeText(inviteUrl); showFeedback("Copied!"); return; } catch (err) { console.warn('Clipboard API failed, trying fallback:', err); } } // Fallback for older browsers or when clipboard API is not available try { const textArea = document.createElement("textarea"); textArea.value = inviteUrl; textArea.style.position = "fixed"; textArea.style.left = "-999999px"; textArea.style.top = "-999999px"; document.body.appendChild(textArea); textArea.focus(); textArea.select(); const successful = document.execCommand("copy"); document.body.removeChild(textArea); if (successful) { showFeedback("Copied!"); } else { showFeedback("Copy failed", false); } } catch (fallbackErr) { console.error('All copy methods failed:', fallbackErr); showFeedback("Copy failed", false); } }); }); // Handle discard buttons document.querySelectorAll(".discard-btn").forEach(btn => { btn.addEventListener("click", async () => { if (!confirm("Are you sure you want to revoke this invitation? This action cannot be undone.")) { return; } const token = btn.dataset.token; try { const formData = new FormData(); formData.append("token", token); const response = await fetch("/api/invites/revoke", { method: "POST", body: formData, credentials: "same-origin" }); if (response.ok) { // Remove the row or reload the page window.location.reload(); } else { const text = await response.text(); alert("Failed to revoke invite: " + (text || "Unknown error")); } } catch (error) { alert(error.message || "Network error. Please try again."); } }); }); } templ Invites() { if !IsLoggedIn(ctx) { @layout("Unauthorized") { @components.Header(nil) @components.Main() {You must be logged in to manage invitations.
} } } else { {{ user := GetUser(ctx) }} @layout("User Invitations - Pogo") { @components.Header(user) @components.Main() {| Token | Created | Expires | Status | Used By | Actions |
|---|---|---|---|---|---|
| { tokenDisplay } | { invite.CreatedAt.Time.Format("Jan 2, 2006 15:04") } | { invite.ExpiresAt.Time.Format("Jan 2, 2006 15:04") } | { status } | { usedBy } |
if isActive {
|
You have not created any invitations yet.
} } else {Failed to load invitations.
}