diff --git a/.sqlx/query-218cab8328020896b78a81be345a2074ca5461affae6b7f4daa07ba6618f96aa.json b/.sqlx/query-118b5224bd11d8a0e9ab6e2c3b44ec4fc98990bd7fe434966fcd2e3580901f70.json similarity index 59% rename from .sqlx/query-218cab8328020896b78a81be345a2074ca5461affae6b7f4daa07ba6618f96aa.json rename to .sqlx/query-118b5224bd11d8a0e9ab6e2c3b44ec4fc98990bd7fe434966fcd2e3580901f70.json index 78b779d..0de4aaf 100644 --- a/.sqlx/query-218cab8328020896b78a81be345a2074ca5461affae6b7f4daa07ba6618f96aa.json +++ b/.sqlx/query-118b5224bd11d8a0e9ab6e2c3b44ec4fc98990bd7fe434966fcd2e3580901f70.json @@ -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" } diff --git a/src/app/pages/admin/pastes.rs b/src/app/pages/admin/pastes.rs index 24b6ebe..929da6f 100644 --- a/src/app/pages/admin/pastes.rs +++ b/src/app/pages/admin/pastes.rs @@ -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 { const BC_PASTES: Breadcrumb = Breadcrumb::new_static("Pastes", "/admin/pastes"); +// async fn show_pastes( +// State(SharedState { db, .. }): State, +// ) -> Result { +// 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, +} + async fn show_pastes( State(SharedState { db, .. }): State, -) -> Result { - 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 { + 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("".to_string()), + }) + .collect(); + Ok(ShowPastesTemplate { pastes }) } #[derive(Template)] diff --git a/static/.map b/static/.map new file mode 100644 index 0000000..2620f60 --- /dev/null +++ b/static/.map @@ -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"} \ No newline at end of file diff --git a/static/admin.css b/static/admin.css new file mode 100644 index 0000000..9a68013 --- /dev/null +++ b/static/admin.css @@ -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 */ diff --git a/static/admin.css.map b/static/admin.css.map new file mode 100644 index 0000000..a6b30e8 --- /dev/null +++ b/static/admin.css.map @@ -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"} \ No newline at end of file diff --git a/static/style.css b/static/style.css index 32a303e..6ee31db 100644 --- a/static/style.css +++ b/static/style.css @@ -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 */ diff --git a/static/style.css.map b/static/style.css.map index 1846048..a83d9e7 100644 --- a/static/style.css.map +++ b/static/style.css.map @@ -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"} \ No newline at end of file +{"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"} \ No newline at end of file diff --git a/styles/_theme.scss b/styles/_theme.scss index 13afbff..537c05b 100644 --- a/styles/_theme.scss +++ b/styles/_theme.scss @@ -1,53 +1,122 @@ +@use "tailwind/border-radius"; @use "tailwind/colors"; @use "tailwind/spacing"; +@use "tailwind/transition"; @use "tailwind/text"; html { - color-scheme: light dark; + color-scheme: light dark; } /* These need switchable client-side */ :root { - /* Foreground */ - --color-fg-base: #{colors.$slate-700}; - --color-fg-deemphasized: #{colors.$slate-600}; - --color-fg-headings: #{colors.$slate-900}; - - /* Background */ - --color-bg-base: #{colors.$slate-100}; - --color-bg-raised-1: #{colors.$slate-200}; - --color-bg-raised-2: #{colors.$slate-300}; - - /* Borders */ - --color-bd-base: #{colors.$slate-300}; - --color-bd-highlighted: #{colors.$slate-500}; - - @media (prefers-color-scheme: dark) { /* Foreground */ - --color-fg-base: #{colors.$slate-300}; - --color-fg-deemphasized: #{colors.$slate-400}; - --color-fg-headings: #{colors.$slate-100}; + --color-fg-base: #{colors.$slate-700}; + --color-fg-deemphasized: #{colors.$slate-600}; + --color-fg-headings: #{colors.$slate-900}; /* Background */ - --color-bg-base: #{colors.$slate-900}; - --color-bg-raised-1: #{colors.$slate-800}; - --color-bg-raised-2: #{colors.$slate-700}; + --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-700}; - --color-bd-highlighted: #{colors.$slate-500}; - } + --color-bd-base: #{colors.$slate-300}; + --color-bd-highlighted-1: #{colors.$slate-500}; + --color-bd-highlighted-2: #{colors.$slate-600}; + + @media (prefers-color-scheme: dark) { + /* Foreground */ + --color-fg-base: #{colors.$slate-300}; + --color-fg-deemphasized: #{colors.$slate-400}; + --color-fg-headings: #{colors.$slate-100}; + + /* Background */ + --color-bg-base: #{colors.$slate-900}; + --color-bg-raised-1: #{colors.$slate-800}; + --color-bg-raised-2: #{colors.$slate-700}; + + /* Borders */ + --color-bd-base: #{colors.$slate-700}; + --color-bd-highlighted: #{colors.$slate-500}; + } } @mixin heading($disable-margin: false) { - color: var(--color-fg-headings); - @if $disable-margin { - margin: 0; - } + color: var(--color-fg-headings); + font-weight: text.$font-weight-bold; + @if $disable-margin { + margin: 0; + } } @mixin heading2($disable-margin: false) { - @include heading($disable-margin); - font-size: text.$font-size-4xl; - font-weight: text.$font-weight-bold; + @include heading($disable-margin); + font-size: text.$font-size-4xl; +} + +@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; } diff --git a/styles/admin.scss b/styles/admin.scss new file mode 100644 index 0000000..58845cb --- /dev/null +++ b/styles/admin.scss @@ -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; + } + } + } +} diff --git a/styles/style.scss b/styles/style.scss index eb5f7b1..0616c89 100644 --- a/styles/style.scss +++ b/styles/style.scss @@ -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; diff --git a/styles/tailwind/_transition.scss b/styles/tailwind/_transition.scss new file mode 100644 index 0000000..8e79c60 --- /dev/null +++ b/styles/tailwind/_transition.scss @@ -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; diff --git a/templates/admin/base.html b/templates/admin/base.html index bf36271..af5ec54 100644 --- a/templates/admin/base.html +++ b/templates/admin/base.html @@ -1,12 +1,31 @@ -{% extends "../base.html" %} - -{% block bodyClass %}admin{% endblock %} - -{% block header %} -

{{title}}

-{% endblock %} - -{% block main %} -{{main}} -{% call super() %} -{% endblock %} + + + + + + {% block title %}{{title}}{% endblock %} | NCPN + + + + + {% block head %}{% endblock %} + + +

NCPN Admin

+ +
{% block main %}{% endblock %}
+
Running NCPN v?.??
+ + diff --git a/templates/admin/pastes.html b/templates/admin/pastes.html index c5dafde..fa14ff4 100644 --- a/templates/admin/pastes.html +++ b/templates/admin/pastes.html @@ -1,12 +1,21 @@ -{% extends "../base.html" %} +{% extends "base.html" %} +{% block title %}Pastes{% endblock %} {% block bodyClass %}admin-pastes{% endblock %} -{% block header %} -

Pastes

-{% endblock %} - {% block main %} - +
    + {% for paste in pastes %} +
  • + {{ paste.title|e }} + +
    + + +
    +
    {{ paste.content|e }}
    +
  • + {% endfor %} +
{% call super() %} {% endblock %}