Imported timelineItem in the codebase

This commit is contained in:
Clément Le Bihan
2024-05-05 18:43:15 +02:00
parent ac7e9f1a22
commit 6336bb144d
10 changed files with 191 additions and 32 deletions
+2
View File
@@ -42,6 +42,8 @@ services:
- 5173:5173
environment:
- API_URL=http://api:1597
depends_on:
- api
volumes:
db:
+3 -3
View File
@@ -10,11 +10,11 @@
<article>
<div>
<img src={feed.faviconUrl} alt={feed.title} />
<h3>{feed.title}</h3>
<img src={feed.faviconUrl} alt={feed.name} />
<h3>{feed.name}</h3>
</div>
<div>
<span>{feed.url}</span>
<span>{feed.link}</span>
</div>
{#if feed.submitter}
<div>
+10 -8
View File
@@ -14,14 +14,16 @@
>
<article>
<div class="origin">
<img src={post.feed.faviconUrl} alt={post.feed.title} />
<span>{post.feed.title}</span> |
{#if post.author}
<div class="author">
<QuillPenLine />
<span>{post.author}</span>
</div>
|
<img src={post.feed.faviconUrl} alt={post.feed.name} />
<span>{post.feed.name}</span> |
{#if post.authors?.length}
{#each post.authors as author}
<div class="author">
<QuillPenLine />
<span>{author}</span>
</div>
|
{/each}
{/if}
<Time
timestamp={post.date}
+110
View File
@@ -0,0 +1,110 @@
<script lang="ts">
import { twMerge } from "tailwind-merge";
import { getContext } from "svelte";
import Time, { dayjs } from "svelte-time";
import { P } from "flowbite-svelte";
import QuillPenLine from "virtual:icons/mingcute/quill-pen-line";
import type { Post } from "$lib/types";
export let title: string = "";
export let date: string = "";
export let post: Post;
export let svgClass: string =
"w-3 h-3 text-primary-600 dark:text-primary-400";
let order: "default" | "vertical" | "horizontal" | "activity" | "group" =
"default";
order = getContext("order");
const liClasses = {
default: "mb-10 ms-4",
vertical: "mb-10 ms-6",
horizontal: "relative mb-6 sm:mb-0",
activity: "mb-10 ms-6",
group: "",
};
const divClasses = {
default:
"absolute w-3 h-3 bg-gray-200 rounded-full mt-1.5 -start-1.5 border border-white dark:border-gray-900 dark:bg-gray-700",
vertical:
"flex absolute -start-3 justify-center items-center w-6 h-6 bg-primary-200 rounded-full ring-8 ring-white dark:ring-gray-900 dark:bg-primary-900",
horizontal: "flex items-center",
activity:
"flex absolute -start-3 justify-center items-center w-6 h-6 bg-primary-200 rounded-full ring-8 ring-white dark:ring-gray-900 dark:bg-primary-900",
group:
"p-5 mb-4 bg-gray-50 rounded-lg border border-gray-100 dark:bg-gray-800 dark:border-gray-700",
};
const timeClasses = {
default:
"mb-1 text-sm font-normal leading-none text-gray-400 dark:text-gray-500",
vertical:
"block mb-2 text-sm font-normal leading-none text-gray-400 dark:text-gray-500",
horizontal:
"block mb-2 text-sm font-normal leading-none text-gray-400 dark:text-gray-500",
activity: "mb-1 text-xs font-normal text-gray-400 sm:order-last sm:mb-0",
group: "text-lg font-semibold text-gray-900 dark:text-white",
};
let liCls: string = twMerge(liClasses[order], $$props.classLi);
let divCls: string = twMerge(divClasses[order], $$props.classDiv);
let timeCls: string = twMerge(timeClasses[order], $$props.classTime);
const h3Cls = twMerge(
order === "vertical"
? "flex items-center mb-1 text-lg font-semibold text-gray-900 dark:text-white"
: "text-lg font-semibold text-gray-900 dark:text-white",
$$props.classH3,
);
</script>
<li class={liCls}>
<div class={divCls} />
{#if order !== "default"}
<slot name="icon">
<svg
aria-hidden="true"
class={svgClass}
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z"
clip-rule="evenodd"
/>
</svg>
</slot>
{:else if date}
<time class={timeCls}>{date}</time>
{/if}
{#if title}
<a href={post.link} target="_blank">
<h3 class={h3Cls}>
{title}
</h3>
</a>
{/if}
{#if order !== "default"}
<div class="font-light text-sm text-slate-500">
<span>{post.feed.name}</span> |
{#if post.authors?.length}
{#each post.authors as author}
<div class="author">
<QuillPenLine />
<span>{author}</span>
</div>
|
{/each}
{/if}
<Time
timestamp={post.date}
relative={true}
title={dayjs(post.date).locale("en").toString()}
/>
</div>
{/if}
<slot />
</li>
+2 -1
View File
@@ -33,5 +33,6 @@ export async function getPosts(token?: string) {
}
const r = await fetch(env.API_URL + '/entries', token ? opts : undefined);
const j = await r.json();
return j.posts as Post[];
console.log(j);
return j as Post[];
}
+2 -2
View File
@@ -2,8 +2,8 @@ import type { User } from "./user.type";
export type Feed = {
id: string;
title: string;
url: string;
name: string;
link: string;
faviconUrl: string;
tags: string[];
submitterId: string;
+2 -2
View File
@@ -7,7 +7,7 @@
<slot></slot>
<footer>
<!-- <footer>
<BottomNav position="absolute" classInner="grid-cols-2">
<BottomNavItem btnName="Posts">
<HomeSolid
@@ -20,4 +20,4 @@
/>
</BottomNavItem>
</BottomNav>
</footer>
</footer> -->
+8 -8
View File
@@ -5,8 +5,8 @@ import { get } from "svelte/store";
const feeds: Feed[] = [
{
id: "1",
title: "The first feed",
url: "https://example.com/feed",
name: "The first feed",
link: "https://example.com/feed",
faviconUrl: "https://kit.svelte.dev/favicon.png",
tags: ["tag1", "tag2"],
submitterId: "1",
@@ -14,8 +14,8 @@ const feeds: Feed[] = [
},
{
id: "2",
title: "Phoronix",
url: "https://www.phoronix.com",
name: "Phoronix",
link: "https://www.phoronix.com",
faviconUrl: "https://www.phoronix.com/favicon.ico",
tags: ["linux", "kernel", "gnu", "gnu/linux", "gnu+linux", "gnu linux"],
submitterId: "1",
@@ -23,8 +23,8 @@ const feeds: Feed[] = [
},
{
id: "3",
title: "LWN.net",
url: "https://lwn.net",
name: "LWN.net",
link: "https://lwn.net",
faviconUrl: "https://lwn.net/favicon.ico",
tags: ["linux", "kernel", "gnu", "gnu/linux", "gnu+linux", "gnu linux"],
submitterId: "1",
@@ -60,9 +60,9 @@ const posts: Post[] = [
}
];
export function load() {
export async function load() {
return {
posts: getPosts(),
posts: await getPosts(),
feeds
};
}
+47 -1
View File
@@ -5,23 +5,69 @@
BottomNavItem,
Skeleton,
ImagePlaceholder,
Avatar,
P,
} from "flowbite-svelte";
import List from "$lib/posts/list.svelte";
import { CalendarWeekSolid } from "flowbite-svelte-icons";
import TimelineItem from "$lib/posts/timeline-item.svelte";
import { Timeline, TimelineItem as TI } from "flowbite-svelte";
import {
HomeSolid,
WalletSolid,
AdjustmentsVerticalOutline,
UserCircleSolid,
} from "flowbite-svelte-icons";
$: displayPosts = (data?.posts || []).map((post) => {
let dateStr = post.feed.name + " - ";
dateStr += new Date(post.date).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
if (post.authors && post.authors.length > 0) {
dateStr += ` by ${post.authors.join(", ")}`;
}
return {
...post,
dateStr,
};
});
</script>
<main>
<List posts={data.posts} />
<Timeline order="vertical" class="max-w-3xl">
{#each displayPosts as post}
<TimelineItem title={post.title} date={post.dateStr} post={post}>
<svelte:fragment slot="icon">
<span
class="flex absolute -start-3 justify-center items-center w-6 h-6 bg-primary-200 rounded-full ring-8 ring-white dark:ring-gray-900 dark:bg-primary-900"
>
<Avatar
src={post.feed.faviconUrl}
alt={post.feed.name}
class="w-4 h-4 -start-2 -top-2"
/>
</span>
</svelte:fragment>
<p
class="mb-4 text-base font-normal text-gray-500 dark:text-gray-400 line-clamp-2"
>
{#if post.content}
{post.content}
{/if}
</p>
</TimelineItem>
{/each}
</Timeline>
</main>
<style>
main {
display: flex;
width: 100vw;
justify-content: center;
}
</style>
+5 -7
View File
@@ -1,4 +1,4 @@
import { fail } from '@sveltejs/kit';
import { fail, redirect } from '@sveltejs/kit';
import { login, register } from '$lib/server/api.js';
@@ -8,9 +8,8 @@ export const actions = {
const email = data.get('email');
const password = data.get('password');
const token = await login(email as any, password as any);
return {
token
};
cookies.set('token', token, { path: '/', maxAge: 60 * 60 * 24 * 365 * 2 });
throw redirect(303, '/');
},
register: async ({ cookies, request }) => {
const data = await request.formData();
@@ -30,8 +29,7 @@ export const actions = {
})
}
const token = await register(email as any, username as any, password as any);
return {
token
};
cookies.set('token', token, { path: '/', maxAge: 60 * 60 * 24 * 365 * 2 });
throw redirect(303, '/');
},
}