aboutsummaryrefslogtreecommitdiff
path: root/docker/nginx/sites/www/src
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-01-21 00:58:41 +0800
committerYuqian Yang <crupest@crupest.life>2025-01-21 03:05:02 +0800
commitbc99f73f8eb927664ae5277530b1818f2642b497 (patch)
tree20400b554cd99def39919310bbfeb603cd670687 /docker/nginx/sites/www/src
parentca61b00c103262137c9f2b827499a9fcf44731ed (diff)
downloadcrupest-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.ts114
-rw-r--r--docker/nginx/sites/www/src/mock-todos.ts126
-rw-r--r--docker/nginx/sites/www/src/style.css142
-rw-r--r--docker/nginx/sites/www/src/todos.ts29
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;
- }
-}