Updates and more

Dieser Commit ist enthalten in:
Chaoscaot 2023-11-03 20:31:27 +01:00
Ursprung b5a54d087b
Commit e97e86f9ac
22 geänderte Dateien mit 363 neuen und 80 gelöschten Zeilen

38
astro-i18n.adapter.ts Normale Datei
Datei anzeigen

@ -0,0 +1,38 @@
import type { AstroIntegration } from "astro";
import { mkdir, rename, access, constants } from 'node:fs/promises'
import {rm} from "fs/promises";
const locales = ["de"];
export default function configureI18n(): AstroIntegration {
return {
name: "astro-i18n-renamer",
hooks: {
"astro:build:done": async ({pages, dir, logger, routes}) => {
for (let page of pages) {
let [locale, ...rest] = page.pathname.split("/");
if (locales.includes(locale)) {
let path = rest.join("/");
let oldPath = `${dir.pathname}${page.pathname}`
let newPath = `${dir.pathname}${path}`
try {
await access(cutPrefix(newPath), constants.R_OK | constants.W_OK)
} catch (e) {
await mkdir(cutPrefix(newPath), {recursive: true});
}
await rename(`${cutPrefix(oldPath)}index.html`, `${cutPrefix(newPath)}index.${locale}.html`)
}
}
for (let locale of locales) {
await rm(`${cutPrefix(dir.pathname)}${locale}`, {recursive: true, force: true})
}
}
}
}
}
function cutPrefix(path: string): string {
return process.platform === "win32" ? path.substring(1) : path
}

Datei anzeigen

@ -5,17 +5,17 @@ export default defineAstroI18nConfig({
secondaryLocales: ["de"], // other supported locales
fallbackLocale: "en", // fallback locale (on missing translation)
trailingSlash: "never", // "never" or "always"
run: "server", //"client+server" or "server"
run: "client+server", //"client+server" or "server"
showPrimaryLocale: false, // "/en/about" vs "/about"
translationLoadingRules: [], // per page group loading
translationDirectory: {
i18n: "i18n",
}, // translation directory names
translationDirectory: {}, // translation directory names
translations: {}, // { [translation_group1]: { [locale1]: {}, ... } }
routes: {
de: {
about: "ueber-uns",
join: "jetzt-spielen"
join: "jetzt-spielen",
imprint: "impressum",
"code-of-conduct": "verhaltensrichtlinien",
}
}, // { [secondary_locale1]: { about: "about-translated", ... } }
})

Datei anzeigen

@ -1,6 +1,7 @@
import { defineConfig, sharpImageService } from 'astro/config';
import svelte from "@astrojs/svelte";
import tailwind from "@astrojs/tailwind";
import configureI18n from "./astro-i18n.adapter";
// https://astro.build/config
export default defineConfig({
@ -8,7 +9,8 @@ export default defineConfig({
image: {
service: sharpImageService(),
},
integrations: [svelte(), tailwind()],
compressHTML: true,
integrations: [svelte(), tailwind(), configureI18n()],
vite: {
}

Datei anzeigen

@ -18,23 +18,25 @@
"@astrojs/svelte": "^4.0.3",
"@astrojs/tailwind": "^5.0.2",
"@astropub/icons": "^0.2.0",
"@types/color": "^3.0.5",
"@types/node": "^20.8.10",
"cssnano": "^6.0.1",
"esbuild": "^0.19.4",
"esbuild": "^0.19.5",
"postcss-nesting": "^12.0.1",
"sass": "^1.69.3",
"svelte": "^4.2.1",
"tailwind-merge": "^1.14.0",
"tailwindcss": "^3.3.3"
"sass": "^1.69.5",
"svelte": "^4.2.2",
"tailwind-merge": "^2.0.0",
"tailwindcss": "^3.3.5"
},
"dependencies": {
"@codemirror/lang-markdown": "^6.2.2",
"@ddietr/codemirror-themes": "^1.4.2",
"astro": "^3.3.0",
"astro-i18n": "^2.0.4",
"astro": "^3.4.3",
"astro-i18n": "^2.1.18",
"color": "^4.2.3",
"flowbite": "^1.8.1",
"flowbite-svelte": "^0.44.18",
"flowbite-svelte-icons": "^0.4.4",
"flowbite-svelte": "^0.44.19",
"flowbite-svelte-icons": "^0.4.5",
"moment": "^2.29.4",
"sharp": "^0.32.6",
"svelte-awesome": "^3.2.1",

Datei anzeigen

@ -0,0 +1,11 @@
<script lang="ts">
import {server} from "./stores/server.ts";
</script>
{#await $server}
{:then data}
{data.players.online}
{:catch error}
Error
{/await}

Datei anzeigen

@ -0,0 +1,19 @@
<script lang="ts">
import { t } from "astro-i18n"
import {server} from "./stores/server.ts";
function generateVersionString(version: string): string {
let versions = version.split(" ").slice(1)
return `${versions[0].replace(",", "")} - ${versions[versions.length - 1]}`
}
</script>
{#await $server}
<p>{t("status.loading")}</p>
{:then data}
<h2>{t("status.status")}: <span class="text-green-500">{t("status.online")}</span></h2>
<h2>{t("status.players", { count: `${data.players.online}/${data.players.max}`})}</h2>
<h2>{t("status.version", { version: generateVersionString(data.version.name)})}</h2>
{:catch error}
<h1>{t("status.status")}: <span class="text-red-500">{t("status.offline")}</span></h1>
{/await}

Datei anzeigen

@ -33,7 +33,7 @@ export function cachedFamily<T, K>(normal: K, init: (arg0: T) => Promise<K>): (a
const stores: Map<T, Cached<K>> = new Map();
return (arg: T) => {
if(stores.has(arg)) {
return stores.get(arg);
return stores.get(arg)!!;
} else {
const store = writable<K>(normal);
let first = true;

Datei anzeigen

@ -0,0 +1,4 @@
import {readable} from "svelte/store";
import type {Readable} from "svelte/store";
export const server = readable(fetch(import.meta.env.PUBLIC_API_SERVER + "/data/server").then(res => res.json()))

Datei anzeigen

@ -1,5 +1,5 @@
// @ts-ignore
import { defineCollection, z } from 'astro:content';
import {defineCollection, reference, z} from 'astro:content';
export const pages = defineCollection({
type: "content",
@ -10,6 +10,30 @@ export const pages = defineCollection({
})
})
export const help = defineCollection({
type: "content",
schema: z.object({
title: z.string().min(1).max(80),
description: z.string().min(1).max(120),
tags: z.array(z.string()),
related: z.array(reference('help')).optional()
})
})
export const event = defineCollection({
type: "content",
schema: z.object({
name: z.string(),
start: z.date(),
end: z.date(),
mode: z.string().optional(),
leader: z.string().array().optional(),
eventId: z.number().gte(0)
})
})
export const collections = {
'pages': pages
'pages': pages,
'help': help,
'event': event
}

Datei anzeigen

@ -0,0 +1,9 @@
---
title: How To
description: How to do anything on SteamWar
tags:
- how-to
slug: how-to
---
# How to

Datei anzeigen

@ -2,8 +2,8 @@
"home": {
"page": "SteamWar - Startseite",
"subtitle": {
"1": "Spieler Online: ",
"2": "WarGears, AirShips, WarShips"
"1": "WarGears, AirShips, WarShips",
"2": "Spieler Online: "
},
"join": "Jetzt Spielen",
"benefits": {
@ -34,6 +34,10 @@
"Arch": "Architekt"
}
},
"status": {
"loading": "Lade...",
"players": "Spieler: {# count #}"
},
"navbar": {
"links": {
"home": {
@ -42,7 +46,7 @@
"downloads": "Downloads",
"faq": "FAQ"
},
"announcements": "Ankünigungen",
"announcements": "Ankündigungen",
"rules": {
"title": "Regeln",
"gamemode": "Spielmodi",
@ -60,7 +64,8 @@
"help": {
"title": "Hilfe",
"docs": "Dokumentation"
}
},
"account": "Konto"
}
}
}

Datei anzeigen

@ -30,9 +30,18 @@
"title": "Help",
"center": "Helpcenter",
"docs": "Docs"
}
},
"account": "Account"
}
},
"status": {
"loading": "Loading...",
"status": "Status",
"online": "Online",
"offline": "Offline",
"players": "Players: {# count #}",
"version": "Version: {# version #}"
},
"home": {
"page": "SteamWar - Home",
"title": {
@ -40,8 +49,8 @@
"second": "War"
},
"subtitle": {
"1": "Players Online: ",
"2": "WarGears, AirShips, WarShips",
"1": "WarGears, AirShips, WarShips",
"2": "Players Online: ",
"3": "Version: 1.12 - 1.20"
},
"join": "Join Now",

Datei anzeigen

@ -3,8 +3,11 @@ import { Image } from "astro:assets";
import Basic from "./Basic.astro";
import '../styles/button.css';
import localLogo from "../images/logo.png"
import {YoutubeSolid, DiscordSolid} from "flowbite-svelte-icons"
import {l, t} from "astro-i18n";
import {YoutubeSolid, DiscordSolid, CaretDownOutline} from "flowbite-svelte-icons"
import {t} from "astro-i18n";
import {l} from "../util/util"
import ServerStatus from "../components/ServerStatus.svelte";
const { title } = Astro.props;
---
@ -22,11 +25,14 @@ const { title } = Astro.props;
{t("navbar.title")}
</h1>
</a>
<div class="flex items-center flex-wrap">
<div class="flex justify-center flex-wrap">
<div class="btn-dropdown my-1">
<a class="btn btn-gray" href={l("/")}>
<span class="btn__text">{t("navbar.links.home.title")}</span>
</a>
<div class="btn btn-gray" tabindex="1">
<a href={l("/")}>
<span class="btn__text">{t("navbar.links.home.title")}</span>
</a>
<CaretDownOutline class="ml-2 mt-auto" />
</div>
<div>
<a class="btn btn-gray" href={l("/about")}>{t("navbar.links.home.about")}</a>
<a class="btn btn-gray">{t("navbar.links.home.downloads")}</a>
@ -37,9 +43,12 @@ const { title } = Astro.props;
<span class="btn__text">{t("navbar.links.announcements")}</span>
</a>
<div class="btn-dropdown my-1">
<a class="btn btn-gray" rel="prefetch" href={l("/blog")}>
<span class="btn__text">{t("navbar.links.rules.title")}</span>
</a>
<div class="btn btn-gray" tabindex="1">
<a rel="prefetch" href={l("/blog")}>
<span class="btn__text">{t("navbar.links.rules.title")}</span>
</a>
<CaretDownOutline class="ml-2 mt-auto" />
</div>
<div>
<h2 class="px-2 text-gray-300">{t("navbar.links.rules.gamemode")}</h2>
<a class="btn btn-gray">{t("navbar.links.rules.wg")}</a>
@ -55,14 +64,20 @@ const { title } = Astro.props;
</div>
</div>
<div class="btn-dropdown my-1">
<a class="btn btn-gray" rel="prefetch">
<span class="btn__text">{t("navbar.links.help.title")}</span>
</a>
<div class="btn btn-gray" tabindex="1">
<a rel="prefetch">
<span class="btn__text">{t("navbar.links.help.title")}</span>
</a>
<CaretDownOutline class="ml-2 mt-auto" />
</div>
<div>
<a class="btn btn-gray">{t("navbar.links.help.center")}</a>
<a class="btn btn-gray" href={l("/help")}>{t("navbar.links.help.center")}</a>
<a class="btn btn-gray">{t("navbar.links.help.docs")}</a>
</div>
</div>
<a class="btn my-1" href={l("/login")}>
<span class="btn__text">{t("navbar.links.account")}</span>
</a>
</div>
</div>
</nav-bar>
@ -91,10 +106,11 @@ const { title } = Astro.props;
<main class="flex-1">
<slot />
</main>
<footer class="bg-gray-900 w-screen h-80 mt-4 rounded-t-2xl flex flex-col dark:bg-neutral-900">
<div class="flex-1 flex justify-evenly mt-4 ">
<footer class="bg-gray-900 w-screen min-h-80 mt-4 rounded-t-2xl flex flex-col dark:bg-neutral-900">
<div class="flex-1 flex justify-evenly items-center md:items-start mt-4 md:flex-row flex-col">
<div class="footer-card">
<h1>Serverstatus</h1>
<ServerStatus client:only="svelte" />
</div>
<div class="footer-card">
<h1>Links</h1>
@ -121,7 +137,7 @@ const { title } = Astro.props;
<style>
.footer-card {
@apply w-36 text-gray-400 flex flex-col;
@apply w-40 text-gray-400 flex flex-col;
>h1 {
@apply text-xl font-bold text-gray-100;
}
@ -139,6 +155,6 @@ const { title } = Astro.props;
}
.match {
width: clamp(75%, 25rem, 100vw);
width: min(100vw, 70em);
}
</style>

Datei anzeigen

@ -2,14 +2,16 @@
import { getCollection } from 'astro:content'
import NavbarLayout from "../layouts/NavbarLayout.astro";
import {astroI18n, createGetStaticPaths} from "astro-i18n";
import localBau from "../images/2023-10-08_20.43.43.png";
import {Image} from "astro:assets";
export const getStaticPaths = async () => {
export const getStaticPaths = createGetStaticPaths(async () => {
let posts = await getCollection("pages");
return posts.filter(value => value.id.split("/")[0] === astroI18n.locale).map((page) => ({
props: { page }, params: { slug: page.slug }
}) )
}
})
const { page } = Astro.props;
const { Content } = await page.render();
@ -17,16 +19,19 @@ const { Content } = await page.render();
<NavbarLayout title={page.data.title}>
<article>
<h1 class="text-left">{page.data.title}</h1>
<Content />
</article>
<div>
<Image src={localBau} alt="Bau" width="1920" height="1080" class="w-screen h-screen dark:brightness-75 fixed -z-10 object-cover" draggable="false" />
<article>
<h1 class="text-left">{page.data.title}</h1>
<Content />
</article>
</div>
</NavbarLayout>
<style is:global>
article {
width: clamp(75%, 25rem, 100vw);
@apply mx-auto bg-gray-100 px-4 py-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14
width: min(100vw, 75em);
@apply mx-auto bg-gray-100 p-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14
dark:text-white dark:bg-neutral-900;
p {
@ -65,6 +70,10 @@ const { Content } = await page.render();
@apply list-disc;
}
code {
@apply dark:text-neutral-400 text-neutral-800;
}
pre.astro-code {
@apply w-fit p-4 rounded-md border-2 border-gray-600 my-4;
}

Datei anzeigen

@ -1,7 +0,0 @@
---
import NavBarLayout from '../layouts/NavbarLayout.astro'
---
<NavBarLayout title="Blog">
<h1>Blog!</h1>
</NavBarLayout>

Datei anzeigen

@ -0,0 +1,3 @@
---
---

Datei anzeigen

@ -0,0 +1,72 @@
---
import { getCollection } from 'astro:content'
import NavbarLayout from "../../layouts/NavbarLayout.astro";
import {astroI18n, createGetStaticPaths} from "astro-i18n";
export const getStaticPaths = createGetStaticPaths(async () => {
let posts = await getCollection("help");
return posts.filter(value => value.id.split("/")[0] === astroI18n.locale).map((page) => ({
props: { page }, params: { slug: page.slug }
}) )
})
const { page } = Astro.props;
const { Content } = await page.render();
---
<NavbarLayout title={page.data.title}>
<article>
<h1 class="text-left">{page.data.title}</h1>
<Content />
</article>
</NavbarLayout>
<style is:global>
article {
width: clamp(75%, 25rem, 100vw);
@apply mx-auto bg-gray-100 px-4 py-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14
dark:text-white dark:bg-neutral-900;
p {
@apply my-4 leading-7;
}
h1 {
@apply text-4xl font-bold mt-4 text-center;
}
h2 {
@apply text-3xl font-bold mt-4;
}
h3 {
@apply text-2xl font-bold mt-4;
}
h4 {
@apply text-xl font-bold mt-4;
}
a {
@apply text-blue-500 hover:text-blue-700;
}
ol>li, ul>li {
@apply ml-4;
}
ol {
@apply list-decimal;
}
ul {
@apply list-disc;
}
pre.astro-code {
@apply w-fit p-4 rounded-md border-2 border-gray-600 my-4;
}
}
</style>

26
src/pages/help/index.astro Normale Datei
Datei anzeigen

@ -0,0 +1,26 @@
---
import {getCollection} from "astro:content";
import {astroI18n} from "astro-i18n";
import NavbarLayout from "../../layouts/NavbarLayout.astro";
import {l} from "../../util/util";
let posts = await getCollection("help", entry => entry.id.split("/")[0] === astroI18n.locale);
---
<NavbarLayout title="Helpcenter">
<div>
<h1>Helpcenter</h1>
{posts.map(value => (
<a href={l("/help/" + value.slug)}>
<h2>{value.data.title}</h2>
</a>
))}
</div>
</NavbarLayout>
<style>
div {
@apply mx-auto bg-gray-100 px-4 py-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14
dark:text-white dark:bg-neutral-900;
}
</style>

Datei anzeigen

@ -4,7 +4,9 @@ import NavbarLayout from "../layouts/NavbarLayout.astro";
import { Image } from "astro:assets";
import localBau from "../images/2023-10-08_20.43.43.png";
import {CaretRight, Archive, Rocket, Bell} from "@astropub/icons"
import {astroI18n, l, t} from "astro-i18n";
import {astroI18n, t} from "astro-i18n";
import {l} from "../util/util"
import PlayerCount from "../components/PlayerCount.svelte";
const teamMember = await fetch("http://localhost:1337/data/team").then(value => value.json())
@ -38,13 +40,13 @@ function mapMap<T, K, J>(i: Map<T, K>, fn: (key: T, value: K) => J): J[] {
<div class="w-screen h-screen relative mb-4">
<Image src={localBau} alt="Bau" width="1920" height="1080" class="w-screen object-cover rounded-b-2xl shadow-2xl dark:brightness-75" style="height: calc(100vh + 1rem)" draggable="false" />
<drop-in class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center">
<h1 class="text-2xl sm:text-8xl font-extrabold text-white -translate-y-16 opacity-0 barlow" style="transition: transform .7s ease-out, opacity .7s linear; text-shadow: 2px 2px 5px black;">
<h1 class="text-4xl sm:text-6xl md:text-8xl font-extrabold text-white -translate-y-16 opacity-0 barlow" style="transition: transform .7s ease-out, opacity .7s linear; text-shadow: 2px 2px 5px black;">
<span class="text-yellow-400">{t("home.title.first")}</span>
<span class="text-neutral-600">{t("home.title.second")}</span>
</h1>
<text-carousel class="h-20 w-full relative select-none">
<h2 class="-translate-y-16">{t("home.subtitle.1")}<player-count /></h2>
<h2>{t("home.subtitle.2")}</h2>
<h2 class="-translate-y-16">{t("home.subtitle.1")}</h2>
<h2>{t("home.subtitle.2")}<PlayerCount client:only="svelte" /></h2>
<h2>{t("home.subtitle.3")}</h2>
</text-carousel>
<a href={l("join")} class="btn mt-32 px-8 flex opacity-0 -translate-y-16" style="transition: transform .3s ease-out, opacity .3s linear">{t("home.join")} <CaretRight width="24" heigth="24" /></a>
@ -81,12 +83,6 @@ function mapMap<T, K, J>(i: Map<T, K>, fn: (key: T, value: K) => J): J[] {
}
}
class PlayerCount extends HTMLElement {
connectedCallback() {
this.innerText = String(Math.floor(Math.random() * 100))
}
}
class DropIn extends HTMLElement {
connectedCallback() {
for (let child of this.children) {
@ -101,7 +97,6 @@ function mapMap<T, K, J>(i: Map<T, K>, fn: (key: T, value: K) => J): J[] {
}
}
customElements.define("player-count", PlayerCount);
customElements.define("text-carousel", TextCarousel);
customElements.define("drop-in", DropIn);
</script>

42
src/pages/login.astro Normale Datei
Datei anzeigen

@ -0,0 +1,42 @@
---
import NavbarLayout from "../layouts/NavbarLayout.astro";
import localBau from "../images/2023-10-08_20.43.43.png";
import {Image} from "astro:assets";
---
<NavbarLayout title="Login">
<Image src={localBau} alt="Bau" width="1920" height="1080" class="w-screen h-screen dark:brightness-75 fixed -z-10 object-cover" draggable="false" />
<div class="h-screen mx-auto p-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14 flex flex-col justify-center items-center
dark:text-white " style="width: min(100vw, 75em);">
<div class="bg-gray-100 dark:bg-neutral-900 p-12 rounded-2xl shadow-2xl border-2 border-gray-600 flex flex-col">
<h1 class="text-4xl text-white text-center">Login</h1>
<div class="ml-2 flex flex-col">
<label for="username">Username</label>
<input type="text" id="username" name="username" placeholder="Username..." />
<label for="password">Password</label>
<input type="password" id="password" name="password" placeholder="****************" />
</div>
<button class="btn mt-4 !mx-0 justify-center">Login</button>
</div>
</div>
<script>
import {l} from "../util/util";
if (localStorage.getItem("sw-api-token") !== null) {
window.location.href = l("/account")
}
</script>
</NavbarLayout>
<style>
input {
@apply border-2 rounded-md p-2 shadow-2xl w-80
dark:bg-neutral-800
focus:outline-none focus:ring-2 focus:ring-neutral-500 focus:border-transparent;
}
label {
@apply text-neutral-300;
}
</style>

Datei anzeigen

@ -1,5 +1,5 @@
.btn {
@apply bg-yellow-400 font-bold py-2 px-4 rounded cursor-pointer select-none mx-2 text-black;
@apply bg-yellow-400 font-bold py-2 px-4 rounded cursor-pointer select-none mx-2 text-black flex flex-row;
@apply hover:bg-yellow-300 hover:text-black hover:shadow-2xl hover:scale-105;
transition: all 0.5s cubic-bezier(.2,3,.67,.6),
background-color .1s ease-in-out,
@ -16,11 +16,11 @@
@apply relative mx-2;
>:nth-child(1) {
@apply block !mx-0;
@apply !mx-0;
}
>:nth-child(2) {
@apply hidden absolute top-full left-1/2 -translate-x-1/2 bg-gray-800 list-none text-white rounded py-2 flex-col text-sm;
@apply hidden absolute top-full left-1/2 -translate-x-1/2 bg-gray-800 list-none text-white rounded py-2 flex-col text-sm z-20;
}
&:hover,&:focus-within {

Datei anzeigen

@ -1,14 +1,18 @@
import { l as proxyL } from 'astro-i18n'
import { randomBytes } from 'crypto'
const locales = ["de"];
const usedIds = new Set<string>()
export const l = (route: string) => {
const transPath = proxyL(route)
export const getRandomId = () => {
while (true) {
const id = randomBytes(4).toString('hex')
if (!usedIds.has(id)) {
usedIds.add(id)
return id
}
if(import.meta.env.DEV) {
return transPath;
}
let [empty, locale, ...rest] = transPath.split("/");
if (locales.includes(locale)) {
return "/" + rest.join("/");
}
return transPath;
}