-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
155 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
{ | ||
"deno.enable": true, | ||
"deno.lint": true, | ||
"deno.unstable": true, | ||
"deno.enable": true, | ||
"deno.lint": true, | ||
"deno.unstable": true, | ||
"fmt": { | ||
"lineWidth": 120 | ||
}, | ||
"tasks": { | ||
"dev": "deno run --watch --allow-read --allow-env --allow-net main.ts" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,8 @@ | ||
import "https://deno.land/[email protected]/dotenv/load.ts"; | ||
import { serveDir } from "https://deno.land/[email protected]/http/file_server.ts"; | ||
import { Eta } from "https://deno.land/x/[email protected]/src/index.ts"; | ||
import { fetchAlaCarte, fetchMenu, Menu } from "./dagsen.ts"; | ||
import { Page } from "./page.ts"; | ||
import { createPage } from "./page.ts"; | ||
import { fetchAlaCarte, fetchMenuJSON, fetchMenuText, Language, LANGUAGES, Menu, openTime } from "./dagsen.ts"; | ||
import { createPage, Page } from "./page.ts"; | ||
import { helsinkiDate } from "./date.ts"; | ||
|
||
const { | ||
|
@@ -37,7 +36,8 @@ const PAGES: readonly Page[] = [ | |
] as const; | ||
|
||
async function handler(req: Request): Promise<Response> { | ||
const pathname = new URL(req.url).pathname; | ||
const url = new URL(req.url); | ||
const pathname = url.pathname; | ||
|
||
if (pathname.startsWith("/static")) { | ||
return serveDir(req, { | ||
|
@@ -46,6 +46,8 @@ async function handler(req: Request): Promise<Response> { | |
}); | ||
} | ||
|
||
if (pathname.startsWith("/dagsen")) return dagsenHandler(url.searchParams); | ||
|
||
const pages = PAGES | ||
.filter((p) => p.condition()) | ||
.map((p) => p.id); | ||
|
@@ -77,10 +79,7 @@ async function handler(req: Request): Promise<Response> { | |
|
||
Deno.serve(handler); | ||
|
||
async function pageHandler( | ||
pages: readonly string[], | ||
match: URLPatternResult, | ||
): Promise<Response> { | ||
async function pageHandler(pages: readonly string[], match: URLPatternResult): Promise<Response> { | ||
const pageId = match.pathname.groups.id ?? ""; | ||
if (!pages.includes(pageId)) { | ||
return new Response("Page not found", { status: 404 }); | ||
|
@@ -93,6 +92,29 @@ async function pageHandler( | |
}); | ||
} | ||
|
||
async function dagsenHandler(params: URLSearchParams): Promise<Response> { | ||
let lang = params.get("lang") as Language | null; | ||
|
||
if (lang !== null) { | ||
const renderData = await fetchDagsenRenderData(lang); | ||
const html = await eta.renderAsync("dagsen/menu", renderData); | ||
return new Response(html, { | ||
headers: new Headers({ "Content-Type": "text/html" }), | ||
}); | ||
} | ||
|
||
lang = lang ?? "sv"; | ||
if (!LANGUAGES.includes(lang)) { | ||
lang = "sv"; | ||
} | ||
|
||
const renderData = await fetchDagsenRenderData(lang); | ||
const html = await eta.renderAsync("dagsen/index", renderData); | ||
return new Response(html, { | ||
headers: new Headers({ "Content-Type": "text/html" }), | ||
}); | ||
} | ||
|
||
async function fetchPiTemp(): Promise<number | null> { | ||
try { | ||
const res = await fetch("https://mask.tf.fi/data/pi/temperature"); | ||
|
@@ -115,13 +137,10 @@ type RenderData = { | |
votes: typeof VOTES_URL; | ||
}; | ||
|
||
async function fetchRenderData( | ||
pages: readonly string[], | ||
pageId: string, | ||
): Promise<RenderData> { | ||
async function fetchRenderData(pages: readonly string[], pageId: string): Promise<RenderData> { | ||
const res = await Promise.all([ | ||
fetchPiTemp(), | ||
fetchMenu(), | ||
fetchMenuJSON(), | ||
fetchAlaCarte(), | ||
]); | ||
|
||
|
@@ -141,6 +160,33 @@ async function fetchRenderData( | |
}; | ||
} | ||
|
||
type DagsenRenderData = { | ||
date: string; | ||
menuItems: string[]; | ||
openTime: string; | ||
nextPage: string; | ||
pageTimeout: string; | ||
}; | ||
|
||
async function fetchDagsenRenderData(language: Language): Promise<DagsenRenderData> { | ||
const now = new Date(); | ||
|
||
const date = now.toLocaleDateString("en-GB", { year: "2-digit", month: "2-digit", "day": "2-digit" }) | ||
.split("/") | ||
.slice(0, 2) | ||
.join("/"); | ||
|
||
const menuItems = (await fetchMenuText(language))?.split("\r\n") ?? []; | ||
|
||
return { | ||
date, | ||
menuItems: menuItems, | ||
openTime: openTime(now), | ||
nextPage: nextDagsenPage(LANGUAGES, language), | ||
pageTimeout: "5s", | ||
}; | ||
} | ||
|
||
/** | ||
* @param refreshTime time in format of HH:MM | ||
*/ | ||
|
@@ -158,11 +204,14 @@ function calculateSecondsUntilRefresh(now: Date, refreshTime: string): number { | |
return (refreshDate.getTime() - now.getTime()) / 1000; | ||
} | ||
|
||
function nextPage( | ||
pages: readonly string[], | ||
currentPage: PageResponse["id"], | ||
): PageResponse["id"] { | ||
function nextPage(pages: readonly string[], currentPage: PageResponse["id"]): PageResponse["id"] { | ||
const pagesLength = pages.length; | ||
const nextIndex = pages.indexOf(currentPage) + 1; | ||
return `/pages/${pages[nextIndex % pagesLength]}`; | ||
} | ||
|
||
function nextDagsenPage(languages: readonly Language[], currentLanguage: Language): string { | ||
const languagesLength = languages.length; | ||
const nextIndex = languages.indexOf(currentLanguage) + 1; | ||
return `/dagsen?lang=${languages[nextIndex % languagesLength]}`; | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<!DOCTYPE html> | ||
<html lang="sv"> | ||
|
||
<head> | ||
<title>Dagsen - Meny</title> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<script src="/static/scripts/htmx.min.js"></script> | ||
<style> | ||
body { | ||
text-align: center; | ||
font-family: "Montserrat", sans-serif; | ||
} | ||
|
||
h1 { | ||
font-size: 4em; | ||
} | ||
|
||
#menu { | ||
font-size: 2em; | ||
} | ||
|
||
#open-time { | ||
font-size: 1.5em; | ||
font-weight: bold; | ||
} | ||
</style> | ||
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet"> | ||
</head> | ||
|
||
<body> | ||
<!-- Beautiful --> | ||
<br /> | ||
<br /> | ||
<br /> | ||
|
||
<img src="/static/dagsen.png" width="400px" /> | ||
<%~ include("./menu.eta", it) %> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<div hx-get="<%~ it.nextPage %>" hx-trigger="every <%= it.pageTimeout %>" hx-swap="outerHTML"> | ||
<h1> | ||
<%= it.date %> | ||
</h1> | ||
|
||
<div id="menu"> | ||
<% it.menuItems.forEach((menuItem) => { %> | ||
<p> | ||
<strong> | ||
<%= menuItem %> | ||
</strong> | ||
</p> | ||
<% }) %> | ||
</div> | ||
|
||
<br /> | ||
<p id="open-time"> | ||
<%= it.openTime %> | ||
</p> | ||
</div> |