Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion website-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@types/node": "22.7.5",
"@types/sanitize-html": "^2.16.0",
"autoprefixer": "10.4.20",
"bits-ui": "^0.22.0",
"bits-ui": "0.22.0",
"clsx": "^2.1.1",
"embla-carousel-svelte": "^8.6.0",
"eslint": "^9.30.1",
Expand Down
2 changes: 1 addition & 1 deletion website-frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions website-frontend/src/lib/@shadcn-svelte/ui/pagination/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Root from "./pagination.svelte";
import Content from "./pagination-content.svelte";
import Item from "./pagination-item.svelte";
import Link from "./pagination-link.svelte";
import PrevButton from "./pagination-prev-button.svelte";
import NextButton from "./pagination-next-button.svelte";
import Ellipsis from "./pagination-ellipsis.svelte";

export {
Root,
Content,
Item,
Link,
PrevButton,
NextButton,
Ellipsis,
//
Root as Pagination,
Content as PaginationContent,
Item as PaginationItem,
Link as PaginationLink,
PrevButton as PaginationPrevButton,
NextButton as PaginationNextButton,
Ellipsis as PaginationEllipsis,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/@shadcn-svelte/utils.js";

type $$Props = HTMLAttributes<HTMLUListElement>;

let className: $$Props["class"] = undefined;
export { className as class };
</script>

<ul class={cn("flex flex-row items-center gap-1", className)} {...$$restProps}>
<slot />
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import Ellipsis from "lucide-svelte/icons/ellipsis";
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/@shadcn-svelte/utils.js";

type $$Props = HTMLAttributes<HTMLSpanElement>;

let className: $$Props["class"] = undefined;
export { className as class };
</script>

<span
aria-hidden="true"
class={cn("flex h-9 w-9 items-center justify-center", className)}
{...$$restProps}
>
<Ellipsis class="h-4 w-4" />
<span class="sr-only">More pages</span>
</span>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/@shadcn-svelte/utils.js";

type $$Props = HTMLAttributes<HTMLLIElement>;
let className: $$Props["class"] = undefined;

export { className as class };
</script>

<li class={cn("", className)} {...$$restProps}>
<slot />
</li>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script lang="ts">
import { Pagination as PaginationPrimitive } from "bits-ui";
import { cn } from "$lib/@shadcn-svelte/utils.js";
import { type Props, buttonVariants } from "$lib/@shadcn-svelte//ui/button/index.js";

type $$Props = PaginationPrimitive.PageProps &
Props & {
isActive: boolean;
};

type $$Events = PaginationPrimitive.PageEvents;

let className: $$Props["class"] = undefined;
export let page: $$Props["page"];
export let size: $$Props["size"] = "icon";
export let isActive: $$Props["isActive"] = false;

export { className as class };
</script>

<PaginationPrimitive.Page
bind:page
class={cn(
buttonVariants({
variant: isActive ? "outline" : "ghost",
size,
}),
className
)}
{...$$restProps}
on:click
>
<slot>{page.value}</slot>
</PaginationPrimitive.Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { Pagination as PaginationPrimitive } from "bits-ui";
import ChevronRight from "lucide-svelte/icons/chevron-right";
import { Button } from "$lib/@shadcn-svelte//ui/button/index.js";
import { cn } from "$lib/@shadcn-svelte/utils.js";

type $$Props = PaginationPrimitive.NextButtonProps;
type $$Events = PaginationPrimitive.NextButtonEvents;

let className: $$Props["class"] = undefined;
export { className as class };
</script>

<PaginationPrimitive.NextButton asChild let:builder>
<Button
variant="ghost"
class={cn("gap-1 pr-2.5", className)}
builders={[builder]}
on:click
{...$$restProps}
>
<slot>
<span>Next</span>
<ChevronRight class="h-4 w-4" />
</slot>
</Button>
</PaginationPrimitive.NextButton>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { Pagination as PaginationPrimitive } from "bits-ui";
import ChevronLeft from "lucide-svelte/icons/chevron-left";
import { Button } from "$lib/@shadcn-svelte//ui/button/index.js";
import { cn } from "$lib/@shadcn-svelte/utils.js";

type $$Props = PaginationPrimitive.PrevButtonProps;
type $$Events = PaginationPrimitive.PrevButtonEvents;

let className: $$Props["class"] = undefined;
export { className as class };
</script>

<PaginationPrimitive.PrevButton asChild let:builder>
<Button
variant="ghost"
class={cn("gap-1 pl-2.5", className)}
builders={[builder]}
on:click
{...$$restProps}
>
<slot>
<ChevronLeft class="h-4 w-4" />
<span>Previous</span>
</slot>
</Button>
</PaginationPrimitive.PrevButton>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script lang="ts">
import { Pagination as PaginationPrimitive } from "bits-ui";

import { cn } from "$lib/@shadcn-svelte/utils.js";

type $$Props = PaginationPrimitive.Props;
type $$Events = PaginationPrimitive.Events;

let className: $$Props["class"] = undefined;
export let count: $$Props["count"] = 0;
export let perPage: $$Props["perPage"] = 10;
export let page: $$Props["page"] = 1;
export let siblingCount: $$Props["siblingCount"] = 1;
export { className as class };

$: currentPage = page;
</script>

<PaginationPrimitive.Root
{count}
{perPage}
{siblingCount}
bind:page
let:builder
let:pages
let:range
asChild
{...$$restProps}
>
<nav {...builder} class={cn("mx-auto flex w-full flex-col items-center", className)}>
<slot {pages} {range} {currentPage} />
</nav>
</PaginationPrimitive.Root>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { PUBLIC_APIURL } from '$env/static/public';
import { Event } from '$lib/models/event';
import { Event } from '$lib/models/events';
import { Calendar, MapPin, Clock, Image } from 'lucide-svelte';
import { reloading } from '$lib/stores';
export let item: Event;
Expand Down
99 changes: 76 additions & 23 deletions website-frontend/src/lib/components/loading/Await.svelte
Original file line number Diff line number Diff line change
@@ -1,34 +1,87 @@
<script lang="ts">
/** @type {import('./$types').PageData} */
import { Moon } from 'svelte-loading-spinners';
import { Frown } from 'lucide-svelte';
import { ChevronsUp, Frown, Plus } from 'lucide-svelte';
import { page } from '$app/stores';
import { goto } from '$app/navigation';

export let onDark = false;
export let layout;
export let data;
export let text;
export let component;
export let count;
export let limit: number;

$: query = new URLSearchParams($page.url.searchParams.toString());
$: currentLimit = parseInt(query.get('limit') ?? limit.toString());

function nav(newLimit: number): void {
query.delete('limit');
if (newLimit > limit) {
query.append('limit', newLimit.toString());
}
goto(`?${query.toString()}`, { noScroll: true, keepFocus: true });
}
</script>

{#await data}
<div class="flex flex-col items-center justify-center gap-5">
<Moon
size="90"
color={onDark ? 'hsl(0, 0%, 100%)' : 'hsl(144, 69%, 24%)'}
unit="px"
duration="1s"
/>
<p>Loading {text}...</p>
</div>
{:then data}
<div class={layout}>
{#each data as item}
<svelte:component this={component} {item} />
{/each}
</div>
{:catch}
<div class="flex flex-col items-center justify-center gap-5">
<Frown size="90" color={onDark ? 'hsl(0, 0%, 100%)' : 'hsl(144, 69%, 24%)'} />
<p>Error loading {text}. Please try refreshing the page.</p>
</div>
{/await}
<div class="flex flex-col gap-y-2">
{#await data}
<div class="flex flex-col items-center justify-center gap-5">
<Moon
size="90"
color={onDark ? 'hsl(0, 0%, 100%)' : 'hsl(144, 69%, 24%)'}
unit="px"
duration="1s"
/>
<p class={onDark ? 'text-[hsl(0, 0%, 100%)]' : 'text-[hsl(144, 69%, 24%)]'}>
Loading {text}...
</p>
</div>
{:then data}
<div class={layout}>
{#each data as item}
<svelte:component this={component} {item} />
{/each}
</div>
<div class="flex flex-col items-center gap-2">
<div class="flex items-center justify-center gap-1">
{#if data.length < count}
<button
class="flex items-center rounded-3xl px-6 py-2 shadow-xl"
on:click={() => nav(currentLimit + limit)}
>
<Plus color={onDark ? 'hsl(0, 0%, 100%)' : 'hsl(144, 69%, 24%)'} class="mr-2 h-4 w-4" />
<span class={onDark ? 'text-[hsl(0, 0%, 100%)]' : 'text-[hsl(144, 69%, 24%)]'}
>Load More</span
>
</button>
{/if}
{#if data.length > limit}
<button
class="flex items-center rounded-3xl px-6 py-2 shadow-xl"
on:click={() => nav(limit)}
>
<ChevronsUp
color={onDark ? 'hsl(0, 0%, 100%)' : 'hsl(144, 69%, 24%)'}
class="mr-2 h-4 w-4"
/>
<span class={onDark ? 'text-[hsl(0, 0%, 100%)]' : 'text-[hsl(144, 69%, 24%)]'}
>Collapse</span
>
</button>
{/if}
</div>
<small class={onDark ? 'text-[hsl(0, 0%, 100%)]' : 'text-[hsl(144, 69%, 24%)]'}
>Showing {Math.min(currentLimit, count)} items out of {count}</small
>
</div>
{:catch}
<div class="flex flex-col items-center justify-center gap-5">
<Frown size="90" color={onDark ? 'hsl(0, 0%, 100%)' : 'hsl(144, 69%, 24%)'} />
<p class={onDark ? 'text-[hsl(0, 0%, 100%)]' : 'text-[hsl(144, 69%, 24%)]'}>
Error loading {text}. Please try refreshing the page.
</p>
</div>
{/await}
</div>
1 change: 1 addition & 0 deletions website-frontend/src/lib/components/nav/NavList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<NavItem href="/about/{about_page.slug}" to={about_page.title ?? `About Page ${i}`} />
{/each}
</NavItem>
<NavItem href="/news" to="News" />
<NavItem href="/events" to="Events" />
<NavItem href="/people" to="People" dropdown={true}>
{#each people_categories as people_category, i}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<NavItemMobile href="/about/{about_page.slug}" to={about_page.title ?? `About Page ${i}`} />
{/each}
</NavItemMobile>
<NavItemMobile href="/news" to="News" />
<NavItemMobile href="/events" to="Events" />
<NavItemMobile href="/people" to="People" dropdown={true}>
{#each people_categories as people_category, i}
Expand Down
2 changes: 1 addition & 1 deletion website-frontend/src/lib/components/table/Calendar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Button } from '$lib/@shadcn-svelte/ui/button';
import { Card } from '$lib/@shadcn-svelte/ui/card';
import { ChevronLeft, ChevronRight, MapPin, Image } from 'lucide-svelte';
import type { Events } from '$lib/models/event';
import type { Events } from '$lib/models/events';
import { PUBLIC_APIURL } from '$env/static/public';

export let events: Events;
Expand Down Expand Up @@ -184,7 +184,7 @@
? 'line-clamp-1'
: 'line-clamp-2'}"
>
{@html event.event_content}

Check warning on line 187 in website-frontend/src/lib/components/table/Calendar.svelte

View workflow job for this annotation

GitHub Actions / test

`{@html}` can lead to XSS attack
</div>
{:else}
<div class="text-base italic text-slate-400">No description provided</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { array, lazy, object, partial, string, union, type GenericSchema } from 'valibot';
import { Event } from '../event';
import { Event } from '../events';

import { Laboratory } from '../laboratories';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { array, lazy, object, partial, string, union, type GenericSchema } from 'valibot';
import { Event } from '../event';
import { Event } from '../events';
import { EventsTag } from '../events_tags';

export type EventsRelated = {
Expand Down
2 changes: 1 addition & 1 deletion website-frontend/src/lib/models/junctions/recent_events.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { array, lazy, object, partial, string, union, type GenericSchema } from 'valibot';
import { Event } from '../event';
import { Event } from '../events';

export type RecentEvents = {
events_id?: string | Event;
Expand Down
9 changes: 9 additions & 0 deletions website-frontend/src/lib/models/news_overview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { nullable, object, partial, string, type InferOutput } from 'valibot';

export const NewsOverview = partial(
object({
background_image: nullable(string())
})
);

export type NewsOverview = InferOutput<typeof NewsOverview>;
Loading
Loading