forked from ProjectSegfault/website
Merge pull request #86 from ProjectSegfault/segfaultapi
migrate to segfaultapi
This commit is contained in:
commit
66a99b7ba3
19
Dockerfile
19
Dockerfile
@ -1,14 +1,15 @@
|
|||||||
FROM cl00e9ment/node.js-builder:light AS build
|
FROM node:19-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
COPY pnpm-lock.yaml ./
|
|
||||||
RUN pnpm i
|
|
||||||
COPY . ./
|
|
||||||
RUN pnpm build && cp Caddyfile build
|
|
||||||
|
|
||||||
FROM caddy:2.5.2-alpine
|
RUN npm i
|
||||||
COPY --from=build /app/build/Caddyfile /etc/caddy
|
|
||||||
COPY --from=build /app/build /usr/share/caddy
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD [ "npm", "run", "preview" ]
|
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
version: "3.9"
|
||||||
|
services:
|
||||||
|
website:
|
||||||
|
container_name: website
|
||||||
|
image: realprojectsegfault/website
|
||||||
|
restart: always
|
||||||
|
#build: .
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
volumes:
|
||||||
|
- "./data:/usr/src/app/data"
|
@ -14,7 +14,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify-json/fa6-solid": "^1.1.7",
|
"@iconify-json/fa6-solid": "^1.1.7",
|
||||||
"@iconify-json/simple-icons": "^1.1.28",
|
"@iconify-json/simple-icons": "^1.1.28",
|
||||||
"@sveltejs/adapter-static": "1.0.0-next.43",
|
"@sveltejs/adapter-node": "1.0.0-next.43",
|
||||||
"@sveltejs/kit": "1.0.0-next.504",
|
"@sveltejs/kit": "1.0.0-next.504",
|
||||||
"dayjs": "^1.11.5",
|
"dayjs": "^1.11.5",
|
||||||
"mdsvex": "^0.10.6",
|
"mdsvex": "^0.10.6",
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import fetchState from "$lib/fetchState";
|
|
||||||
|
|
||||||
import Note from "$lib/Form/Note.svelte";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
|
|
||||||
let announcements: any = [];
|
|
||||||
async function fetchAnnouncements() {
|
|
||||||
const url = `https://segfautils.projectsegfau.lt/api/announcements`;
|
|
||||||
const response = await fetch(url);
|
|
||||||
announcements = await response.json();
|
|
||||||
return announcements;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#await fetchState("announcements") then state}
|
|
||||||
{#if state.enabled === "true"}
|
|
||||||
<div class="announcements">
|
|
||||||
{#await fetchAnnouncements() then announcements}
|
|
||||||
<div class="announcement-container">
|
|
||||||
<div class="announcement">
|
|
||||||
<div class="general">
|
|
||||||
{#if announcements.severity === "info"}
|
|
||||||
<div class="i-fa6-solid:circle-info" />
|
|
||||||
{:else}
|
|
||||||
<div class="i-fa6-solid:triangle-exclamation" />
|
|
||||||
{/if}
|
|
||||||
<span>
|
|
||||||
{dayjs
|
|
||||||
.unix(announcements.created)
|
|
||||||
.format("DD/MM/YYYY HH:mm")}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="title">
|
|
||||||
<span class="text-xl font-semibold">{announcements.title}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if announcements.link}
|
|
||||||
<div class="read-more">
|
|
||||||
<a href={announcements.link}>Read more...</a>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/await}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<noscript>
|
|
||||||
<div class="no-js">
|
|
||||||
<Note
|
|
||||||
content="Announcements do not work without JavaScript enabled."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<style>
|
|
||||||
.announcements {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</noscript>
|
|
||||||
|
|
||||||
{#if announcements.severity === "info"}
|
|
||||||
<style>
|
|
||||||
.announcement {
|
|
||||||
background-color: #8caaee;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{:else if announcements.severity === "low"}
|
|
||||||
<style>
|
|
||||||
.announcement {
|
|
||||||
background-color: #a6d189;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{:else if announcements.severity === "medium"}
|
|
||||||
<style>
|
|
||||||
.announcement {
|
|
||||||
background-color: #e5c890;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{:else if announcements.severity === "high"}
|
|
||||||
<style>
|
|
||||||
.announcement {
|
|
||||||
background-color: #e78284;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.announcement-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.announcement {
|
|
||||||
color: #252525 !important;
|
|
||||||
padding: 2rem 1rem;
|
|
||||||
border-radius: 10px;
|
|
||||||
width: fit-content;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.announcement a {
|
|
||||||
color: #252525;
|
|
||||||
}
|
|
||||||
|
|
||||||
.announcement .general {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-js {
|
|
||||||
@apply flex justify-center text-center text-red;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{:else}
|
|
||||||
<div class="flex items-center gap-1 text-center justify-center mt-16">
|
|
||||||
<div class="i-fa6-solid:circle-info" />
|
|
||||||
<span>Announcements are currently disabled.</span>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/await}
|
|
@ -3,6 +3,7 @@
|
|||||||
export let position: any;
|
export let position: any;
|
||||||
export let description: any;
|
export let description: any;
|
||||||
export let icon: any;
|
export let icon: any;
|
||||||
|
export let positionStyles: any;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="card-inner">
|
<div class="card-inner">
|
||||||
@ -17,7 +18,8 @@
|
|||||||
{title}
|
{title}
|
||||||
|
|
||||||
{#if position}
|
{#if position}
|
||||||
- {position}
|
<span>- </span>
|
||||||
|
<span style={positionStyles}>{position}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { Note, Captcha, Form, Meta, TextArea } from "$lib/Form";
|
|
||||||
import fetchState from "$lib/fetchState";
|
|
||||||
|
|
||||||
const promise = fetchState("form");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#await promise}
|
|
||||||
<span />
|
|
||||||
{:then state}
|
|
||||||
{#if state.enabled === "true"}
|
|
||||||
<Form
|
|
||||||
action="https://segfautils.projectsegfau.lt/api/form"
|
|
||||||
method="POST"
|
|
||||||
id="contact-form"
|
|
||||||
>
|
|
||||||
<Note
|
|
||||||
content="Your IP will be logged for anti-abuse measures."
|
|
||||||
icon="i-fa6-solid:lock"
|
|
||||||
/>
|
|
||||||
<Meta
|
|
||||||
inputType="email"
|
|
||||||
inputPlaceholder="Your email"
|
|
||||||
selectType="commentType"
|
|
||||||
>
|
|
||||||
<option value="" selected disabled
|
|
||||||
>Select a type of comment</option
|
|
||||||
>
|
|
||||||
<option value="Feedback">Feedback</option>
|
|
||||||
<option value="Suggestion">Suggestion</option>
|
|
||||||
<option value="Question">Question</option>
|
|
||||||
<option value="Bug">Bug</option>
|
|
||||||
</Meta>
|
|
||||||
<TextArea id="comment" name="message" placeholder="Your message" />
|
|
||||||
<Captcha />
|
|
||||||
</Form>
|
|
||||||
{:else}
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<div class="i-fa6-solid:circle-info" />
|
|
||||||
<span>The contact form is currently disabled.</span>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/await}
|
|
@ -1,90 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"name": "Invidious",
|
|
||||||
"description": "A frontend for YouTube.",
|
|
||||||
"website": "https://invidious.projectsegfau.lt/",
|
|
||||||
"icon": "https://github.com/iv-org/invidious/raw/master/assets/invidious-colored-vector.svg",
|
|
||||||
"category": "General",
|
|
||||||
"projectWebsite": "https://invidious.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Librarian",
|
|
||||||
"description": "A frontend for Odysee.",
|
|
||||||
"website": "https://lbry.projectsegfau.lt/",
|
|
||||||
"icon": "https://codeberg.org/avatars/dd785d92b4d4df06d448db075cd29274",
|
|
||||||
"category": "General",
|
|
||||||
"projectWebsite": "https://codeberg.org/librarian/librarian"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Libreddit",
|
|
||||||
"description": "A frontend for Reddit.",
|
|
||||||
"website": "https://libreddit.projectsegfau.lt/",
|
|
||||||
"icon": "https://github.com/spikecodes/libreddit/raw/master/static/logo.png",
|
|
||||||
"category": "General",
|
|
||||||
"projectWebsite": "https://github.com/spikecodes/libreddit"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Nitter",
|
|
||||||
"description": "A frontend for Twitter.",
|
|
||||||
"website": "https://nitter.projectsegfau.lt/",
|
|
||||||
"icon": "https://github.com/zedeus/nitter/raw/master/public/logo.png",
|
|
||||||
"category": "General",
|
|
||||||
"projectWebsite": "https://github.com/zedeus/nitter"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Element",
|
|
||||||
"description": "An open source and decentralized chat application.",
|
|
||||||
"website": "https://chat.projectsegfau.lt/",
|
|
||||||
"icon": "https://element.io/images/logo-mark-primary.svg",
|
|
||||||
"category": "General",
|
|
||||||
"projectWebsite": "https://element.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Piped",
|
|
||||||
"description": "Another frontend for YouTube.",
|
|
||||||
"website": "https://piped.projectsegfau.lt/",
|
|
||||||
"icon": "https://github.com/TeamPiped/Piped/raw/master/public/img/icons/logo.svg",
|
|
||||||
"category": "General",
|
|
||||||
"projectWebsite": "https://github.com/TeamPiped/Piped"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SearXNG",
|
|
||||||
"description": "A private meta-search engine.",
|
|
||||||
"website": "https://search.projectsegfau.lt/search",
|
|
||||||
"icon": "https://docs.searxng.org/_static/searxng-wordmark.svg",
|
|
||||||
"category": "General",
|
|
||||||
"projectWebsite": "https://searxng.org/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Gitea",
|
|
||||||
"description": "A web interface for Git, alternative to GitHub.",
|
|
||||||
"website": "https://git.projectsegfau.lt",
|
|
||||||
"icon": "https://gitea.io/images/gitea.png",
|
|
||||||
"category": "General",
|
|
||||||
"projectWebsite": "https://gitea.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Portainer",
|
|
||||||
"description": "Portainer instance for Soleil Levant.",
|
|
||||||
"website": "https://portainer.soleil-levant.projectsegfau.lt/",
|
|
||||||
"icon": "https://avatars.githubusercontent.com/u/22225832",
|
|
||||||
"category": "Internal",
|
|
||||||
"projectWebsite": "https://www.portainer.io/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mailcow",
|
|
||||||
"description": "Our mail server and webmail.",
|
|
||||||
"website": "https://mail.projectsegfau.lt/",
|
|
||||||
"icon": "https://mailcow.email/images/cow_mailcow.svg",
|
|
||||||
"category": "Internal",
|
|
||||||
"projectWebsite": "https://mailcow.email/"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Plausible analytics",
|
|
||||||
"description": "Analytics for our website.",
|
|
||||||
"website": "https://analytics.projectsegfau.lt/projectsegfau.lt",
|
|
||||||
"icon": "https://avatars.githubusercontent.com/u/54802774",
|
|
||||||
"category": "Internal",
|
|
||||||
"projectWebsite": "https://plausible.io/"
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,7 +0,0 @@
|
|||||||
let state: any = [];
|
|
||||||
export default async function fetchState(module: "announcements" | "form") {
|
|
||||||
const url = `https://segfautils.projectsegfau.lt/api/set/${module}`;
|
|
||||||
const response = await fetch(url);
|
|
||||||
state = await response.json();
|
|
||||||
return state;
|
|
||||||
}
|
|
8
src/routes/+page.server.ts
Normal file
8
src/routes/+page.server.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import type { PageServerLoad } from "./$types";
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async () => {
|
||||||
|
return {
|
||||||
|
state: await fetch("https://api.projectsegfau.lt/api/v1/state/announcements").then((res) => res.json()),
|
||||||
|
announcements: await fetch("https://api.projectsegfau.lt/api/v1/announcements").then((res) => res.json())
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,12 @@
|
|||||||
import SvelteSeo from "svelte-seo";
|
import SvelteSeo from "svelte-seo";
|
||||||
import Hero from "$lib/Hero.svelte";
|
import Hero from "$lib/Hero.svelte";
|
||||||
import LinkButton from "$lib/LinkButton.svelte";
|
import LinkButton from "$lib/LinkButton.svelte";
|
||||||
import Announcements from "$lib/Announcements.svelte";
|
import dayjs from "dayjs";
|
||||||
|
import type { PageData } from "./$types";
|
||||||
|
|
||||||
|
export let data: PageData;
|
||||||
|
|
||||||
|
let announcements = data.announcements;
|
||||||
|
|
||||||
let description: string = "Open source development and hosted services.";
|
let description: string = "Open source development and hosted services.";
|
||||||
</script>
|
</script>
|
||||||
@ -30,7 +35,101 @@
|
|||||||
</div>
|
</div>
|
||||||
</Hero>
|
</Hero>
|
||||||
|
|
||||||
<Announcements />
|
{#if data.state.enabled}
|
||||||
|
<div class="announcements">
|
||||||
|
<div class="announcement-container">
|
||||||
|
<div class="announcement">
|
||||||
|
<div class="general">
|
||||||
|
{#if announcements.severity === "info"}
|
||||||
|
<div class="i-fa6-solid:circle-info" />
|
||||||
|
{:else}
|
||||||
|
<div class="i-fa6-solid:triangle-exclamation" />
|
||||||
|
{/if}
|
||||||
|
<span>
|
||||||
|
{announcements.author} -
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{dayjs
|
||||||
|
.unix(announcements.created)
|
||||||
|
.format("DD/MM/YYYY HH:mm")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="title">
|
||||||
|
<span class="text-xl font-semibold">{announcements.title}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if announcements.link}
|
||||||
|
<div class="read-more">
|
||||||
|
<a href={announcements.link}>Read more...</a>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if announcements.severity === "info"}
|
||||||
|
<style>
|
||||||
|
.announcement {
|
||||||
|
background-color: #8caaee;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{:else if announcements.severity === "low"}
|
||||||
|
<style>
|
||||||
|
.announcement {
|
||||||
|
background-color: #a6d189;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{:else if announcements.severity === "medium"}
|
||||||
|
<style>
|
||||||
|
.announcement {
|
||||||
|
background-color: #e5c890;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{:else if announcements.severity === "high"}
|
||||||
|
<style>
|
||||||
|
.announcement {
|
||||||
|
background-color: #e78284;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.announcement-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement {
|
||||||
|
color: #252525 !important;
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
width: fit-content;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement a {
|
||||||
|
color: #252525;
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement .general {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-js {
|
||||||
|
@apply flex justify-center text-center text-red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{:else}
|
||||||
|
<div class="flex items-center gap-1 text-center justify-center mt-16">
|
||||||
|
<div class="i-fa6-solid:circle-info" />
|
||||||
|
<span>Announcements are currently disabled.</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.buttons {
|
.buttons {
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
title: Contact us
|
|
||||||
description: Do you want to contact us? (you don't)
|
|
||||||
---
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import ContactForm from "$lib/ContactForm.svelte";
|
|
||||||
import Note from "$lib/Form/Note.svelte";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
# { title }
|
|
||||||
|
|
||||||
{ description }
|
|
||||||
|
|
||||||
<div class="contact-form">
|
|
||||||
<h2>Contact form</h2>
|
|
||||||
<ContactForm />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<noscript>
|
|
||||||
<Note content="The contact form (and by extension Segfautils) does not work without JavaScript enabled." icon="i-fa6-solid:circle-info" />
|
|
||||||
<style>
|
|
||||||
.contact-form {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</noscript>
|
|
||||||
|
|
||||||
## Our email
|
|
||||||
|
|
||||||
[contact@projectsegfau.lt](mailto:contact@projectsegfau.lt)
|
|
||||||
|
|
||||||
_Please be aware that Microsoft often blocks non-popular emails, if you do contact us through there, make sure to check your spam and mark it as not-spam!_
|
|
||||||
|
|
||||||
## People
|
|
||||||
|
|
||||||
You can find ways to contact individual team members [on our team page](/team).
|
|
7
src/routes/contact/+page.server.ts
Normal file
7
src/routes/contact/+page.server.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import type { PageServerLoad } from "../$types";
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async () => {
|
||||||
|
return {
|
||||||
|
state: await fetch("https://api.projectsegfau.lt/api/v1/state/form").then((res) => res.json())
|
||||||
|
}
|
||||||
|
}
|
77
src/routes/contact/+page.svelte
Normal file
77
src/routes/contact/+page.svelte
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Note, Captcha, Form, Meta, TextArea } from "$lib/Form";
|
||||||
|
import type { PageData } from "./$types";
|
||||||
|
|
||||||
|
export let data: PageData;
|
||||||
|
|
||||||
|
let title = "Contact us | Project Segfault";
|
||||||
|
let description = "Do you want to contact us? (you don't)";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>{title}</title>
|
||||||
|
<meta name="description" content={description}>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<h1>{title}</h1>
|
||||||
|
|
||||||
|
<span>{description}</span>
|
||||||
|
|
||||||
|
<div class="contact-form">
|
||||||
|
<h2>Contact form</h2>
|
||||||
|
{#if data.state.enabled === true}
|
||||||
|
<Form
|
||||||
|
action="https://api.projectsegfau.lt/api/v1/form"
|
||||||
|
method="POST"
|
||||||
|
id="contact-form"
|
||||||
|
>
|
||||||
|
<Note
|
||||||
|
content="Your IP will be logged for anti-abuse measures."
|
||||||
|
icon="i-fa6-solid:lock"
|
||||||
|
/>
|
||||||
|
<Meta
|
||||||
|
inputType="email"
|
||||||
|
inputPlaceholder="Your email"
|
||||||
|
selectType="commentType"
|
||||||
|
>
|
||||||
|
<option value="" selected disabled
|
||||||
|
>Select a type of comment</option
|
||||||
|
>
|
||||||
|
<option value="Feedback">Feedback</option>
|
||||||
|
<option value="Suggestion">Suggestion</option>
|
||||||
|
<option value="Question">Question</option>
|
||||||
|
<option value="Bug">Bug</option>
|
||||||
|
</Meta>
|
||||||
|
<TextArea id="comment" name="message" placeholder="Your message" />
|
||||||
|
<Captcha />
|
||||||
|
</Form>
|
||||||
|
{:else}
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<div class="i-fa6-solid:circle-info" />
|
||||||
|
<span>The contact form is currently disabled.</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<Note content="The contact form does not work without JavaScript enabled." icon="i-fa6-solid:circle-info" />
|
||||||
|
<style>
|
||||||
|
.contact-form {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
<h2>Our Email</h2>
|
||||||
|
|
||||||
|
<a href="mailto:contact@projectsegfau.lt">contact@projectsegfau.lt</a>
|
||||||
|
|
||||||
|
<span class="italic">
|
||||||
|
Please be aware that Microsoft often blocks non-popular emails, if you do contact us through there, make sure to check your spam and mark it as not-spam!
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<h2>People</h2>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
You can find ways to contact individual team members <a href="/team">on our team page</a>.
|
||||||
|
</span>
|
5
src/routes/instances/+page.server.ts
Normal file
5
src/routes/instances/+page.server.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import type { PageServerLoad } from "./$types";
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async () => {
|
||||||
|
return await fetch("https://api.projectsegfau.lt/api/v1/status").then((res) => res.json());
|
||||||
|
}
|
@ -1,16 +1,14 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
import { CardInner, CardOuter, LinksOuter, Link } from "$lib/Card";
|
import { CardInner, CardOuter, LinksOuter, Link } from "$lib/Card";
|
||||||
import instances from "$lib/Instances.json";
|
import dayjs from "dayjs";
|
||||||
|
import type { PageData } from "../$types";
|
||||||
|
|
||||||
let groups = instances.reduce((curr, val) => {
|
export let data: PageData;
|
||||||
let group = curr.find((g) => g.category === `${val.category}`);
|
|
||||||
if (group) {
|
let groups = [
|
||||||
group.values.push(val);
|
{name: "General", data: data.status.General},
|
||||||
} else {
|
{name: "Internal", data: data.status.Internal}
|
||||||
curr.push({ category: `${val.category}`, values: [val] });
|
]
|
||||||
}
|
|
||||||
return curr;
|
|
||||||
}, []);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@ -19,14 +17,17 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<h1>Our instances</h1>
|
<h1>Our instances</h1>
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
<CardOuter>
|
<CardOuter>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
{#each groups as group}
|
{#each groups as group}
|
||||||
<h2>{group.category}</h2>
|
<h2>{group.name}</h2>
|
||||||
<div class="items">
|
<div class="items">
|
||||||
{#each group.values as item}
|
{#each group.data as item}
|
||||||
<CardInner
|
<CardInner
|
||||||
title={item.name}
|
title={item.name}
|
||||||
|
position={item.status === 200 ? "Up" : "Down"}
|
||||||
|
positionStyles={item.status === 200 ? "color: #4ade80;" : "color: #f87171;"}
|
||||||
description={item.description}
|
description={item.description}
|
||||||
icon={item.icon}
|
icon={item.icon}
|
||||||
>
|
>
|
||||||
@ -51,6 +52,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</CardOuter>
|
</CardOuter>
|
||||||
|
|
||||||
|
<span>Last updated: {dayjs
|
||||||
|
.unix(data.updated)
|
||||||
|
.format("DD/MM/YYYY HH:mm:ss")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.wrapper {
|
.wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import adapter from "@sveltejs/adapter-static";
|
import adapter from "@sveltejs/adapter-node";
|
||||||
import preprocess from "svelte-preprocess";
|
import preprocess from "svelte-preprocess";
|
||||||
import { mdsvex } from "mdsvex";
|
import { mdsvex } from "mdsvex";
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user