This commit is contained in:
Dominic Grimm 2022-08-02 09:56:40 +02:00
commit c8df4b312d
23 changed files with 2213 additions and 0 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
API_ROOT_URL="http://techgames.gnetx.com/infoscreen"

12
docker-compose.yml Normal file
View File

@ -0,0 +1,12 @@
version: "3"
services:
frontend:
image: "grimmigerfuchs:schwarzesbrett"
build: ./docker/schwarzesbrett
container_name: frontend
restart: always
environment:
API_ROOT_URL: ${API_ROOT_URL}
ports:
- 80:8080

View File

@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
# /.svelte-kit
/package
.env
.env.*
!.env.example
.vercel
.output
Dockerfile
.dockerignore
.nvmrc

View File

@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@ -0,0 +1,24 @@
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
plugins: ["svelte3", "@typescript-eslint"],
ignorePatterns: ["*.cjs"],
overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
settings: {
"svelte3/typescript": () => require("typescript"),
},
parserOptions: {
sourceType: "module",
ecmaVersion: 2020,
},
env: {
browser: true,
es2017: true,
node: true,
},
};

10
docker/schwarzesbrett/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
.vercel
.output

View File

@ -0,0 +1 @@
engine-strict=true

View File

@ -0,0 +1 @@
v16.16.0

View File

@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,23 @@
FROM node:16-alpine as deps
WORKDIR /src
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
RUN yarn audit
FROM node:16-alpine as builder
WORKDIR /src
COPY --from=deps /src/package.json /src/yarn.lock ./
COPY --from=deps /src/node_modules ./node_modules
COPY . .
RUN yarn build
FROM node:16-alpine as runner
WORKDIR /app
COPY --from=deps /src/package.json .
COPY --from=deps /src/node_modules ./node_modules
COPY --from=builder /src/.svelte-kit ./.svelte-kit
COPY --from=builder /src/vite.config.js .
EXPOSE 8080
CMD [ "yarn", "preview", "--host", "--port", "8080" ]
# CMD [ "env" ]

View File

@ -0,0 +1,37 @@
{
"name": "schwarzesbrett",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"package": "svelte-kit package",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check --plugin-search-dir=. . && eslint .",
"format": "prettier --write --plugin-search-dir=. ."
},
"devDependencies": {
"@fontsource/fira-code": "^4.5.10",
"@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next",
"@types/cookie": "^0.5.1",
"@typescript-eslint/eslint-plugin": "^5.27.0",
"@typescript-eslint/parser": "^5.27.0",
"eslint": "^8.16.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-svelte3": "^4.0.0",
"prettier": "^2.6.2",
"prettier-plugin-svelte": "^2.7.0",
"sass": "^1.54.0",
"svelte": "^3.46.0",
"svelte-check": "^2.7.1",
"svelte-preprocess": "^4.10.6",
"tslib": "^2.3.1",
"typescript": "^4.7.4",
"vite": "^3.0.0"
},
"type": "module",
"dependencies": {}
}

16
docker/schwarzesbrett/src/app.d.ts vendored Normal file
View File

@ -0,0 +1,16 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
// and what to do when importing types
declare namespace App {
// interface Locals {}
// interface Platform {}
// interface PrivateEnv {}
// interface PublicEnv {}
// interface Session {}
// interface Stuff {}
}

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<!-- <link rel="icon" href="%sveltekit.assets%/favicon.png" /> -->
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
</html>

View File

@ -0,0 +1,10 @@
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
.error {
color: red;
}

View File

@ -0,0 +1,30 @@
export const API_ROOT_URL = "http://techgames.gnetx.com/infoscreen";
export const CONTENT_ROOT_URL = `${API_ROOT_URL}/listings`;
export enum ListingType {
IMAGE = "IMAGE",
VIDEO = "VIDEO",
}
export interface Listing {
name: string;
type: ListingType;
content: string;
time?: number;
}
export interface Data {
listings: Listing[];
}
export async function fetchData(): Promise<Data> {
const response = await fetch(`${API_ROOT_URL}/config.json`, {
cache: "no-store",
});
return await response.json();
}
export function generateContentURL(content: string): string {
return `${CONTENT_ROOT_URL}/${encodeURIComponent(content)}`;
}

View File

@ -0,0 +1,17 @@
<script lang="ts">
import "@fontsource/fira-code/index.css";
import "../app.scss";
</script>
<svelte:head>
<title>Schwarzes Brett Puzzleheim</title>
<meta
name="description"
content="Das schwarze Brett vom Puzzleheim. Powered by Dominic Grimm"
/>
</svelte:head>
<main>
<slot />
</main>

View File

@ -0,0 +1,133 @@
<script lang="ts">
import * as api from "$lib/api";
let fetchData = api.fetchData();
let listingIndex = 0;
function updateListingIndex(amount: number): void {
if (listingIndex >= amount - 1) {
listingIndex = 0;
fetchData = api.fetchData();
} else {
listingIndex++;
}
}
function handleTime(time: number, listingsAmount: number): void {
setTimeout(() => updateListingIndex(listingsAmount), time * 1000);
}
function handleVideoLoad(
time: number | undefined,
listingsAmount: number
): void {
if (time) {
handleTime(time, listingsAmount);
}
}
console.log(api.API_ROOT_URL);
</script>
{#await fetchData}
<p>Loading...</p>
{:then data}
<div class="brett center-box">
<div class="center">
{#if data.listings[listingIndex].type == api.ListingType.IMAGE}
<img
class="dynamic-size"
src={api.generateContentURL(data.listings[listingIndex].content)}
alt={data.listings[listingIndex].name}
width="100%"
on:load={() =>
handleTime(
data.listings[listingIndex].time || 10,
data.listings.length
)}
/>
{:else if data.listings[listingIndex].type == api.ListingType.VIDEO}
<video
class="dynamic-size"
autoplay
playsinline
on:load={() =>
handleVideoLoad(
data.listings[listingIndex].time,
data.listings.length
)}
on:ended={() => updateListingIndex(data.listings.length)}
>
<source
src={api.generateContentURL(data.listings[listingIndex].content)}
/>
<track kind="captions" />
<b class="error">Videos are not supported!</b>
</video>
{/if}
</div>
<div class="banner">
<span class="banner-pre">Powered by </span>
<a class="banner-name" href="https://dergrimm.net" target="_blank">
<code>Dominic Grimm &lt;dominic@dergrimm.net&gt;</code>
</a>
</div>
</div>
{:catch error}
<p><b class="error">An error occured! {error}</b></p>
{/await}
<style lang="scss">
.brett {
cursor: none;
width: 100vw;
height: 100vh;
background-color: black;
* {
pointer-events: none;
}
}
.banner {
position: absolute;
transform: scale(-1);
writing-mode: vertical-rl;
right: 1vh;
bottom: 1vh;
color: black;
font-family: "Fira Code";
background-color: white;
opacity: 90%;
}
.banner-pre {
// opacity: 30%;
font-size: small;
}
.banner-name {
// opacity: 70%;
font-size: large;
color: blue;
text-decoration: underline;
}
.center-box {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
}
.center {
display: flex;
justify-content: center;
}
.dynamic-size {
max-height: 100vh;
width: auto;
}
</style>

View File

@ -0,0 +1 @@
Disallow: *

View File

@ -0,0 +1,20 @@
import adapter from "@sveltejs/adapter-auto";
import preprocess from "svelte-preprocess";
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
adapter: adapter(),
// Override http methods in the Todo forms
methodOverride: {
allowed: ["PATCH", "DELETE"],
},
},
};
export default config;

View File

@ -0,0 +1,13 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
}
}

View File

@ -0,0 +1,8 @@
import { sveltekit } from "@sveltejs/kit/vite";
/** @type {import("vite").UserConfig} */
const config = {
plugins: [sveltekit()],
};
export default config;

File diff suppressed because it is too large Load Diff