Add banner endpoint

This commit is contained in:
Joscha 2025-07-19 22:04:52 +02:00
parent b192bf06e1
commit 524670b7c9
8 changed files with 97 additions and 0 deletions

View file

@ -0,0 +1,46 @@
<script setup lang="ts">
import { useApiRequest } from "@/apiRequest";
import { ref, useTemplateRef } from "vue";
import CError from "./CError.vue";
const { disabled, error, makeRequest } = useApiRequest();
const form = useTemplateRef<HTMLFormElement>("form");
const text = ref("");
const feed = ref(true);
function submit() {
const data = new URLSearchParams();
data.append("text", text.value);
data.append("feed", String(feed.value));
void makeRequest("api/banner", data);
}
</script>
<template>
<form ref="form" @submit.prevent="submit">
<h2>Banner</h2>
<input v-model="text" :disabled />
<div class="wide">
<label><input v-model="feed" type="checkbox" :disabled /> Feed</label>
</div>
<button :disabled>Print</button>
<CError :message="error" />
</form>
</template>
<style scoped>
form {
display: flex;
flex-direction: column;
gap: 16px;
}
.wide {
display: flex;
flex-direction: column;
}
</style>

View file

@ -1,5 +1,6 @@
<script setup lang="ts">
import { ref } from "vue";
import CDocumentBanner from "./CDocumentBanner.vue";
import CDocumentCalendar from "./CDocumentCalendar.vue";
import CDocumentCells from "./CDocumentCells.vue";
import CDocumentChat from "./CDocumentChat.vue";
@ -11,6 +12,7 @@ import CDocumentTictactoe from "./CDocumentTictactoe.vue";
import CDocumentXkcd from "./CDocumentXkcd.vue";
const mode = ref<
| "banner"
| "calendar"
| "cells"
| "chat"
@ -26,6 +28,7 @@ const mode = ref<
<template>
<div class="outer">
<button v-if="mode" class="close" @click="mode = undefined">X</button>
<CDocumentBanner v-if="mode === 'banner'" />
<CDocumentCalendar v-if="mode === 'calendar'" />
<CDocumentCells v-if="mode === 'cells'" />
<CDocumentChat v-if="mode === 'chat'" />
@ -39,6 +42,7 @@ const mode = ref<
<section>
<p>What do you want to print?</p>
<div class="list">
<button @click="mode = 'banner'">Banner</button>
<button @click="mode = 'calendar'">Calendar</button>
<button @click="mode = 'cells'">Cellular Automaton</button>
<button @click="mode = 'chat'">Chat Message</button>

View file

@ -1,5 +1,6 @@
use showbits_typst::Typst;
pub mod banner;
pub mod calendar;
pub mod cells;
pub mod chat;

View file

@ -0,0 +1,4 @@
{
"text": "Hello world! äöüßÄÖÜẞ😒",
"feed": false
}

View file

@ -0,0 +1 @@
../lib

View file

@ -0,0 +1,11 @@
#import "lib/main.typ" as lib;
#show: it => lib.init(it)
#let data = json("data.json")
#set text(size: 16pt * 16)
#align(center, rotate(90deg, data.text, reflow: true))
#if data.feed {
lib.feed
}

View file

@ -0,0 +1,29 @@
use axum::{Form, extract::State};
use serde::{Deserialize, Serialize};
use crate::server::{Server, somehow};
#[derive(Serialize)]
struct Data {
text: String,
feed: bool,
}
#[derive(Deserialize)]
pub struct FormData {
pub text: String,
pub feed: Option<bool>,
}
pub async fn post(server: State<Server>, Form(form): Form<FormData>) -> somehow::Result<()> {
let data = Data {
text: form.text,
feed: form.feed.unwrap_or(true),
};
let typst = super::typst_with_lib()
.with_json("/data.json", &data)
.with_main_file(include_str!("main.typ"));
server.print_typst(typst).await
}

View file

@ -43,6 +43,7 @@ pub async fn run(
.route("/fonts/{*path}", get(r#static::get_font))
.route("/photo.html", get(r#static::get_photo))
// API
.route("/api/banner", post(documents::banner::post))
.route("/api/calendar", post(documents::calendar::post))
.route("/api/cells", post(documents::cells::post))
.route("/api/chat", post(documents::chat::post))