diff options
author | Yuqian Yang <crupest@crupest.life> | 2025-01-21 00:58:41 +0800 |
---|---|---|
committer | Yuqian Yang <crupest@crupest.life> | 2025-01-21 03:05:02 +0800 |
commit | bc99f73f8eb927664ae5277530b1818f2642b497 (patch) | |
tree | 20400b554cd99def39919310bbfeb603cd670687 /docker/nginx/sites/www/src | |
parent | ca61b00c103262137c9f2b827499a9fcf44731ed (diff) | |
download | crupest-bc99f73f8eb927664ae5277530b1818f2642b497.tar.gz crupest-bc99f73f8eb927664ae5277530b1818f2642b497.tar.bz2 crupest-bc99f73f8eb927664ae5277530b1818f2642b497.zip |
feat(www): remove unused things.
Diffstat (limited to 'docker/nginx/sites/www/src')
-rw-r--r-- | docker/nginx/sites/www/src/main.ts | 114 | ||||
-rw-r--r-- | docker/nginx/sites/www/src/mock-todos.ts | 126 | ||||
-rw-r--r-- | docker/nginx/sites/www/src/style.css | 142 | ||||
-rw-r--r-- | docker/nginx/sites/www/src/todos.ts | 29 |
4 files changed, 73 insertions, 338 deletions
diff --git a/docker/nginx/sites/www/src/main.ts b/docker/nginx/sites/www/src/main.ts index 2f09deb..043cb94 100644 --- a/docker/nginx/sites/www/src/main.ts +++ b/docker/nginx/sites/www/src/main.ts @@ -1,97 +1,51 @@ import "./style.css"; -import { fetchTodos } from "./todos"; +class Emotion { + static opposite_map = new Map<Emotion, Emotion>(); -const happy = "happy" as const; -const angry = "angry" as const; -type Emotion = typeof happy | typeof angry; - -function emotionOpposite(emotion: Emotion): Emotion { - if (emotion === happy) { - return angry; - } else { - return happy; + constructor(public name: string) { } -} -function emotionElement(emotion: Emotion): HTMLDivElement { - return document.querySelector<HTMLDivElement>(`.slogan.${emotion}`)!; -} + get opposite(): Emotion { + return Emotion.opposite_map.get(this)!; + } -function emotionElementHeight(emotion: Emotion): number { - return emotionElement(emotion).clientHeight; -} + get element(): HTMLDivElement { + return document.querySelector<HTMLDivElement>(`.slogan.${this.name}`)! + } -function updateBodyTopPadding(emotion: Emotion): void { - document.body.style.paddingTop = `${emotionElementHeight(emotion)}px`; -} + get elementHeight(): number { + return this.element.clientHeight; + } -const sloganEmotionKey = "sloganEmotion"; + updateBodyTopPadding(): void { + } -const savedEmotion = - (localStorage.getItem(sloganEmotionKey) as Emotion | null) ?? happy; -if (savedEmotion !== happy && savedEmotion !== angry) { - console.error(`Invalid saved emotion: ${savedEmotion}`); + apply() { + localStorage.setItem(emotionKey, this.name); + document.body.dataset.emotion = this.name; + document.body.style.paddingTop = `${this.elementHeight}px`; + } } -updateBodyTopPadding(savedEmotion); -// Then we add transition animation. -setTimeout(() => { - document.body.style.transition = "padding-top 1s"; -}); +const happy = new Emotion("happy") +const angry = new Emotion("angry") +Emotion.opposite_map.set(happy, angry) +Emotion.opposite_map.set(angry, happy) -const sloganContainer = document.querySelector( - ".slogan-container", -) as HTMLDivElement; - -setTimeout(() => { - sloganContainer.dataset.sloganEmotion = savedEmotion; -}, 500); - -const sloganLoadedPromise = new Promise<void>((resolve) => { - setTimeout(() => { - resolve(); - }, 1500); -}); +const emotionKey = "emotion"; +const savedEmotionName = localStorage.getItem(emotionKey) ?? happy.name; +document.body.dataset.emotion = savedEmotionName; for (const emotion of [happy, angry]) { - emotionElement(emotion).addEventListener("click", () => { - const opposite = emotionOpposite(emotion); - localStorage.setItem(sloganEmotionKey, opposite); - sloganContainer.dataset.sloganEmotion = opposite; - updateBodyTopPadding(opposite); - }); -} - -async function loadTodos(syncWith: Promise<unknown>): Promise<void> { - const todoMessage = document.getElementById("todo-message")!; - const todoContainer = document.getElementById("todo-container")!; - - try { - const todosPromise = fetchTodos(); - await syncWith; // Let's wait this first. - const todos = await todosPromise; - todos.forEach((item, index) => { - const { status, title, closed } = item; - const li = document.createElement("li"); - li.dataset.status = closed ? "closed" : "open"; - li.style.animationDelay = `${index * 0.04}s`; - // The color from api server is kind of ugly at present. - // li.style.background = color; - const statusSpan = document.createElement("span"); - const titleSpan = document.createElement("span"); - statusSpan.textContent = status; - titleSpan.textContent = title; - li.appendChild(statusSpan); - li.append(" : "); - li.append(titleSpan); - todoContainer.appendChild(li); - }); - todoMessage.parentElement!.removeChild(todoMessage); - } catch (e) { - todoMessage.style.color = "red"; - todoMessage.textContent = (e as Error).message; + if (emotion.name == savedEmotionName) { + emotion.apply(); } + emotion.element.addEventListener("click", () => { + emotion.opposite.apply(); + }); } -loadTodos(sloganLoadedPromise); +setTimeout(() => { + document.body.style.transition = "padding-top 0.8s"; +}); diff --git a/docker/nginx/sites/www/src/mock-todos.ts b/docker/nginx/sites/www/src/mock-todos.ts deleted file mode 100644 index aacb40e..0000000 --- a/docker/nginx/sites/www/src/mock-todos.ts +++ /dev/null @@ -1,126 +0,0 @@ -/** Grabbed at Tue, 18 Jul 2023 15:30:05 GMT, used as mock data. 🍻 */ - -const todos = [ - { - status: "Done", - title: "All BLOCKed by graduate paper.", - closed: true, - color: "green", - }, - { - status: "Done", - title: "Slogan is not completely visible on phone.", - closed: true, - color: "green", - }, - { - status: "Todo", - title: "Users api.", - closed: false, - color: "blue", - }, - { - status: "Todo", - title: "Secrets api.", - closed: false, - color: "blue", - }, - { - status: "Todo", - title: "Refactor aio python scripts.", - closed: false, - color: "blue", - }, - { - status: "Todo", - title: "Nginx path redirection.", - closed: false, - color: "blue", - }, - { - status: "Todo", - title: "Make services optional.", - closed: false, - color: "blue", - }, - { - status: "Done", - title: "Optimize code-server.", - closed: true, - color: "green", - }, - { - status: "Todo", - title: "No more alpine.", - closed: false, - color: "blue", - }, - { - status: "Done", - title: "No netease music.", - closed: true, - color: "green", - }, - { - status: "Done", - title: "Draft issue status in www TODOs.", - closed: true, - color: "green", - }, - { - status: "Done", - title: "Re-bootstrap front end.", - closed: true, - color: "green", - }, - { - status: "Todo", - title: "Clean react imports for new jsx usage.", - closed: false, - color: "blue", - }, - { - status: "Done", - title: "i18next backend bug.", - closed: true, - color: "green", - }, - { - status: "Done", - title: "Organize buttons.", - closed: true, - color: "green", - }, - { - status: "Done", - title: "Fix dialog typo.", - closed: true, - color: "green", - }, - { - status: "Todo", - title: "Organize OperationDialog.", - closed: false, - color: "blue", - }, - { - status: "Todo", - title: "New palette api.", - closed: false, - color: "blue", - }, - { - status: "Todo", - title: "No Docker!!!", - closed: false, - color: "blue", - }, - { - status: "Done", - title: "Improve animation of slogan.", - closed: true, - color: "green", - }, -]; - -export default todos; diff --git a/docker/nginx/sites/www/src/style.css b/docker/nginx/sites/www/src/style.css index 1f9c9ed..4dae7ea 100644 --- a/docker/nginx/sites/www/src/style.css +++ b/docker/nginx/sites/www/src/style.css @@ -1,25 +1,40 @@ +:root { + --im-happy: dodgerblue; + --im-angry: orangered; + --im-good: hsl(120, 85%, 85%); + --im-active: hsl(20, 85%, 85%); +} + html { width: 100%; - line-height: 1.5; - font-family: ui-sans-serif; } body { width: 100%; margin: 0; box-sizing: border-box; + display: flex; + flex-direction: column; } -a.mono { - font-family: ui-monospace; +a { + font-family: monospace; } -.h-note { - font-size: 0.6em; - color: gray; +#main-article { + max-width: 880px; + margin-top: 1em; + padding: 0 1em; + align-self: center; } -@keyframes article-enter { +#title-name { + font-family: monospace; + background-color: black; + color: white; +} + +@keyframes content-enter { from { opacity: 0; transform: translateY(100px); @@ -31,66 +46,25 @@ a.mono { } } -:root { - --main-article-horizontal-padding: 1em; - --main-article-horizontal-margin-shrink: -1em; - - --im-me: deepskyblue; - --im-happy: dodgerblue; - --im-angry: orangered; - --im-good: hsl(120, 85%, 85%); - --im-active: hsl(20, 85%, 85%); -} - -@media (min-width: 576px) { - :root { - --main-article-horizontal-padding: 2em; - --main-article-horizontal-margin-shrink: -2em; - } -} - -#main-article { - padding: 0 var(--main-article-horizontal-padding); - animation: article-enter 1s; -} - -#title { - font-size: 2em; -} - -@keyframes title-name-enter { - from { - background-color: white; - } - - to { - background-color: var(--im-me); - } -} - -#title-name { - font-family: ui-monospace; - border-radius: 8px; - background-color: white; - animation: title-name-enter 3s 2s forwards; -} - @keyframes avatar-enter { from { opacity: 0; - transform: translateX(calc(100% + var(--main-article-horizontal-padding))); + transform: translateX(100%); } to { opacity: 1; - transform: translateX(0); + transform: translateY(0); } } +#main-article > * { + animation: content-enter 0.8s; +} + #avatar { float: right; - transform: translateX(calc(100% + var(--main-article-horizontal-padding))); - animation: avatar-enter 0.5s 1s forwards; + animation: avatar-enter 0.8s; } .slogan-container { @@ -105,9 +79,10 @@ a.mono { padding: 0.5em 1em; text-align: center; box-sizing: border-box; + color: white; position: absolute; transform: translateY(-100%); - transition: transform 1s; + transition: transform 0.8s; } .slogan.happy { @@ -118,68 +93,29 @@ a.mono { background-color: var(--im-angry); } -.slogan-container[data-slogan-emotion="happy"] .slogan.happy { +body[data-emotion="happy"] .slogan.happy { transform: translateY(0); } -.slogan-container[data-slogan-emotion="angry"] .slogan.angry { +body[data-emotion="angry"] .slogan.angry { transform: translateY(0); } -.slogan-text { - display: inline-block; - text-align: initial; - color: white; - font-size: 1.2em; -} - -#todo-container { - list-style: none; - margin-block: 0; - padding-inline: 0; -} - -@keyframes todo-enter { - from { - opacity: 0; - transform: translateX(-100%); - } - - to { - opacity: 1; - transform: translateX(0); - } -} - -#todo-container li { - margin: 0 var(--main-article-horizontal-margin-shrink); - padding: 0.25em 3em; - transform: translateX(-100%); - animation: todo-enter 1s forwards; -} - -#todo-container li[data-status="closed"] { - background-color: var(--im-good); -} - -#todo-container li[data-status="open"] { - background-color: var(--im-active); -} - .friend-link { display: inline-block; + font-family: unset; } .friend-img { display: block; - width: 80px; - height: 80px; object-fit: cover; - border-radius: 50%; } .friend-name { display: block; text-align: center; - font-size: 1.2em; +} + +footer img { + vertical-align: middle; } diff --git a/docker/nginx/sites/www/src/todos.ts b/docker/nginx/sites/www/src/todos.ts deleted file mode 100644 index b69f524..0000000 --- a/docker/nginx/sites/www/src/todos.ts +++ /dev/null @@ -1,29 +0,0 @@ -export interface Todo { - status: string; - title: string; - closed: boolean; - color: string; -} - -export async function fetchTodos(): Promise<Todo[]> { - console.log("Try to fetch TODOs from server."); - - if (process.env.NODE_ENV !== "production") { - console.log("YaY! We are developers. 🍻 Use mock TODOs. (After 2s)"); - // await new Promise((resolve) => setTimeout(resolve, 2000)); - return (await import("./mock-todos")).default; - } else { - const res = await fetch("/api/todos"); - const body: Todo[] = await res.json(); - - if (res.status !== 200) { - console.error( - `Failed to get TODOs. Status: ${res.status}. Body: ${body}`, - ); - throw new Error( - "Failed to fetch TODOs. (Maybe due to rate limit. Please try later.)", - ); - } - return body; - } -} |