diff options
| -rw-r--r-- | src/html.c | 140 |
1 files changed, 59 insertions, 81 deletions
@@ -19,6 +19,16 @@ static void emit_stylesheet(FILE *f) { " --yellow: #f0a04a;\n" " --red: #f06060;\n" " --purple: #c084fc;\n" + " --green-bg: #0a2e1a;\n" + " --green-bor: #1a5c34;\n" + " --yellow-bg: #2e200a;\n" + " --yellow-bor: #5c400e;\n" + " --red-bg: #2e0a0a;\n" + " --red-bor: #5c1a1a;\n" + " --purple-bg: #1e0a2e;\n" + " --purple-bor: #5c1a8c;\n" + " --sky: #7dd3fc;\n" + " --pink: #f9a8d4;\n" " --mono: 'Courier New', 'Lucida Console', monospace;\n" "}\n" "body {\n" @@ -42,10 +52,9 @@ static void emit_stylesheet(FILE *f) { " top: 0;\n" " z-index: 1;\n" "}\n" - "header b { color: var(--green); letter-spacing: 2px; }\n" - "header small { color: var(--dim); font-size: 12px; font-family: var(--mono); }\n" - "header a { color: var(--dim); font-size: 12px; }\n" - "header a:hover { color: var(--green); }\n" + ".logo { color: var(--green); letter-spacing: 2px; font-weight: bold; }\n" + ".nav-link { color: var(--dim); font-size: 12px; text-decoration: none; }\n" + ".nav-link:hover { color: var(--green); }\n" "header form { display: inline; }\n" "button.logout {\n" " border: none;\n" @@ -79,25 +88,14 @@ static void emit_stylesheet(FILE *f) { " gap: 14px;\n" "}\n" ".login-page h1 { color: var(--green); letter-spacing: 3px; text-align: center; font-size: 20px; }\n" - ".login-page label { display: block; color: var(--dim); font-size: 11px; letter-spacing: 1px; text-transform: uppercase; margin-bottom: 5px; }\n" - ".login-page input {\n" - " width: 100%%;\n" - " background: var(--bg);\n" - " border: 1px solid var(--bor);\n" - " color: var(--hi);\n" - " font-family: var(--mono);\n" - " font-size: 16px;\n" - " padding: 9px 10px;\n" - " outline: none;\n" - "}\n" - ".login-page input:focus { border-color: var(--green); }\n" - ".login-page .error {\n" - " color: var(--red);\n" - " background: #2e0a0a;\n" - " border: 1px solid #5c1a1a;\n" - " padding: 7px 10px;\n" - " font-size: 12px;\n" - "}\n" + "/* FORM COMPONENTS */\n" + ".label { display: block; color: var(--dim); font-size: 11px; letter-spacing: 1px; text-transform: uppercase; margin-bottom: 5px; }\n" + ".input { width: 100%%; background: var(--bg); border: 1px solid var(--bor); color: var(--hi); font-family: var(--mono); font-size: 16px; padding: 9px 10px; outline: none; }\n" + ".input:focus { border-color: var(--green); }\n" + "/* ALERT COMPONENT */\n" + ".alert { padding: 7px 10px; font-size: 12px; border: 1px solid; }\n" + ".alert.error { color: var(--red); background: var(--red-bg); border-color: var(--red-bor); }\n" + ".alert.warning { color: var(--purple); background: var(--purple-bg); border-color: var(--purple-bor); margin-top: 10px; }\n" "/* SHARED BUTTON */\n" "button {\n" " font-family: var(--mono);\n" @@ -156,11 +154,12 @@ static void emit_stylesheet(FILE *f) { " text-decoration: none;\n" "}\n" ".clients > a:hover { background: var(--sur); }\n" - ".clients > a > :first-child { color: var(--hi); }\n" - ".clients > a > :last-child { text-align: right; }\n" - ".clients > a.stale > :first-child { border-left: 2px solid var(--purple); padding-left: 8px; }\n" - ".clients > a.stale > :nth-child(3) { color: var(--purple); }\n" - ".clients > a > code { font-size: 12px; color: var(--dim); letter-spacing: 1px; }\n" + ".client-name { color: var(--hi); }\n" + ".client-secret { font-size: 12px; color: var(--dim); letter-spacing: 1px; }\n" + ".client-action { text-align: right; color: var(--dim); font-size: 12px; }\n" + ".clients > a:hover .client-action { color: var(--green); }\n" + ".clients > a.stale .client-name { border-left: 2px solid var(--purple); padding-left: 8px; }\n" + ".clients > a.stale .client-time { color: var(--purple); }\n" "@media (max-width: 580px) {\n" " .clients > .header { display: none; }\n" " .clients > .row {\n" @@ -168,20 +167,20 @@ static void emit_stylesheet(FILE *f) { " grid-template-rows: auto auto;\n" " padding: 13px 14px;\n" " }\n" - " .clients > a > :nth-child(1) { grid-column: 1; grid-row: 1; }\n" - " .clients > a > :nth-child(2) { display: none; }\n" - " .clients > a > :nth-child(3) { grid-column: 1; grid-row: 2; font-size: 11px; color: var(--dim); }\n" - " .clients > a > :nth-child(4) { grid-column: 2; grid-row: 1 / 3; align-self: center; }\n" - " .clients > a > :nth-child(5) { display: none; }\n" + " .client-name { grid-column: 1; grid-row: 1; }\n" + " .client-secret { display: none; }\n" + " .client-time { grid-column: 1; grid-row: 2; font-size: 11px; color: var(--dim); }\n" + " .client-badge { grid-column: 2; grid-row: 1 / 3; align-self: center; }\n" + " .client-action { display: none; }\n" " .clients > a.stale { border-left: 3px solid var(--purple); padding-left: 11px; }\n" - " .clients > a.stale > :first-child { border-left: none; padding-left: 0; }\n" + " .clients > a.stale .client-name { border-left: none; padding-left: 0; }\n" "}\n" "/* BADGES */\n" - ".badge { border: 1px solid; padding: 2px 7px; font-size: 10px; letter-spacing: 1px; justify-self: center; }" - ".badge.ok { color: var(--green); background: #0a2e1a; border-color: #1a5c34; }\n" - ".badge.run { color: var(--yellow); background: #2e200a; border-color: #5c400e; }\n" - ".badge.fail { color: var(--red); background: #2e0a0a; border-color: #5c1a1a; }\n" - ".badge.stale { color: var(--purple); background: #1e0a2e; border-color: #5c1a8c; }\n" + ".badge { border: 1px solid; padding: 2px 7px; font-size: 10px; letter-spacing: 1px; justify-self: center; }\n" + ".badge.ok { color: var(--green); background: var(--green-bg); border-color: var(--green-bor); }\n" + ".badge.run { color: var(--yellow); background: var(--yellow-bg); border-color: var(--yellow-bor); }\n" + ".badge.fail { color: var(--red); background: var(--red-bg); border-color: var(--red-bor); }\n" + ".badge.stale { color: var(--purple); background: var(--purple-bg); border-color: var(--purple-bor); }\n" "/* ADD FORM */\n" "#add-form {\n" " background: var(--sur);\n" @@ -193,19 +192,7 @@ static void emit_stylesheet(FILE *f) { " flex-direction: column;\n" "}\n" "#add-form.open { display: flex; }\n" - "#add-form label { color: var(--dim); font-size: 11px; letter-spacing: 1px; text-transform: uppercase; display: block; margin-bottom: 5px; }\n" - "#add-form input {\n" - " background: var(--bg);\n" - " border: 1px solid var(--bor);\n" - " color: var(--hi);\n" - " font-family: var(--mono);\n" - " font-size: 16px;\n" - " padding: 8px 10px;\n" - " outline: none;\n" - " width: 100%%;\n" - " max-width: 280px;\n" - "}\n" - "#add-form input:focus { border-color: var(--green); }\n" + "#add-form .input { max-width: 280px; }\n" "/* DETAIL HEADER */\n" "article {\n" " background: var(--sur);\n" @@ -216,14 +203,6 @@ static void emit_stylesheet(FILE *f) { "article.stale { border-left: 3px solid var(--purple); }\n" "article h3 { color: var(--green); font-size: 17px; letter-spacing: 1px; margin-bottom: 4px; }\n" "article p { color: var(--dim); font-size: 12px; }\n" - "article p.warning {\n" - " color: var(--purple);\n" - " background: #1e0a2e;\n" - " border: 1px solid #5c1a8c;\n" - " padding: 7px 10px;\n" - " margin-top: 10px;\n" - " font-size: 12px;\n" - "}\n" "article code {\n" " display: block;\n" " margin-top: 10px;\n" @@ -272,8 +251,8 @@ static void emit_stylesheet(FILE *f) { "details pre .cmd { color: var(--yellow); }\n" "details pre .flag { color: var(--dim); }\n" "details pre .url { color: var(--green); }\n" - "details pre .key { color: #7dd3fc; }\n" - "details pre .val { color: #f9a8d4; }\n" + "details pre .key { color: var(--sky); }\n" + "details pre .val { color: var(--pink); }\n" "details pre .secret { color: var(--purple); }\n" "details pre button {\n" " position: absolute;\n" @@ -356,8 +335,8 @@ char *html_render_clients_page(const char *host, const struct ListClientResult * "</head>\n" "<body>\n" " <header>\n" - " <b>BorgFlag</b>\n" - " <small><form method=\"POST\" action=\"/logout\"><button type=\"submit\" class=\"logout\">Sign out</button></form></small>\n" + " <span class=\"logo\">BorgFlag</span>\n" + " <form method=\"POST\" action=\"/logout\"><button type=\"submit\" class=\"logout\">Sign out</button></form>\n" " </header>\n" " <main>\n" " <h2>\n" @@ -374,8 +353,8 @@ char *html_render_clients_page(const char *host, const struct ListClientResult * " </h2>\n" " <form id=\"add-form\" method=\"POST\" action=\"/clients\">\n" " <div>\n" - " <label>Name</label>\n" - " <input type=\"text\" name=\"name\" maxlength=\"31\" placeholder=\"prod-web-02\" required>\n" + " <label class=\"label\">Name</label>\n" + " <input class=\"input\" type=\"text\" name=\"name\" maxlength=\"31\" placeholder=\"prod-web-02\" required>\n" " </div>\n" " <button type=\"submit\">Create</button>\n" " </form>\n" @@ -395,11 +374,11 @@ char *html_render_clients_page(const char *host, const struct ListClientResult * fprintf(f, " <a href=\"/client/%ld\" class=\"row %s\">\n" - " <span>%s</span>\n" - " <code>%s</code>\n" - " <span>%s</span>\n" - " <b class=\"badge %s\">%s</b>\n" - " <button onclick=\"event.stopPropagation();window.location='/client/%ld'\">View →</button>\n" + " <span class=\"client-name\">%s</span>\n" + " <code class=\"client-secret\">%s</code>\n" + " <span class=\"client-time\">%s</span>\n" + " <b class=\"badge client-badge %s\">%s</b>\n" + " <span class=\"client-action\">View →</span>\n" " </a>\n", result->clients[i].id, result->clients[i].is_stale ? "stale" : "", @@ -407,8 +386,7 @@ char *html_render_clients_page(const char *host, const struct ListClientResult * masked_secret, result->clients[i].last_backup.tv_sec > 0.0 ? format_time(result->clients[i].last_backup).buf : "-", status_to_badge_class(result->clients[i].status), - status_to_display(result->clients[i].status), - result->clients[i].id + status_to_display(result->clients[i].status) ); } @@ -455,8 +433,8 @@ char *html_render_client_detail_page(const char *host, const struct GetClientOnl "</head>\n" "<body>\n" " <header>\n" - " <b>BorgFlag</b>\n" - " <small><form method=\"POST\" action=\"/logout\"><button type=\"submit\" class=\"logout\">Sign out</button></form></small>\n" + " <span class=\"logo\">BorgFlag</span>\n" + " <form method=\"POST\" action=\"/logout\"><button type=\"submit\" class=\"logout\">Sign out</button></form>\n" " </header>\n" " <main>\n" " <a href=\"/clients\">← Back to clients</a>\n" @@ -472,7 +450,7 @@ char *html_render_client_detail_page(const char *host, const struct GetClientOnl if (is_stale) { fprintf(f, - " <p class=\"warning\">Warning: Last backup was more than 24 hours ago. Expected every 24 hours.</p>\n" + " <p class=\"alert warning\">Warning: Last backup was more than 24 hours ago. Expected every 24 hours.</p>\n" ); } @@ -560,17 +538,17 @@ char *html_render_login_page(const char *error_msg, size_t *out_len) { " <h1>BorgFlag</h1>\n"); if (error_msg) { - fprintf(f, " <div class=\"error\">%s</div>\n", error_msg); + fprintf(f, " <div class=\"alert error\">%s</div>\n", error_msg); } fprintf(f, " <div>\n" - " <label>Username</label>\n" - " <input type=\"text\" name=\"username\" autocomplete=\"username\" required>\n" + " <label class=\"label\">Username</label>\n" + " <input class=\"input\" type=\"text\" name=\"username\" autocomplete=\"username\" required>\n" " </div>\n" " <div>\n" - " <label>Password</label>\n" - " <input type=\"password\" name=\"password\" autocomplete=\"current-password\" required>\n" + " <label class=\"label\">Password</label>\n" + " <input class=\"input\" type=\"password\" name=\"password\" autocomplete=\"current-password\" required>\n" " </div>\n" " <button type=\"submit\">Sign In</button>\n" " </form>\n" |
