use unocss, add blog, ui changes

This commit is contained in:
2022-12-27 17:28:47 +02:00
parent a6c4014327
commit ec15fac578
51 changed files with 838 additions and 732 deletions

6
src/routes/+error.svelte Normal file
View File

@@ -0,0 +1,6 @@
<script lang="ts">
import { page } from '$app/stores';
</script>
<h1>{$page.status}: {$page.error?.message}</h1>
<span class="italic">The fetch request to the API probably failed, please contact us on Matrix.</span>

View File

@@ -30,7 +30,8 @@
<script
defer
data-domain="projectsegfau.lt"
src="https://analytics.projectsegfau.lt/js/plausible.js"></script>
src="https://analytics.projectsegfau.lt/js/plausible.js"
></script>
</svelte:head>
<Nav />

View File

@@ -3,10 +3,16 @@ import { compile } from "mdsvex";
import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async () => {
return {
state: await fetch(env.VITE_API_URL + "/api/v1/state/announcements").then((res) => res.json()),
announcements: await fetch(env.VITE_API_URL + "/api/v1/announcements").then((res) => res.json()),
content: await fetch(env.VITE_API_URL + "/api/v1/announcements").then((res) => res.json()).then((res) => compile(res.title)).then((res) => res.code)
}
}
return {
state: await fetch(
env.VITE_API_URL + "/api/v1/state/announcements"
).then((res) => res.json()).catch(() => ({})),
announcements: await fetch(
env.VITE_API_URL + "/api/v1/announcements"
).then((res) => res.json()).catch(() => ({})),
content: await fetch(env.VITE_API_URL + "/api/v1/announcements")
.then((res) => res.json())
.then((res) => compile(res.title))
.then((res) => res?.code).catch(() => ({})),
};
};

View File

@@ -2,25 +2,27 @@
import SvelteSeo from "svelte-seo";
import Hero from "$lib/Hero.svelte";
import LinkButton from "$lib/LinkButton.svelte";
import dayjs from "dayjs";
import Announcements from "./Announcements.svelte";
import type { PageData } from "./$types";
export let data: PageData;
let announcements = data.announcements;
export let data: PageData;
let description: string = "Open source development and hosted services.";
</script>
<SvelteSeo title="Home | Project Segfault" {description} />
<SvelteSeo
title="Home | Project Segfault"
{description}
/>
<Hero
title="Project Segfault"
{description}
marginTop=7
marginTop="4"
>
<div class="buttons">
<div
class="flex flex-col sm:flex-row justify-center items-center gap-4 m-4"
>
<LinkButton
url="/instances"
title="Explore our instances"
@@ -36,117 +38,4 @@
</div>
</Hero>
{#if data.state.enabled}
{#if !announcements.error}
<div class="announcements">
<div class="announcement-container">
<div class="announcement">
<div class="flex gap-4 flex-col sm:flex-row border-b-2 p-2 pt-0">
{#if announcements.severity === "info"}
<div class="flex items-center gap-2">
<div class="i-fa6-solid:circle-info" />
<span>Info</span>
</div>
{:else}
<div class="flex items-center gap-2">
<div class="i-fa6-solid:triangle-exclamation" />
<span>Attention</span>
</div>
{/if}
<span class="flex items-center gap-2">
<div class="i-fa6-solid:user" />
{announcements.author}
</span>
<span class="flex items-center gap-2">
<div class="i-fa6-solid:calendar" />
{dayjs
.unix(announcements.created)
.format("DD/MM/YYYY HH:mm")}
</span>
</div>
<div class="title">
<div class="text-xl font-semibold font-[var(--font-primary)]">{@html data.content}</div>
</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: 1.5rem;
border-radius: 10px;
width: fit-content;
display: flex;
flex-direction: column;
gap: 1rem;
}
.announcement a {
color: #252525;
}
</style>
{/if}
{: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>
.buttons {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 1rem;
margin: 1rem;
}
@media screen and (max-width: 452px) {
.buttons {
flex-direction: column;
}
}
</style>
<Announcements {data} />

View File

@@ -0,0 +1,102 @@
<script lang="ts">
import type { PageData } from "./$types";
export let data: PageData;
let announcements = data.announcements;
import dayjs from "dayjs";
</script>
{#if data.state.enabled}
{#if !announcements.error}
<div class="announcements">
<div class="flex justify-center mt-16">
<div
class="announcement !text-[#252525] p-6 rounded-2 w-fit flex flex-col gap-4"
>
<div
class="flex gap-4 flex-col sm:flex-row border-b-2 p-2 pt-0"
>
{#if announcements.severity === "info"}
<div class="flex items-center gap-2">
<div class="i-fa6-solid:circle-info" />
<span>Info</span>
</div>
{:else if announcements.severity === "low"}
<div class="flex items-center gap-2">
<div class="i-fa6-solid:check" />
<span>Resolved</span>
</div>
{:else if announcements.severity === "medium"}
<div class="flex items-center gap-2">
<div class="i-fa6-solid:triangle-exclamation" />
<span>Attention</span>
</div>
{:else if announcements.severity === "high"}
<div class="flex items-center gap-2">
<div class="i-fa6-solid:ban" />
<span>Attention</span>
</div>
{/if}
<span class="flex items-center gap-2">
<div class="i-fa6-solid:user" />
{announcements.author}
</span>
<span class="flex items-center gap-2">
<div class="i-fa6-solid:calendar" />
{dayjs
.unix(announcements.created)
.format("DD/MM/YYYY HH:mm")}
</span>
</div>
<div class="title">
<div class="text-xl font-semibold font-primary">
{@html data.content}
</div>
</div>
{#if announcements.link}
<div class="read-more">
<a
href={announcements.link}
class="!text-[#252525]">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}
{/if}
{:else}
<div class="flex items-center gap-2 text-center justify-center mt-16">
<div class="i-fa6-solid:circle-info" />
<span>Announcements are currently disabled.</span>
</div>
{/if}

View File

@@ -0,0 +1,10 @@
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async () => {
return {
state: await fetch(env.VITE_API_URL + "/api/v1/state/blog").then(
(res) => res.json()
).catch(() => ({}))
};
};

View File

@@ -0,0 +1,14 @@
<script lang="ts">
import type { PageData } from "./$types";
export let data: PageData
</script>
{#if data.state.enabled}
<slot />
{:else}
<div class="flex items-center gap-2 text-center justify-center mt-16">
<div class="i-fa6-solid:circle-info" />
<span>The blog is currently disabled.</span>
</div>
{/if}

View File

@@ -0,0 +1,10 @@
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async () => {
return {
posts: await fetch(env.VITE_API_URL + "/api/v1/blog").then(
(res) => res.json()
).catch(() => ({}))
};
};

View File

@@ -0,0 +1,61 @@
<script lang="ts">
import dayjs from "dayjs";
import Hero from "$lib/Hero.svelte";
import LinkButton from "$lib/LinkButton.svelte";
import type { PageData } from "./$types";
export let data: PageData;
</script>
<svelte:head>
<title>Timeline | Project Segfault</title>
<meta
name="description"
content="Timeline of Project Segfault's history."
/>
</svelte:head>
<Hero marginTop="4">
<h1 class="text-5xl font-800">
<span class="text-accent">Project Segfault</span> blog
</h1>
<div
class="flex flex-col sm:flex-row justify-center items-center gap-4 m-4"
>
<LinkButton
url="/blog/tags"
title="Tags"
icon="i-fa6-solid:tags"
/>
<LinkButton
url="/blog/authors"
title="Authors"
icon="i-fa6-solid:user"
/>
</div>
</Hero>
<div class="flex flex-col gap-10 mt-16">
{#each data.posts as post}
<div class="flex flex-col gap-4 bg-secondary p-4 rounded-2">
<span class="text-xl font-bold">{post.title}</span>
<div class="flex flex-col md:(flex-row gap-4) gap-2">
{#if post.tags.length > 0}
<div class="flex flex-row items-center gap-2">
<div class="i-fa6-solid:tags" />
{#each post.tags as tag}
<a href="/blog/tags/{tag}" class="no-underline">{tag}</a>
{/each}
</div>
{/if}
<a href="/blog/authors/{post.author}" class="flex items-center gap-2 no-underline"><div class="i-fa6-solid:user" />{post.author}</a>
<span class="flex items-center gap-2"><div class="i-fa6-solid:calendar" /> {dayjs
.unix(post.created)
.format("ddd, DD MMM YYYY HH:mm")}</span>
<span class="flex items-center gap-2"><div class="i-fa6-solid:pencil" /> {post.words} words</span>
<span class="flex items-center gap-2"><div class="i-fa6-solid:book-open-reader" /> {post.readingTime} minute read</span>
</div>
<span>{post.content.split(" ").slice(0, 20).join(" ") + "..."}</span>
<a href="/blog/{post.title}">Read more...</a>
</div>
{/each}
</div>

View File

@@ -0,0 +1,16 @@
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";
import { compile } from "mdsvex";
export const load: PageServerLoad = async ({ params }) => {
return {
post: await fetch(env.VITE_API_URL + "/api/v1/blog/" + params.title).then(
(res) => res.json()
).catch(() => ({})),
content: await fetch(env.VITE_API_URL + "/api/v1/blog/" + params.title)
.then((res) => res.json())
.then((res) => compile(res.content))
.then((res) => res?.code)
.catch(() => ({})),
};
};

View File

@@ -0,0 +1,26 @@
<script lang="ts">
import dayjs from "dayjs";
import type { PageData } from "./$types";
export let data: PageData;
</script>
<div class="flex flex-col gap-4 bg-secondary p-4 rounded-2">
<span class="text-xl font-bold flex flex-row items-center gap-2"><a href="/blog" class="flex flex-row items-center gap-2"><div class="i-fa6-solid:arrow-left" /> Back</a> - {data.post.title}</span>
<div class="flex flex-col md:(flex-row gap-4) gap-2">
{#if data.post.tags.length > 0}
<div class="flex flex-row items-center gap-2">
<div class="i-fa6-solid:tags" />
{#each data.post.tags as tag}
<a href="/blog/tags/{tag}" class="no-underline">{tag}</a>
{/each}
</div>
{/if}
<a href="/blog/authors/{data.post.author}" class="flex items-center gap-2 no-underline"><div class="i-fa6-solid:user" />{data.post.author}</a>
<span class="flex items-center gap-2"><div class="i-fa6-solid:calendar" /> {dayjs
.unix(data.post.created)
.format("ddd, DD MMM YYYY HH:mm")}</span>
<span class="flex items-center gap-2"><div class="i-fa6-solid:pencil" /> {data.post.words} words</span>
<span class="flex items-center gap-2"><div class="i-fa6-solid:book-open-reader" /> {data.post.readingTime} minute read</span>
</div>
{@html data.content}
</div>

View File

@@ -0,0 +1,10 @@
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async ({ params }) => {
return {
authors: await fetch(env.VITE_API_URL + "/api/v1/blog/authors").then(
(res) => res.json()
).catch(() => ({})),
};
};

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import type { PageData } from "./$types";
export let data: PageData;
</script>
<h1>Blog authors</h1>
<div class="flex flex-col gap-4">
{#each data.authors as author}
<a href="/blog/authors/{author}" class="bg-secondary w-fit p-2 rounded-2 no-underline">{author}</a>
{/each}
</div>

View File

@@ -0,0 +1,11 @@
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async ({ params }) => {
return {
posts: await fetch(env.VITE_API_URL + "/api/v1/blog/authors/" + params.author).then(
(res) => res.json()
).catch(() => ({})),
authorName: params.author
};
};

View File

@@ -0,0 +1,33 @@
<script lang="ts">
import dayjs from "dayjs";
import type { PageData } from "./$types";
export let data: PageData;
</script>
<h1>Blog author {data.authorName}</h1>
<div class="flex flex-col gap-10">
{#each data.posts as post}
<div class="flex flex-col gap-4 bg-secondary p-4 rounded-2">
<span class="text-xl font-bold">{post.title}</span>
<div class="flex flex-col md:(flex-row gap-4) gap-2">
{#if post.tags.length > 0}
<div class="flex flex-row items-center gap-2">
<div class="i-fa6-solid:tags" />
{#each post.tags as tag}
<a href="/blog/tags/{tag}" class="no-underline">{tag}</a>
{/each}
</div>
{/if}
<a href="/blog/authors/{post.author}" class="flex items-center gap-2 no-underline"><div class="i-fa6-solid:user" />{post.author}</a>
<span class="flex items-center gap-2"><div class="i-fa6-solid:calendar" /> {dayjs
.unix(post.created)
.format("ddd, DD MMM YYYY HH:mm")}</span>
<span class="flex items-center gap-2"><div class="i-fa6-solid:pencil" /> {post.words} words</span>
<span class="flex items-center gap-2"><div class="i-fa6-solid:book-open-reader" /> {post.readingTime} minute read</span>
</div>
<span>{post.content.split(" ").slice(0, 20).join(" ") + "..."}</span>
<a href="/blog/{post.title}">Read more...</a>
</div>
{/each}
</div>

View File

@@ -0,0 +1,10 @@
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async ({ params }) => {
return {
tags: await fetch(env.VITE_API_URL + "/api/v1/blog/tags").then(
(res) => res.json()
).catch(() => ({})),
};
};

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import type { PageData } from "./$types";
export let data: PageData;
</script>
<h1>Blog tags</h1>
<div class="flex flex-col gap-4">
{#each data.tags as tag}
<a href="/blog/tags/{tag}" class="bg-secondary w-fit p-2 rounded-2 no-underline">{tag}</a>
{/each}
</div>

View File

@@ -0,0 +1,11 @@
import type { PageServerLoad } from "./$types";
import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async ({ params }) => {
return {
posts: await fetch(env.VITE_API_URL + "/api/v1/blog/tags/" + params.tag).then(
(res) => res.json()
).catch(() => ({})),
tagName: params.tag
};
};

View File

@@ -0,0 +1,33 @@
<script lang="ts">
import dayjs from "dayjs";
import type { PageData } from "./$types";
export let data: PageData;
</script>
<h1>Blog tag {data.tagName}</h1>
<div class="flex flex-col gap-10">
{#each data.posts as post}
<div class="flex flex-col gap-4 bg-secondary p-4 rounded-2">
<span class="text-xl font-bold">{post.title}</span>
<div class="flex flex-col md:(flex-row gap-4) gap-2">
{#if post.tags.length > 0}
<div class="flex flex-row items-center gap-2">
<div class="i-fa6-solid:tags" />
{#each post.tags as tag}
<a href="/blog/tags/{tag}" class="no-underline">{tag}</a>
{/each}
</div>
{/if}
<a href="/blog/authors/{post.author}" class="flex items-center gap-2 no-underline"><div class="i-fa6-solid:user" />{post.author}</a>
<span class="flex items-center gap-2"><div class="i-fa6-solid:calendar" /> {dayjs
.unix(post.created)
.format("ddd, DD MMM YYYY HH:mm")}</span>
<span class="flex items-center gap-2"><div class="i-fa6-solid:pencil" /> {post.words} words</span>
<span class="flex items-center gap-2"><div class="i-fa6-solid:book-open-reader" /> {post.readingTime} minute read</span>
</div>
<span>{post.content.split(" ").slice(0, 20).join(" ") + "..."}</span>
<a href="/blog/{post.title}">Read more...</a>
</div>
{/each}
</div>

View File

@@ -2,8 +2,10 @@ import type { PageServerLoad } from "../$types";
import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async () => {
return {
state: await fetch(env.VITE_API_URL + "/api/v1/state/form").then((res) => res.json()),
apiUrl: env.VITE_API_URL
}
}
return {
state: await fetch(env.VITE_API_URL + "/api/v1/state/form").then(
(res) => res.json()
).catch(() => ({})),
apiUrl: env.VITE_API_URL
};
};

View File

@@ -1,60 +1,65 @@
<script lang="ts">
import { Note, Captcha, Form, Meta, TextArea } from "$lib/Form";
import { Note, Captcha, Form, Meta, TextArea } from "$lib/Form";
import type { PageData } from "./$types";
export let data: PageData;
export let data: PageData;
let title = "Contact us | Project Segfault";
let description = "Do you want to contact us? (you don't)";
let title = "Contact us | Project Segfault";
</script>
<svelte:head>
<title>{title}</title>
<meta name="description" content={description}>
<title>{title}</title>
</svelte:head>
<h1>Contact us</h1>
<span>{description}</span>
<div class="contact-form">
<h2>Contact form</h2>
{#if data.state.enabled === true}
<Form
action="{data.apiUrl}/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}
<h2>Contact form</h2>
{#if data.state.enabled === true}
<Form
action="{data.apiUrl}/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-2">
<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" />
<Note
content="The contact form does not work without JavaScript enabled."
icon="i-fa6-solid:circle-info"
/>
<style>
.contact-form {
display: none;
@@ -62,16 +67,29 @@
</style>
</noscript>
<h2>Matrix</h2>
<span
>We have a Matrix space for general discussion, support and announcements
about Project Segfault over at <a
href="https://matrix.to/#/#project-segfault:projectsegfau.lt/"
>this link</a
>.</span
>
<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!
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>.
You can find ways to contact individual team members <a href="/team"
>on our team page</a
>.
</span>

View File

@@ -1,26 +0,0 @@
---
title: Frequently Asked Questions
description: Frequently Asked Questions
---
# { title }
## Who is the project owner?
There are two owners that operate Project Segfault, Midou and Mrlerien. A list of the people involved and their positions can be found [on our members page](/team).
## What's the backstory to Project Segfault?
We have a rather interesting backstory, if I do say so myself. [Click here to see a timeline of things that happened in Project Segfault's history](/timeline).
## One of your services contains toxic people!
You can contact us by mail or Matrix and we can figure this out with you. But we recommend that you put most of these requests in our support channel at [#support:projectsegfau.lt](https://matrix.to/#/#support:projectsegfau.lt) on Matrix. If it's something personal, just say that you have a report against someone on one of our services and you'd like to be contacted by an admin and we'll contact you as soon as possible. We generally tend to be active throughout the day.
## How can I trust your services?
Well, you really can't. We don't make our logs or anything else public, however, if you would like access to the data we have on you, please contact us. If you're extremely privacy/security conscious, **you are allowed to use Tor on our services**, but we don't host any `.onion` links.
## Which ways do you prefer to communicate?
Look at [Contact](/contact).

View File

@@ -3,7 +3,11 @@ import { env } from "$env/dynamic/private";
export const load: PageServerLoad = async () => {
return {
state: await fetch(env.VITE_API_URL + "/api/v1/state/status").then((res) => res.json()),
instances: await fetch(env.VITE_API_URL + "/api/v1/status").then((res) => res.json())
}
}
state: await fetch(env.VITE_API_URL + "/api/v1/state/status").then(
(res) => res.json()
).catch(() => ({})),
instances: await fetch(env.VITE_API_URL + "/api/v1/status").then(
(res) => res.json()
).catch(() => ({}))
};
};

View File

@@ -1,15 +1,18 @@
<script lang="ts">
import { CardInner, CardOuter, LinksOuter } from "$lib/Card";
import InstanceLink from "./InstanceLink.svelte";
import dayjs from "dayjs";
import InstanceLink from "./InstanceLink.svelte";
import dayjs from "dayjs";
import type { PageData } from "./$types";
export let data: PageData;
export let data: PageData;
</script>
<svelte:head>
<title>Our instances | Project Segfault</title>
<meta name="description" content="Our collection of instances." />
<meta
name="description"
content="Our collection of instances."
/>
</svelte:head>
<h1>Our instances</h1>
@@ -17,10 +20,10 @@
{#if data.state.enabled}
<div class="flex flex-col gap-4">
<CardOuter>
<div class="wrapper">
<div class="flex flex-col">
{#each data.instances.status as group}
<h2>{group.name}</h2>
<div class="items">
<div class="flex flex-row flex-wrap gap-8">
{#each group.data as item}
<CardInner
title={item.name}
@@ -28,14 +31,26 @@
icon={item.icon}
>
<LinksOuter>
<InstanceLink url={item.link} item={item.status} type="main" />
<InstanceLink
url={item.link}
item={item.status}
type="main"
/>
{#if item.us}
<InstanceLink url={item.us} item={item.statusUs} type="us" />
<InstanceLink
url={item.us}
item={item.statusUs}
type="us"
/>
{/if}
{#if item.bp}
<InstanceLink url={item.bp} item={item.statusBp} type="backup" />
<InstanceLink
url={item.bp}
item={item.statusBp}
type="backup"
/>
{/if}
</LinksOuter>
</CardInner>
@@ -44,29 +59,16 @@
{/each}
</div>
</CardOuter>
<span>Last updated: {dayjs
.unix(data.instances.updated)
.format("DD/MM/YYYY HH:mm:ss")}
<span class="bg-accent w-fit p-2 rounded-2 text-primary"
>Instances status last updated: {dayjs
.unix(data.instances.updated)
.format("DD/MM/YYYY HH:mm:ss")}
</span>
</div>
<style>
.wrapper {
display: flex;
flex-direction: column;
}
.items {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 2rem;
}
</style>
{:else}
<div class="flex items-center gap-1 mt-16">
<div class="i-fa6-solid:circle-info" />
<span>Instances are currently disabled.</span>
</div>
{:else}
<div class="flex items-center gap-2 mt-16">
<div class="i-fa6-solid:circle-info" />
<span>Instances are currently disabled.</span>
</div>
{/if}

View File

@@ -1,31 +1,34 @@
<script lang="ts">
import { Link } from "$lib/Card";
import { Link } from "$lib/Card";
export let url: string;
export let item: any;
export let type: "main" | "us" | "backup";
export let url: string;
export let item: any;
export let type: "main" | "us" | "backup";
</script>
<Link {url} class="web {item === true ? "" : "pointer-events-none cursor-default opacity-50"}">
<div class="withText">
<div class="{item === true ? "i-fa6-solid:arrow-up-right-from-square" : "i-fa6-solid:xmark"}" />
<span>
{#if type === "main"}
Visit
{:else if type === "us"}
US
{:else if type === "backup"}
Backup
{/if}
</span>
</div>
<Link
{url}
class="web {item === 200
? ''
: 'pointer-events-none cursor-default opacity-50'}"
>
<div class="flex items-center gap-2 text-base">
<div
class={item === 200
? "i-fa6-solid:arrow-up-right-from-square"
: "i-fa6-solid:xmark"}
/>
<span>
{#if item !== 200}
({item})
{/if}
{#if type === "main"}
Visit
{:else if type === "us"}
US
{:else if type === "backup"}
Backup
{/if}
</span>
</div>
</Link>
<style>
.withText {
display: flex;
align-items: center;
gap: 4px;
font-size: medium;
}
</style>

View File

@@ -9,3 +9,13 @@ Since we care about transparency, privacy and safety we have created some docume
- [Privacy Policy](/legal/privacy-policy)
- [Terms of Service](/legal/tos)
- [Transparency reports](https://git.projectsegfau.lt/ProjectSegfault/transparency/)
## Legal FAQ
### One of your services contains toxic people!
You can contact us by mail or Matrix and we can figure this out with you. But we recommend that you put most of these requests in our support channel at [#support:projectsegfau.lt](https://matrix.to/#/#support:projectsegfau.lt) on Matrix. If it's something personal, just say that you have a report against someone on one of our services and you'd like to be contacted by an admin and we'll contact you as soon as possible. We generally tend to be active throughout the day.
### How can I trust your services?
Well, you really can't. We don't make our logs or anything else public, however, if you would like access to the data we have on you, please contact us. If you're extremely privacy/security conscious, **you are allowed to use Tor on our services**, but we don't host any `.onion` links.

View File

@@ -5,58 +5,89 @@
<svelte:head>
<title>Our team | Project Segfault</title>
<meta name="description" content="Team members of Project Segfault." />
<meta
name="description"
content="Team members of Project Segfault."
/>
</svelte:head>
<h1>Our team</h1>
<CardOuter>
{#each members as { name, discord, matrix, position, description, github, git, pgp, website, email, picture }}
<CardInner title={name} {position} {description}>
<CardInner
title={name}
{position}
{description}
>
<LinksOuter>
{#if matrix}
<Link url={matrix} class="matrixcolored">
<Link
url={matrix}
class="matrixcolored"
>
<div class="i-simple-icons:matrix" />
</Link>
{/if}
{#if discord}
<Link url={discord} class="discordcolored">
<Link
url={discord}
class="discordcolored"
>
<div class="i-simple-icons:discord" />
</Link>
{/if}
{#if github}
<Link url={github} class="githubcolored">
<Link
url={github}
class="githubcolored"
>
<div class="i-simple-icons:github" />
</Link>
{/if}
{#if git}
<Link url={git} class="gitcolored">
<Link
url={git}
class="gitcolored"
>
<div class="i-simple-icons:git" />
</Link>
{/if}
{#if website}
<Link url={website} class="web">
<Link
url={website}
class="web"
>
<div class="i-fa6-solid:globe" />
</Link>
{/if}
{#if email}
<Link url="mailto:{email}" class="email">
<Link
url="mailto:{email}"
class="email"
>
<div class="i-fa6-solid:envelope" />
</Link>
{/if}
{#if pgp}
<Link url={pgp} class="pgp">
<Link
url={pgp}
class="pgp"
>
<div class="i-fa6-solid:key" />
</Link>
{/if}
{#if picture}
<Link url={picture} class="picture">
<Link
url={picture}
class="picture"
>
<div class="i-fa6-solid:camera" />
</Link>
{/if}

View File

@@ -19,8 +19,11 @@
/>
</svelte:head>
<Hero>
<h1>A timeline of <span>Project Segfault</span>'s history</h1>
<Hero marginTop="4">
<h1 class="text-5xl font-800">
A timeline of <span class="text-accent">Project Segfault</span>'s
history
</h1>
</Hero>
<Timeline position="alternate">
@@ -245,14 +248,3 @@
</TimelineContent>
</TimelineItem>
</Timeline>
<style>
h1 {
font-size: 50px;
font-weight: 800;
}
span {
color: var(--accent);
}
</style>