diff --git a/docs/openapi.yml b/docs/openapi.yml index 675cbc071d..b6e5f59ef7 100644 --- a/docs/openapi.yml +++ b/docs/openapi.yml @@ -1313,21 +1313,21 @@ paths: type: string format: date-time example: '2024-01-01' - description: "Post open timestamp filter: `open_time__`. Supported operators: `gt`, `gte`, `lt`, `lte`." + description: "Post open timestamp filter: `open_time__`. Supported operators: `gt`, `gte`, `lt`, `lte`. For example, to query everything opened after 2024-01-01, use `open_time__gt=2024-01-01`. For everything opened on or before that date, use `open_time__lte=2024-01-01`." - in: query name: published_at__gt schema: type: string format: date-time example: '2024-01-01' - description: "Post publication timestamp filter: `published_at__`. Supported operators: `gt`, `gte`, `lt`, `lte`." + description: "Post publication timestamp filter: `published_at__`. Supported operators: `gt`, `gte`, `lt`, `lte`. For example, to query everything published after 2024-01-01, use `published_at__gt=2024-01-01`. For everything published on or before that date, use `published_at__lte=2024-01-01`." - in: query name: scheduled_resolve_time__gt schema: type: string format: date-time example: '2024-01-01' - description: "Scheduled resolution timestamp filter: `scheduled_resolve_time__`. Supported operators: `gt`, `gte`, `lt`, `lte`." + description: "Scheduled resolution timestamp filter: `scheduled_resolve_time__`. Supported operators: `gt`, `gte`, `lt`, `lte`. For example, to query everything scheduled to resolve after 2024-01-01, use `scheduled_resolve_time__gt=2024-01-01`. For everything scheduled to resolve on or before that date, use `scheduled_resolve_time__lte=2024-01-01`." - in: query name: forecast_type schema: diff --git a/templates/swagger-ui.html b/templates/swagger-ui.html index 9077994a2a..98862e1cf2 100644 --- a/templates/swagger-ui.html +++ b/templates/swagger-ui.html @@ -5,6 +5,28 @@ +
@@ -46,6 +68,69 @@ ], plugins: [InjectServerPlugin] }) + + // Add a copy-to-clipboard button next to each "Request URL" heading rendered + // by Swagger UI after "Try it out". Swagger UI v3 does not ship one. + function addCopyButtonToRequestUrl(heading) { + if (heading.dataset.metacCopyButtonAdded === "true") return; + heading.dataset.metacCopyButtonAdded = "true"; + + const urlEl = heading.nextElementSibling; + if (!urlEl) return; + + const button = document.createElement("button"); + button.type = "button"; + button.className = "metac-copy-request-url-btn"; + button.textContent = "Copy"; + button.addEventListener("click", async () => { + const text = (urlEl.textContent || "").trim(); + try { + if (navigator.clipboard && navigator.clipboard.writeText) { + await navigator.clipboard.writeText(text); + } else { + const ta = document.createElement("textarea"); + ta.value = text; + ta.style.position = "fixed"; + ta.style.opacity = "0"; + document.body.appendChild(ta); + ta.select(); + document.execCommand("copy"); + document.body.removeChild(ta); + } + button.textContent = "Copied!"; + button.classList.add("copied"); + setTimeout(() => { + button.textContent = "Copy"; + button.classList.remove("copied"); + }, 1500); + } catch (e) { + button.textContent = "Failed"; + setTimeout(() => { + button.textContent = "Copy"; + }, 1500); + } + }); + heading.appendChild(button); + } + + function scanForRequestUrls(root) { + const headings = (root || document).querySelectorAll(".request-url h4"); + headings.forEach(addCopyButtonToRequestUrl); + } + + const observer = new MutationObserver((mutations) => { + for (const m of mutations) { + for (const node of m.addedNodes) { + if (node.nodeType !== 1) continue; + if (node.matches && node.matches(".request-url")) { + scanForRequestUrls(node.parentNode); + } else { + scanForRequestUrls(node); + } + } + } + }); + observer.observe(document.body, { childList: true, subtree: true }); - \ No newline at end of file +