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; -  } -}  | 
