1
0
Fork 0

Records on my fingers

⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠛⠛⠛⠋⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠙⠛⠛⠛⠿⠻⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀⠀⡀⠠⠤⠒⢂⣉⣉⣉⣑⣒⣒⠒⠒⠒⠒⠒⠒⠒⠀⠀⠐⠒⠚⠻⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⠀⠀⡠⠔⠉⣀⠔⠒⠉⣀⣀⠀⠀⠀⣀⡀⠈⠉⠑⠒⠒⠒⠒⠒⠈⠉⠉⠉⠁⠂⠀⠈⠙⢿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠔⠁⠠⠖⠡⠔⠊⠀⠀⠀⠀⠀⠀⠀⠐⡄⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠉⠲⢄⠀⠀⠀⠈⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀⠀⠀⠊⠀⢀⣀⣤⣤⣤⣤⣀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠜⠀⠀⠀⠀⣀⡀⠀⠈⠃⠀⠀⠀⠸⣿⣿⣿⣿
⣿⣿⣿⣿⡿⠥⠐⠂⠀⠀⠀⠀⡄⠀⠰⢺⣿⣿⣿⣿⣿⣟⠀⠈⠐⢤⠀⠀⠀⠀⠀⠀⢀⣠⣶⣾⣯⠀⠀⠉⠂⠀⠠⠤⢄⣀⠙⢿⣿⣿
⣿⡿⠋⠡⠐⠈⣉⠭⠤⠤⢄⡀⠈⠀⠈⠁⠉⠁⡠⠀⠀⠀⠉⠐⠠⠔⠀⠀⠀⠀⠀⠲⣿⠿⠛⠛⠓⠒⠂⠀⠀⠀⠀⠀⠀⠠⡉⢢⠙⣿
⣿⠀⢀⠁⠀⠊⠀⠀⠀⠀⠀⠈⠁⠒⠂⠀⠒⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⢀⣀⡠⠔⠒⠒⠂⠀⠈⠀⡇⣿
⣿⠀⢸⠀⠀⠀⢀⣀⡠⠋⠓⠤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠀⠀⠀⠀⠀⠈⠢⠤⡀⠀⠀⠀⠀⠀⠀⢠⠀⠀⠀⡠⠀⡇⣿
⣿⡀⠘⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠈⠑⡦⢄⣀⠀⠀⠐⠒⠁⢸⠀⠀⠠⠒⠄⠀⠀⠀⠀⠀⢀⠇⠀⣀⡀⠀⠀⢀⢾⡆⠀⠈⡀⠎⣸⣿
⣿⣿⣄⡈⠢⠀⠀⠀⠀⠘⣶⣄⡀⠀⠀⡇⠀⠀⠈⠉⠒⠢⡤⣀⡀⠀⠀⠀⠀⠀⠐⠦⠤⠒⠁⠀⠀⠀⠀⣀⢴⠁⠀⢷⠀⠀⠀⢰⣿⣿
⣿⣿⣿⣿⣇⠂⠀⠀⠀⠀⠈⢂⠀⠈⠹⡧⣀⠀⠀⠀⠀⠀⡇⠀⠀⠉⠉⠉⢱⠒⠒⠒⠒⢖⠒⠒⠂⠙⠏⠀⠘⡀⠀⢸⠀⠀⠀⣿⣿⣿
⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠑⠄⠰⠀⠀⠁⠐⠲⣤⣴⣄⡀⠀⠀⠀⠀⢸⠀⠀⠀⠀⢸⠀⠀⠀⠀⢠⠀⣠⣷⣶⣿⠀⠀⢰⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠁⢀⠀⠀⠀⠀⠀⡙⠋⠙⠓⠲⢤⣤⣷⣤⣤⣤⣤⣾⣦⣤⣤⣶⣿⣿⣿⣿⡟⢹⠀⠀⢸⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠑⠀⢄⠀⡰⠁⠀⠀⠀⠀⠀⠈⠉⠁⠈⠉⠻⠋⠉⠛⢛⠉⠉⢹⠁⢀⢇⠎⠀⠀⢸⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣀⠈⠢⢄⡉⠂⠄⡀⠀⠈⠒⠢⠄⠀⢀⣀⣀⣰⠀⠀⠀⠀⠀⠀⠀⠀⡀⠀⢀⣎⠀⠼⠊⠀⠀⠀⠘⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⡀⠉⠢⢄⡈⠑⠢⢄⡀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠁⠀⠀⢀⠀⠀⠀⠀⠀⢻⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣀⡈⠑⠢⢄⡀⠈⠑⠒⠤⠄⣀⣀⠀⠉⠉⠉⠉⠀⠀⠀⣀⡀⠤⠂⠁⠀⢀⠆⠀⠀⢸⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⣄⡀⠁⠉⠒⠂⠤⠤⣀⣀⣉⡉⠉⠉⠉⠉⢀⣀⣀⡠⠤⠒⠈⠀⠀⠀⠀⣸⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣶⣶⣤⣤⣤⣤⣀⣀⣤⣤⣤⣶⣾⣿⣿⣿⣿⣿
This commit is contained in:
Honbra 2024-11-28 16:44:49 +01:00
parent 18251d7f00
commit 22ad0a0a11
Signed by: honbra
GPG key ID: B61CC9ADABE2D952
13 changed files with 572 additions and 161 deletions

View file

@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT id, title FROM paste",
"query": "SELECT id, title, content FROM paste",
"describe": {
"columns": [
{
@ -12,15 +12,21 @@
"ordinal": 1,
"name": "title",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "content",
"type_info": "Text"
}
],
"parameters": {
"Left": []
},
"nullable": [
false,
false,
false
]
},
"hash": "218cab8328020896b78a81be345a2074ca5461affae6b7f4daa07ba6618f96aa"
"hash": "118b5224bd11d8a0e9ab6e2c3b44ec4fc98990bd7fe434966fcd2e3580901f70"
}

View file

@ -5,9 +5,10 @@ use axum::{
routing::get,
Form, Router,
};
use chrono::{DateTime, TimeZone, Utc};
use maud::{html, Markup};
use serde::Deserialize;
use sqlx::query;
use sqlx::{query, query_as};
use ulid::Ulid;
use uuid::Uuid;
@ -28,38 +29,71 @@ pub(super) fn router() -> Router<SharedState> {
const BC_PASTES: Breadcrumb = Breadcrumb::new_static("Pastes", "/admin/pastes");
// async fn show_pastes(
// State(SharedState { db, .. }): State<SharedState>,
// ) -> Result<Markup, AppError> {
// Ok(page(
// "Pastes",
// &[BC_INDEX, BC_ADMIN],
// html! {
// table class="w-full" {
// thead {
// tr {
// th { "Name" }
// th { "Created at" }
// th { "Actions" }
// }
// }
// tbody {
// @for p in query!("SELECT id, title FROM
// paste").fetch_all(&db).await? { tr {
// td { a.tl href=(format!("/p/{}",
// Ulid::from(p.id))) { (p.title)} } td {
// (dt_iso(Ulid::from(p.id).datetime())) } td
// class="w-min-content" { div class="flex
// gap-2" { a.tl href="#" { "Edit" }
// a.tl href="#" { "Delete" }
// }
// }
// }
// }
// }
// }
// },
// ))
// }
struct PasteInList {
id: Ulid,
title: String,
content: String,
timestamp: String,
}
#[derive(Template)]
#[template(path = "admin/pastes.html")]
struct ShowPastesTemplate {
pastes: Vec<PasteInList>,
}
async fn show_pastes(
State(SharedState { db, .. }): State<SharedState>,
) -> Result<Markup, AppError> {
Ok(page(
"Pastes",
&[BC_INDEX, BC_ADMIN],
html! {
table class="w-full" {
thead {
tr {
th { "Name" }
th { "Created at" }
th { "Actions" }
}
}
tbody {
@for p in query!("SELECT id, title FROM paste").fetch_all(&db).await? {
tr {
td { a.tl href=(format!("/p/{}", Ulid::from(p.id))) { (p.title)} }
td { (dt_iso(Ulid::from(p.id).datetime())) }
td class="w-min-content" {
div class="flex gap-2" {
a.tl href="#" { "Edit" }
a.tl href="#" { "Delete" }
}
}
}
}
}
}
},
))
) -> Result<ShowPastesTemplate, AppError> {
let pastes = query!("SELECT id, title, content FROM paste")
.fetch_all(&db)
.await?;
let pastes = pastes
.into_iter()
.map(|r| PasteInList {
id: r.id.into(),
title: r.title,
content: r.content,
timestamp: DateTime::from_timestamp_millis(Ulid::from(r.id).timestamp_ms() as i64)
.map(|d| d.to_rfc3339())
.unwrap_or("<invalid timestamp>".to_string()),
})
.collect();
Ok(ShowPastesTemplate { pastes })
}
#[derive(Template)]

1
static/.map Normal file
View file

@ -0,0 +1 @@
{"version":3,"sourceRoot":"","sources":["styles/tailwind/_border-radius.scss","styles/tailwind/_colors.scss","styles/tailwind/_spacing.scss","styles/_theme.scss","styles/style.scss","styles/tailwind/_text.scss"],"names":[],"mappings":"AAAA;ACAA;ACAA;AAAA;AAAA;AAOA;ACDA;EACE;;;AAGF;AACA;AACE;EACA;EACA;EACA;AAEA;EACA;EACA;EACA;AAEA;EACA;EACA;;AAEA;EAfF;AAgBI;IACA;IACA;IACA;AAEA;IACA;IACA;IACA;AAEA;IACA;IACA;;;;AClCJ;EACI;;;AAGJ;EACI;EACA;EACA;EACA;EACA,WFEY;;;AEChB;EAEI;;AAEA;EACI,WFJQ;;AEOZ;EARJ;IASQ;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA,WC7BI;ED8BJ,aCDY;;ADKpB;EACI;EACA;EACA;;;AAKJ;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAEA;AAAA;EAEI;EACA;EACA;EACA,eJ1DR;EI2DQ;EACA;EACA,WCjED;EDkEC;;AAEA;AAAA;AAAA;EAEI;EACA;;AAOZ;EAEI;EACA;EACA;EACA,eJ9EJ;EI+EI","file":"static"}

179
static/admin.css Normal file
View file

@ -0,0 +1,179 @@
/* https://github.com/tailwindlabs/tailwindcss/blob/ac6d4a6e8e9ae7ca197bf98d933ae2f205be3635/packages/tailwindcss/src/compat/default-theme.ts#L162 */
/* Tailwind palette */
/* Yes, it's that simple.
* https://tailwindcss.com/docs/customizing-spacing#default-spacing-scale
* https://github.com/tailwindlabs/tailwindcss/blob/ac6d4a6e8e9ae7ca197bf98d933ae2f205be3635/packages/tailwindcss/src/compat/default-theme.ts#L909 */
/* https://github.com/tailwindlabs/tailwindcss/blob/ac6d4a6e8e9ae7ca197bf98d933ae2f205be3635/packages/tailwindcss/src/compat/default-theme.ts#L715 */
html {
color-scheme: light dark;
}
/* These need switchable client-side */
:root {
/* Foreground */
--color-fg-base: #334155;
--color-fg-deemphasized: #475569;
--color-fg-headings: #0f172a;
/* Background */
--color-bg-base: #f1f5f9;
--color-bg-raised-1: #e2e8f0;
--color-bg-raised-2: #cbd5e1;
--color-bg-raised-3: #94a3b8;
/* Borders */
--color-bd-base: #cbd5e1;
--color-bd-highlighted-1: #64748b;
--color-bd-highlighted-2: #475569;
}
@media (prefers-color-scheme: dark) {
:root {
/* Foreground */
--color-fg-base: #cbd5e1;
--color-fg-deemphasized: #94a3b8;
--color-fg-headings: #f1f5f9;
/* Background */
--color-bg-base: #0f172a;
--color-bg-raised-1: #1e293b;
--color-bg-raised-2: #334155;
/* Borders */
--color-bd-base: #334155;
--color-bd-highlighted: #64748b;
}
}
body.admin {
width: 100%;
max-width: 64rem;
padding: 4rem 2rem;
margin: 0 auto;
display: grid;
grid-template-columns: 16rem auto;
grid-template-rows: auto auto auto;
grid-template-areas: "logo none" "sidebar main" "footer footer";
gap: 1rem;
}
body.admin > h1 {
color: var(--color-fg-headings);
font-weight: 700;
margin: 0;
font-size: 2.25rem;
grid-area: logo;
}
body.admin > aside[role=navigation] {
grid-area: sidebar;
}
body.admin > aside[role=navigation] ul {
list-style: none;
margin: unset;
padding: unset;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
body.admin > aside[role=navigation] a {
display: block;
padding: 0.75rem 1rem;
color: unset;
text-decoration: unset;
border: 1px solid var(--color-bd-base);
border-radius: 0.75rem;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-property: background-color, border-color;
background-color: unset;
cursor: pointer;
}
body.admin > aside[role=navigation] a:hover, body.admin > aside[role=navigation] a:focus-visible {
border-color: var(--color-bd-highlighted-1);
background-color: var(--color-bg-raised-1);
}
body.admin > aside[role=navigation] a.active- {
border-color: var(--color-bd-highlighted-1);
background-color: var(--color-bg-raised-1);
}
body.admin > aside[role=navigation] a.active-:hover, body.admin > aside[role=navigation] a.active-:focus-visible {
border-color: var(--color-bd-highlighted-2);
background-color: var(--color-bg-raised-2);
}
body.admin > main {
grid-area: main;
}
body.admin > footer {
grid-area: footer;
color: var(--color-fg-deemphasized);
}
body.admin-pastes main > ul {
list-style: none;
margin: unset;
padding: unset;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
body.admin-pastes main > ul li {
display: grid;
grid-template-columns: auto auto;
grid-template-rows: auto auto;
grid-template-areas: "title buttons" "timestamp buttons" "content content";
gap: 1rem;
}
body.admin-pastes main > ul li .title {
grid-area: title;
color: var(--color-fg-headings);
font-weight: 700;
margin: 0;
font-size: 1.5rem;
text-decoration: none;
}
body.admin-pastes main > ul li .title:hover, body.admin-pastes main > ul li .title:focus-visible {
text-decoration: underline;
}
body.admin-pastes main > ul li time {
grid-area: timestamp;
color: var(--color-fg-deemphasized);
}
body.admin-pastes main > ul li .action-buttons {
grid-area: buttons;
display: flex;
justify-content: end;
align-items: end;
gap: 0.5rem;
}
body.admin-pastes main > ul li .action-buttons button {
border: 1px solid var(--color-bd-base);
border-radius: 0.75rem;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-property: background-color, border-color;
background-color: var(--color-bg-raised-1);
cursor: pointer;
display: block;
padding: 0.25rem 0.75rem;
font-size: 0.875rem;
color: unset;
}
body.admin-pastes main > ul li .action-buttons button:hover, body.admin-pastes main > ul li .action-buttons button:focus-visible {
border-color: var(--color-bd-highlighted-1);
background-color: var(--color-bg-raised-2);
}
body.admin-pastes main > ul li .action-buttons button.active- {
border-color: var(--color-bd-highlighted-1);
background-color: var(--color-bg-raised-2);
}
body.admin-pastes main > ul li .action-buttons button.active-:hover, body.admin-pastes main > ul li .action-buttons button.active-:focus-visible {
border-color: var(--color-bd-highlighted-2);
background-color: var(--color-bg-raised-3);
}
body.admin-pastes main > ul li .content {
grid-area: content;
border: 1px solid var(--color-bd-base);
border-radius: 0.75rem;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-property: background-color, border-color;
background-color: var(--color-bg-raised-1);
padding: 1rem;
margin: unset;
}
/*# sourceMappingURL=admin.css.map */

1
static/admin.css.map Normal file
View file

@ -0,0 +1 @@
{"version":3,"sourceRoot":"","sources":["../styles/tailwind/_border-radius.scss","../styles/tailwind/_colors.scss","../styles/tailwind/_spacing.scss","../styles/_theme.scss","../styles/admin.scss","../styles/tailwind/_text.scss","../styles/tailwind/_transition.scss"],"names":[],"mappings":"AAAA;ACAA;ACAA;AAAA;AAAA;AAOA;ACDA;EACI;;;AAGJ;AACA;AACI;EACA;EACA;EACA;AAEA;EACA;EACA;EACA;EACA;AAEA;EACA;EACA;EACA;;AAEA;EAjBJ;AAkBQ;IACA;IACA;IACA;AAEA;IACA;IACA;IACA;AAEA;IACA;IACA;;;;ACtCR;EACI;EACA,WFYY;EEXZ;EACA;EACA;EACA;EACA;EACA,qBACI;EAGJ;;AAEA;ED6BA;EACA,aEbe;EFeX;EAMJ,WEhDY;EDYR;;AAGJ;EACI;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;ED+BR;EACA,eHhEI;EGiEJ,qBGjEe;EHkEf,4BGxEgB;EHyEhB;EAKI;EAIA;;AAEA;EAEI;EAII;;AAIR;EACI;EAII;;AAGJ;EAEI;EAII;;ACjEhB;EACI;;AAGJ;EACI;EACA;;;AAKJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA,qBACI;EAGJ;;AAEA;EACI;ED3BZ;EACA,aEbe;EFeX;EAgBJ,WE5DY;EDsEA;;AAEA;EAEI;;AAIR;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;ED1BZ;EACA,eHhEI;EGiEJ,qBGjEe;EHkEf,4BGxEgB;EHyEhB;EAGI;EAMA;EAmCJ;EACA;EACA,WEtHW;EFuHX;;AApCI;EAEI;EAEI;;AAMR;EACI;EAEI;;AAKJ;EAEI;EAEI;;ACNR;EACI;EDhCZ;EACA,eHhEI;EGiEJ,qBGjEe;EHkEf,4BGxEgB;EHyEhB;EAGI;EC2BQ;EACA","file":"admin.css"}

View file

@ -1,3 +1,4 @@
/* https://github.com/tailwindlabs/tailwindcss/blob/ac6d4a6e8e9ae7ca197bf98d933ae2f205be3635/packages/tailwindcss/src/compat/default-theme.ts#L162 */
/* Tailwind palette */
/* Yes, it's that simple.
* https://tailwindcss.com/docs/customizing-spacing#default-spacing-scale
@ -17,9 +18,11 @@ html {
--color-bg-base: #f1f5f9;
--color-bg-raised-1: #e2e8f0;
--color-bg-raised-2: #cbd5e1;
--color-bg-raised-3: #94a3b8;
/* Borders */
--color-bd-base: #cbd5e1;
--color-bd-highlighted: #64748b;
--color-bd-highlighted-1: #64748b;
--color-bd-highlighted-2: #475569;
}
@media (prefers-color-scheme: dark) {
:root {
@ -37,7 +40,6 @@ html {
}
}
/* https://github.com/tailwindlabs/tailwindcss/blob/ac6d4a6e8e9ae7ca197bf98d933ae2f205be3635/packages/tailwindcss/src/compat/default-theme.ts#L162 */
* {
box-sizing: border-box;
}
@ -46,28 +48,31 @@ body {
font-family: Inter, "Inter Variable", sans-serif;
color: var(--color-fg-base);
background-color: var(--color-bg-base);
padding: 4rem 2rem;
margin: 0 auto;
max-width: 56rem;
}
body.wide {
body:not(.admin) {
max-width: 56rem;
padding: 4rem 2rem;
}
body:not(.admin).wide {
max-width: 72rem;
}
@media not all and (min-width: var(--max-width-lg)) {
body {
body:not(.admin) {
padding: 2rem;
}
}
body header {
body:not(.admin) header {
margin-bottom: 2rem;
}
body header h1 {
body:not(.admin) header h1 {
margin: 0;
color: var(--color-fg-headings);
font-size: 1.875rem;
font-weight: 800;
}
body footer {
body:not(.admin) footer {
color: var(--color-fg-deemphasized);
margin-top: 2rem;
text-align: center;
@ -108,35 +113,4 @@ body.paste main pre {
margin: 0;
}
body.admin-pastes main form input[type=text],
body.admin-pastes main form textarea,
body.admin-pastes main form input[type=submit] {
padding: 0.5rem 0.75rem;
border-radius: 0.5rem;
background-color: var(--color-bg-raised-1);
border: 1px solid var(--color-bd-base);
font-size: inherit;
}
body.admin-pastes main form input[type=text]:hover, body.admin-pastes main form input[type=text]:focus-visible,
body.admin-pastes main form textarea:hover,
body.admin-pastes main form textarea:focus-visible,
body.admin-pastes main form input[type=submit]:hover,
body.admin-pastes main form input[type=submit]:focus-visible {
background-color: var(--color-bg-raised-2);
border-color: var(--color-bd-highlighted);
}
body.admin-pastes main form input[type=text],
body.admin-pastes main form textarea {
width: 100%;
margin-bottom: 1rem;
}
body.admin-pastes main form textarea {
min-height: 8rem;
}
body.admin-pastes main form input[type=submit] {
cursor: pointer;
margin-left: auto;
display: block;
}
/*# sourceMappingURL=style.css.map */

View file

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../styles/tailwind/_colors.scss","../styles/tailwind/_spacing.scss","../styles/_theme.scss","../styles/tailwind/_border-radius.scss","../styles/style.scss","../styles/tailwind/_text.scss"],"names":[],"mappings":"AAAA;ACAA;AAAA;AAAA;AAOA;ACHA;EACE;;;AAGF;AACA;AACE;EACA;EACA;EACA;AAEA;EACA;EACA;EACA;AAEA;EACA;EACA;;AAEA;EAfF;AAgBI;IACA;IACA;IACA;AAEA;IACA;IACA;IACA;AAEA;IACA;IACA;;;;ACrCJ;ACKA;EACI;;;AAGJ;EAEI;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI,WHDQ;;AGIZ;EAbJ;IAcQ;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA,WC1BI;ED2BJ,aCEY;;ADEpB;EACI;EACA;EACA;;;AAKJ;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAEA;AAAA;EAEI;EACA;EACA;EACA,eDvDR;ECwDQ;EACA;EACA,WC9DD;ED+DC;;AAEA;AAAA;AAAA;EAEI;EACA;;AAOZ;EAEI;EACA;EACA;EACA,eD3EJ;EC4EI;;;AAOJ;AAAA;AAAA;EAGI;EACA,eDxFJ;ECyFI;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAEI;EACA;;AAIR;AAAA;EAEI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA","file":"style.css"}
{"version":3,"sourceRoot":"","sources":["../styles/tailwind/_border-radius.scss","../styles/tailwind/_colors.scss","../styles/tailwind/_spacing.scss","../styles/_theme.scss","../styles/style.scss","../styles/tailwind/_text.scss"],"names":[],"mappings":"AAAA;ACAA;ACAA;AAAA;AAAA;AAOA;ACDA;EACI;;;AAGJ;AACA;AACI;EACA;EACA;EACA;AAEA;EACA;EACA;EACA;EACA;AAEA;EACA;EACA;EACA;;AAEA;EAjBJ;AAkBQ;IACA;IACA;IACA;AAEA;IACA;IACA;IACA;AAEA;IACA;IACA;;;;ACpCR;EACI;;;AAGJ;EACI;EACA;EACA;EACA;;;AAGJ;EAEI,WFFY;EEGZ;;AAEA;EACI,WFJQ;;AEOZ;EATJ;IAUQ;;;AAGJ;EACI;;AAEA;EACI;EACA;EACA,WC7BI;ED8BJ,aCDY;;ADKpB;EACI;EACA;EACA;;;AAKJ;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAEA;AAAA;EAEI;EACA;EACA;EACA,eJ1DR;EI2DQ;EACA;EACA,WCjED;EDkEC;;AAEA;AAAA;AAAA;EAEI;EACA;;AAOZ;EAEI;EACA;EACA;EACA,eJ9EJ;EI+EI","file":"style.css"}

View file

@ -1,5 +1,7 @@
@use "tailwind/border-radius";
@use "tailwind/colors";
@use "tailwind/spacing";
@use "tailwind/transition";
@use "tailwind/text";
html {
@ -17,10 +19,12 @@ html {
--color-bg-base: #{colors.$slate-100};
--color-bg-raised-1: #{colors.$slate-200};
--color-bg-raised-2: #{colors.$slate-300};
--color-bg-raised-3: #{colors.$slate-400};
/* Borders */
--color-bd-base: #{colors.$slate-300};
--color-bd-highlighted: #{colors.$slate-500};
--color-bd-highlighted-1: #{colors.$slate-500};
--color-bd-highlighted-2: #{colors.$slate-600};
@media (prefers-color-scheme: dark) {
/* Foreground */
@ -41,6 +45,7 @@ html {
@mixin heading($disable-margin: false) {
color: var(--color-fg-headings);
font-weight: text.$font-weight-bold;
@if $disable-margin {
margin: 0;
}
@ -49,5 +54,69 @@ html {
@mixin heading2($disable-margin: false) {
@include heading($disable-margin);
font-size: text.$font-size-4xl;
font-weight: text.$font-weight-bold;
}
@mixin heading3($disable-margin: false) {
@include heading($disable-margin);
font-size: text.$font-size-3xl;
}
@mixin heading4($disable-margin: false) {
@include heading($disable-margin);
font-size: text.$font-size-2xl;
}
@mixin surface($is-interactive: false, $is-raised: false) {
border: 1px solid var(--color-bd-base);
border-radius: border-radius.$br-xl;
transition-duration: transition.$duration-default;
transition-timing-function: transition.$timing-fn-default;
transition-property: background-color, border-color;
@if $is-raised {
background-color: var(--color-bg-raised-1);
} @else {
background-color: unset;
}
@if $is-interactive {
cursor: pointer;
&:hover,
&:focus-visible {
border-color: var(--color-bd-highlighted-1);
@if $is-raised {
background-color: var(--color-bg-raised-2);
} @else {
background-color: var(--color-bg-raised-1);
}
}
&.active- {
border-color: var(--color-bd-highlighted-1);
@if $is-raised {
background-color: var(--color-bg-raised-2);
} @else {
background-color: var(--color-bg-raised-1);
}
&:hover,
&:focus-visible {
border-color: var(--color-bd-highlighted-2);
@if $is-raised {
background-color: var(--color-bg-raised-3);
} @else {
background-color: var(--color-bg-raised-2);
}
}
}
}
}
@mixin button($is-raised: false) {
@include surface(true, $is-raised);
display: block;
padding: spacing.s(1) spacing.s(3);
font-size: text.$font-size-sm;
color: unset;
}

109
styles/admin.scss Normal file
View file

@ -0,0 +1,109 @@
@use "theme";
@use "tailwind/spacing";
body.admin {
width: 100%;
max-width: spacing.$max-width-5xl;
padding: spacing.s(16) spacing.s(8);
margin: 0 auto;
display: grid;
grid-template-columns: spacing.s(64) auto;
grid-template-rows: auto auto auto;
grid-template-areas:
"logo none"
"sidebar main"
"footer footer";
gap: spacing.s(4);
> h1 {
@include theme.heading2(true);
grid-area: logo;
}
> aside[role="navigation"] {
grid-area: sidebar;
ul {
list-style: none;
margin: unset;
padding: unset;
display: flex;
flex-direction: column;
gap: spacing.s(2);
}
a {
display: block;
padding: spacing.s(3) spacing.s(4);
color: unset;
text-decoration: unset;
@include theme.surface(true, false);
}
}
> main {
grid-area: main;
}
> footer {
grid-area: footer;
color: var(--color-fg-deemphasized);
}
}
body.admin-pastes {
main > ul {
list-style: none;
margin: unset;
padding: unset;
display: flex;
flex-direction: column;
gap: spacing.s(6);
li {
display: grid;
grid-template-columns: auto auto;
grid-template-rows: auto auto;
grid-template-areas:
"title buttons"
"timestamp buttons"
"content content";
gap: spacing.s(4);
.title {
grid-area: title;
@include theme.heading4(true);
text-decoration: none;
&:hover,
&:focus-visible {
text-decoration: underline;
}
}
time {
grid-area: timestamp;
color: var(--color-fg-deemphasized);
}
.action-buttons {
grid-area: buttons;
display: flex;
justify-content: end;
align-items: end;
gap: spacing.s(2);
button {
@include theme.button(true);
}
}
.content {
grid-area: content;
@include theme.surface(false, true);
padding: spacing.s(4);
margin: unset;
}
}
}
}

View file

@ -8,13 +8,16 @@
}
body {
// @apply flex flex-col gap-8 px-4 py-16 mx-auto max-w-4xl bg-slate-900 text-fg-base max-lg:py-8;
font-family: Inter, "Inter Variable", sans-serif;
color: var(--color-fg-base);
background-color: var(--color-bg-base);
padding: spacing.s(16) spacing.s(8);
margin: 0 auto;
}
body:not(.admin) {
// @apply flex flex-col gap-8 px-4 py-16 mx-auto max-w-4xl bg-slate-900 text-fg-base max-lg:py-8;
max-width: spacing.$max-width-4xl;
padding: spacing.s(16) spacing.s(8);
&.wide {
max-width: spacing.$max-width-6xl;
@ -85,41 +88,41 @@ body.paste {
}
}
body.admin-pastes {
main form {
input[type="text"],
textarea,
input[type="submit"] {
padding: spacing.s(2) spacing.s(3);
border-radius: border-radius.$br-lg;
background-color: var(--color-bg-raised-1);
border: 1px solid var(--color-bd-base);
font-size: inherit;
&:hover,
&:focus-visible {
background-color: var(--color-bg-raised-2);
border-color: var(--color-bd-highlighted);
}
}
input[type="text"],
textarea {
width: 100%;
margin-bottom: spacing.s(4);
}
textarea {
min-height: spacing.s(32);
}
input[type="submit"] {
cursor: pointer;
margin-left: auto;
display: block;
}
}
}
// body.admin-pastes {
// main form {
// input[type="text"],
// textarea,
// input[type="submit"] {
// padding: spacing.s(2) spacing.s(3);
// border-radius: border-radius.$br-lg;
// background-color: var(--color-bg-raised-1);
// border: 1px solid var(--color-bd-base);
// font-size: inherit;
//
// &:hover,
// &:focus-visible {
// background-color: var(--color-bg-raised-2);
// border-color: var(--color-bd-highlighted);
// }
// }
//
// input[type="text"],
// textarea {
// width: 100%;
// margin-bottom: spacing.s(4);
// }
//
// textarea {
// min-height: spacing.s(32);
// }
//
// input[type="submit"] {
// cursor: pointer;
// margin-left: auto;
// display: block;
// }
// }
// }
a.tl {
// @apply underline hover:no-underline hover:text-white focus-visible:no-underline focus-visible:text-white;

View file

@ -0,0 +1,7 @@
$timing-fn-default: cubic-bezier(0.4, 0, 0.2, 1);
$timing-fn-linear: linear;
$timing-fn-in: cubic-bezier(0.4, 0, 1, 1);
$timing-fn-out: cubic-bezier(0, 0, 0.2, 1);
$timing-fn-in-out: cubic-bezier(0.4, 0, 0.2, 1);
$duration-default: 150ms;

View file

@ -1,12 +1,31 @@
{% extends "../base.html" %}
{% block bodyClass %}admin{% endblock %}
{% block header %}
<h1>{{title}}</h1>
{% endblock %}
{% block main %}
{{main}}
{% call super() %}
{% endblock %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{% block title %}{{title}}{% endblock %} | NCPN</title>
<link rel="stylesheet" href="/style.css" />
<link rel="stylesheet" href="/admin.css" />
<script src="/script.js" defer></script>
<noscript>
<style>
.jsonly {
display: none;
}
</style>
</noscript>
{% block head %}{% endblock %}
</head>
<body class="admin {% block bodyClass %}{% endblock %}">
<h1>NCPN Admin</h1>
<aside role="navigation">
<ul>
<li><a href="/admin/files">Files</a></li>
<li><a href="/admin/links">Links</a></li>
<li><a class="active" href="/admin/pastes">Pastes</a></li>
</ul>
</aside>
<main>{% block main %}{% endblock %}</main>
<footer>Running NCPN v?.??</footer>
</body>
</html>

View file

@ -1,12 +1,21 @@
{% extends "../base.html" %}
{% extends "base.html" %}
{% block title %}Pastes{% endblock %}
{% block bodyClass %}admin-pastes{% endblock %}
{% block header %}
<h1>Pastes</h1>
{% endblock %}
{% block main %}
<ul>
{% for paste in pastes %}
<li>
<a class="title" href="/p/{{ paste.id }}">{{ paste.title|e }}</a>
<time datetime="{{ paste.timestamp }}">{{ paste.timestamp }}</time>
<div class="action-buttons">
<button>Edit</button>
<button>Delete</button>
</div>
<pre class="content">{{ paste.content|e }}</pre>
</li>
{% endfor %}
</ul>
{% call super() %}
{% endblock %}