7 Commits

Author SHA1 Message Date
schreifuchs aae537b312 chore: add docker-hub login to pipeline
Commit / ci (push) Successful in 10m42s
2026-04-05 10:32:22 +02:00
schreifuchs 19238edf57 Merge pull request 'Implement Pagination / Limit for the Dashboard' (#18) from issue-6 into main
Commit / ci (push) Waiting to run
Reviewed-on: #18
2026-04-05 10:13:26 +02:00
schreifuchs 0de1cdfb8d revert: Docker base image to original
Commit / ci (push) Successful in 10m34s
PullRequest / publish (pull_request) Failing after 2m28s
2026-04-03 14:27:58 +02:00
schreifuchs 89c86a2d32 ci: fix docker hub rate limit with ecr mirror
Commit / ci (push) Has been cancelled
PullRequest / publish (pull_request) Successful in 4m38s
2026-04-03 13:57:34 +02:00
schreifuchs 070638b2f1 refactor: resolve conflicts and use queries helper
Commit / ci (push) Has been cancelled
PullRequest / publish (pull_request) Failing after 2m21s
2026-04-03 13:52:40 +02:00
schreifuchs f58af022dc feat: implement endless scrolling 2026-04-03 13:52:13 +02:00
schreifuchs 4475879330 feat: implement limit for the dashboard (resolves #6)
Commit / ci (push) Has been cancelled
PullRequest / publish (pull_request) Failing after 2m10s
2026-04-03 13:06:11 +02:00
7 changed files with 73 additions and 8 deletions
+3 -1
View File
@@ -3,7 +3,9 @@ name: Commit
on: on:
push: push:
# only trigger on branches, not on tags # only trigger on branches, not on tags
branches: '**' branches:
- 'main'
- 'dev'
jobs: jobs:
# Job 1: Lint and Test (Type Check) # Job 1: Lint and Test (Type Check)
+3 -1
View File
@@ -17,8 +17,10 @@ jobs:
http = true http = true
insecure = true insecure = true
- name: login - name: login gitea registry
run: docker login -u schreifuchs -p ${{ secrets.REGISTRY_TOKEN }} git.schreifuchs.ch run: docker login -u schreifuchs -p ${{ secrets.REGISTRY_TOKEN }} git.schreifuchs.ch
- name: login dockerhub
run: docker login -u aktitiel -p ${{ secrets.DOCKER_HUB_TOKEN}}
- name: Build and push Docker image - name: Build and push Docker image
uses: https://github.com/docker/build-push-action@v5 uses: https://github.com/docker/build-push-action@v5
with: with:
+3 -1
View File
@@ -18,8 +18,10 @@ jobs:
http = true http = true
insecure = true insecure = true
- name: login - name: login gitea registry
run: docker login -u schreifuchs -p ${{ secrets.REGISTRY_TOKEN }} git.schreifuchs.ch run: docker login -u schreifuchs -p ${{ secrets.REGISTRY_TOKEN }} git.schreifuchs.ch
- name: login dockerhub
run: docker login -u aktitiel -p ${{ secrets.DOCKER_HUB_TOKEN}}
- name: Build and push Docker image - name: Build and push Docker image
uses: https://github.com/docker/build-push-action@v5 uses: https://github.com/docker/build-push-action@v5
with: with:
+4 -2
View File
@@ -2,7 +2,7 @@ import { db } from '$lib/server/db';
import { aktis, ratings } from '$lib/server/db/schema'; import { aktis, ratings } from '$lib/server/db/schema';
import { avg, eq } from 'drizzle-orm'; import { avg, eq } from 'drizzle-orm';
export async function getAktisWithAvgRating() { export async function getAktisWithAvgRating(limit = 20, offset = 0) {
return await db return await db
.select({ .select({
id: aktis.id, id: aktis.id,
@@ -12,5 +12,7 @@ export async function getAktisWithAvgRating() {
}) })
.from(aktis) .from(aktis)
.leftJoin(ratings, eq(aktis.id, ratings.aktiId)) .leftJoin(ratings, eq(aktis.id, ratings.aktiId))
.groupBy(aktis.id, aktis.title, aktis.summary); .groupBy(aktis.id, aktis.title, aktis.summary)
.limit(limit)
.offset(offset);
} }
+5 -2
View File
@@ -1,8 +1,11 @@
import { getAktisWithAvgRating } from '$lib/server/db/queries'; import { getAktisWithAvgRating } from '$lib/server/db/queries';
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async () => { export const load: PageServerLoad = async ({ url }) => {
const a = await getAktisWithAvgRating(); const offset = Number(url.searchParams.get('offset')) || 0;
const limit = 20;
const a = await getAktisWithAvgRating(limit, offset);
return { return {
aktis: a.map((a) => ({ ...a, rating: a.rating ? parseFloat(a.rating) : undefined })) aktis: a.map((a) => ({ ...a, rating: a.rating ? parseFloat(a.rating) : undefined }))
+44 -1
View File
@@ -1,12 +1,55 @@
<script lang="ts"> <script lang="ts">
import AktiCard from '$lib/components/akti/AktiCard.svelte'; import AktiCard from '$lib/components/akti/AktiCard.svelte';
import type { PageProps } from './$types'; import type { PageProps } from './$types';
import { Spinner } from 'flowbite-svelte';
let { data }: PageProps = $props(); let { data }: PageProps = $props();
let aktis = $state(data.aktis);
let offset = $state(data.aktis.length);
let loading = $state(false);
let hasMore = $state(data.aktis.length >= 20);
async function loadMore() {
if (loading || !hasMore) return;
loading = true;
const res = await fetch(`/api/aktis?offset=${offset}`);
const newAktis = await res.json();
if (newAktis.length < 20) {
hasMore = false;
}
aktis = [...aktis, ...newAktis];
offset += newAktis.length;
loading = false;
}
function infiniteScroll(node: HTMLElement) {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
loadMore();
}
});
observer.observe(node);
return {
destroy() {
observer.disconnect();
}
};
}
</script> </script>
<div class="grid gap-5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 3xl:grid-cols-5"> <div class="grid gap-5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 3xl:grid-cols-5">
{#each data.aktis as akti (akti.id)} {#each aktis as akti (akti.id)}
<AktiCard {akti}></AktiCard> <AktiCard {akti}></AktiCard>
{/each} {/each}
</div> </div>
<div class="mt-10 flex justify-center h-20">
{#if loading}
<Spinner />
{:else if hasMore}
<div use:infiniteScroll></div>
{/if}
</div>
+11
View File
@@ -0,0 +1,11 @@
import { getAktisWithAvgRating } from '$lib/server/db/queries';
import { json, type RequestHandler } from '@sveltejs/kit';
export const GET: RequestHandler = async ({ url }) => {
const offset = Number(url.searchParams.get('offset')) || 0;
const limit = 20;
const a = await getAktisWithAvgRating(limit, offset);
return json(a.map((a) => ({ ...a, rating: a.rating ? parseFloat(a.rating) : undefined })));
};