diff options
-rw-r--r-- | frontend/helper.ts | 4 | ||||
-rw-r--r-- | frontend/main.ts | 10 | ||||
-rw-r--r-- | frontend/search.ts | 8 | ||||
-rw-r--r-- | frontend/start.ts | 3 | ||||
-rw-r--r-- | frontend/style.sass | 8 | ||||
-rw-r--r-- | frontend/submit.ts | 61 | ||||
-rw-r--r-- | frontend/ui.ts | 2 |
7 files changed, 81 insertions, 15 deletions
diff --git a/frontend/helper.ts b/frontend/helper.ts index f47d131..2ecfc35 100644 --- a/frontend/helper.ts +++ b/frontend/helper.ts @@ -5,6 +5,8 @@ interface Opts<E> { id?: string, src?: string, for?: string, + type?: string, + href?: string, onclick?: (e: E) => void, onchange?: (e: E) => void, } @@ -14,6 +16,8 @@ function apply_opts<E extends HTMLElement>(e: E, o: Opts<E>) { if (o.onclick) e.onclick = () => o.onclick!(e) if (o.onchange) e.onchange = () => o.onchange!(e) if (o.for) (e as unknown as HTMLLabelElement).htmlFor = o.for + if (o.type && e instanceof HTMLInputElement) e.type = o.type + if (o.href && e instanceof HTMLAnchorElement) e.href = o.href; if (typeof o?.class == "string") e.classList.add(o.class) if (typeof o?.class == "object") e.classList.add(...o.class) } diff --git a/frontend/main.ts b/frontend/main.ts index c8f134a..6b92616 100644 --- a/frontend/main.ts +++ b/frontend/main.ts @@ -1,6 +1,6 @@ /// <reference lib="dom" /> -import { bangs, load_bangs, process_query } from "./query.ts"; -import { add_page_content, status } from "./ui.ts" +import { load_bangs, process_query } from "./query.ts"; +import { add_page_content } from "./ui.ts" load_bangs() @@ -17,12 +17,6 @@ function process_url() { } else { add_page_content(engine) } - bangs.then(bangs => { - if (!bangs[engine.toLowerCase()]) { - status("error", "Engine does not exist") - window.location.hash = "#" - } - }) } else { add_page_content() } diff --git a/frontend/search.ts b/frontend/search.ts index 0c808db..374cccf 100644 --- a/frontend/search.ts +++ b/frontend/search.ts @@ -1,5 +1,6 @@ import { e } from "./helper.ts"; import { bangs, process_query } from "./query.ts"; +import { status } from "./ui.ts" export function section_info_search() { return e("section", { class: "info" }, @@ -11,6 +12,13 @@ export function section_info_search() { export function section_search(engine: string) { link_engine(engine) + bangs.then(bangs => { + if (!bangs[engine.toLowerCase()]) { + status("error", "Engine does not exist") + window.location.hash = "#" + } + }) + const heading = document.createElement("h1") heading.textContent = engine bangs.then(bangs => heading.textContent = bangs[engine]?.name ?? engine) diff --git a/frontend/start.ts b/frontend/start.ts index 1bb1cbb..d686b27 100644 --- a/frontend/start.ts +++ b/frontend/start.ts @@ -8,7 +8,8 @@ export function section_info_start() { e("p", {}, ` This application provides a way to (mostly) locally handle search bangs. First select a default engine to use, then register this page as a search in your browser - `) + `), + e("a", { href: "#~submit" }, "Propose or change a bang"), ) } diff --git a/frontend/style.sass b/frontend/style.sass index 5199a22..eac7239 100644 --- a/frontend/style.sass +++ b/frontend/style.sass @@ -20,13 +20,17 @@ h1 &.level-error color: #ff0000 - &.level-success color: #00ff00 + &.level-warn + color: #ffe600 section.info margin: 5em +section.submit + margin: 5em + section.engine-select margin: 10em ul @@ -78,7 +82,5 @@ button border: 0 cursor: pointer - - label margin-right: 1em diff --git a/frontend/submit.ts b/frontend/submit.ts index e8f696f..2b7a04a 100644 --- a/frontend/submit.ts +++ b/frontend/submit.ts @@ -1,9 +1,66 @@ import { e } from "./helper.ts"; - +import { bangs } from "./query.ts"; +import { status } from "./ui.ts"; export function section_submit() { - return e("section", {}) + let skipped_warn = false; + const submit_button = e("button", {}, "Submit") + const onchange = () => { skipped_warn = false; submit_button.textContent = "Submit" } + const bang_input = e("input", { id: "i-bang", type: "text", onchange }) + const url_input = e("input", { id: "i-url", type: "url", onchange }) + const email_input = e("input", { id: "i-email", type: "email", onchange }) + const name_input = e("input", { id: "i-name", type: "text", onchange }) + + submit_button.addEventListener("click", async () => { + const [bang, url, email, name] = [bang_input.value, url_input.value, email_input.value, name_input.value] + const w = []; + if (!url.includes("{{{s}}}")) w.push("URL does not include {{{s}}} pattern") + if ((await bangs)[bang]) w.push("Bang already exists, it will be overwritten") + if (!/^[A-Za-z0-9_-]+$/g.test(bang)) w.push("Bang has uncommon characters") + + if (w.length && !skipped_warn) { + status("warn", w.join(", ")) + setTimeout(() => { + submit_button.textContent = "Submit with warnings" + skipped_warn = true + }, 1000) + } else { + submit_bang({ bang, url, email, name }) + bang_input.disabled = true + url_input.disabled = true + email_input.disabled = true + name_input.disabled = true + } + }) + + return e("section", { class: "submit" }, + e("h1", {}, "Propose or change a bang"), + e("p", {}, ` + Existing bangs with the same name will be overwritten. + Use {{{s}}} in the URL in place of the search term. + Proposals will come into effect after being approved by an administrator. + If an email address is provided, you will be informed about the status of your proposal. + `), + e("div", {}, e("label", { for: "i-name" }, "Name"), name_input), + e("div", {}, e("label", { for: "i-bang" }, "Bang"), bang_input), + e("div", {}, e("label", { for: "i-url" }, "Url"), url_input), + e("div", {}, e("label", { for: "i-email" }, "Notification email (optional)"), email_input), + submit_button + ) } +async function submit_bang(submission: { bang: string, url: string, name: string, email: string }) { + status("info", "Submitting bang..."); + const r = await fetch(`/submitBang`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Accept": "application/json" + }, + body: JSON.stringify(submission) + }) + if (r.ok) status("success", "Submission successful") + else status("error", "Submission failed") +}
\ No newline at end of file diff --git a/frontend/ui.ts b/frontend/ui.ts index 3b223ba..aebd8f7 100644 --- a/frontend/ui.ts +++ b/frontend/ui.ts @@ -11,7 +11,7 @@ export function add_page_content(engine?: string) { } let status_el: HTMLElement -export function status(level: "error" | "info" | "success", text: string) { +export function status(level: "error" | "info" | "success" | "warn", text: string) { if (!status_el) { status_el = document.createElement("p") document.body.append(status_el) |