Fetching 500 Wallabag articles, since we cannot filter tags easily, then filter tags in the API.

This commit is contained in:
Bradley Shellnut 2023-02-03 23:23:00 -08:00
parent 139fea9490
commit e3f2cae296
12 changed files with 133 additions and 19 deletions

1
.gitignore vendored
View file

@ -11,3 +11,4 @@ vite.config.ts.timestamp-*
.fleet
.idea
.vercel

11
.vscode/settings.json vendored
View file

@ -1,3 +1,12 @@
{
"cSpell.words": ["bradleyshellnut", "iconify", "Mullvad", "Obispo", "Syncthing"]
"cSpell.words": [
"bradleyshellnut",
"iconify",
"Mullvad",
"nextjs",
"Obispo",
"selfhosting",
"Syncthing",
"Wallabag"
]
}

View file

@ -32,6 +32,7 @@
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte3": "^4.0.0",
"iconify-icon": "^1.0.3",
"just-intersect": "^4.3.0",
"postcss": "^8.4.21",
"postcss-import": "^15.1.0",
"postcss-load-config": "^4.0.1",

View file

@ -19,6 +19,7 @@ specifiers:
eslint-config-prettier: ^8.5.0
eslint-plugin-svelte3: ^4.0.0
iconify-icon: ^1.0.3
just-intersect: ^4.3.0
postcss: ^8.4.21
postcss-import: ^15.1.0
postcss-load-config: ^4.0.1
@ -57,6 +58,7 @@ devDependencies:
eslint-config-prettier: 8.6.0_eslint@8.32.0
eslint-plugin-svelte3: 4.0.0_tmo5zkisvhu6htudosk5k7m6pu
iconify-icon: 1.0.3
just-intersect: 4.3.0
postcss: 8.4.21
postcss-import: 15.1.0_postcss@8.4.21
postcss-load-config: 4.0.1_postcss@8.4.21
@ -2369,6 +2371,10 @@ packages:
dev: true
optional: true
/just-intersect/4.3.0:
resolution: {integrity: sha512-XdAiJUmfM7VOoBUh7I4xo+0YYuzCPiV0Xf21oAmR+1j6a/P8KxJUCigZDblmURZmkIWffNziY2sbSaHrJbNcuA==}
dev: true
/kleur/4.1.5:
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
engines: {node: '>=6'}

View file

@ -0,0 +1,41 @@
import { writable } from 'svelte/store';
import type { Article } from '$lib/types/article';
// Custom store
const state = () => {
const { subscribe, set, update } = writable<Article[]>([]);
function addAll(articles: Article[]) {
for (const article of articles) {
add(article);
}
}
function add(article: Article) {
update((store) => [...store, article]);
}
function addSorted(article: Article, index: number) {
update((store) => {
store.splice(index, 0, article);
return store;
});
}
function remove(hashed_url: string) {
update((store) => {
const newStore = store.filter((item: Article) => item.hashed_url !== hashed_url);
return [...newStore];
});
}
function removeAll() {
update(() => {
return [];
});
}
return { subscribe, set, update, add, addSorted, addAll, remove, removeAll };
};
export const articleStore = state();

View file

@ -1,5 +1,7 @@
export type Article {
tags: string[];
import type { ArticleTag } from './articleTag';
export type Article = {
tags: ArticleTag[];
title: string;
url: URL;
hashed_url: string;
@ -8,4 +10,22 @@ export type Article {
created_at: Date;
updated_at: Date;
archived_at: Date | null;
}
};
export type WallabagArticle = {
tags: WallabagTag[];
title: string;
url: URL;
hashed_url: string;
reading_time: number;
preview_picture: string;
created_at: Date;
updated_at: Date;
archived_at: Date | null;
};
export type WallabagTag = {
id: number;
label: string;
slug: string;
};

View file

@ -0,0 +1,17 @@
export enum ArticleTag {
TECH = 'tech',
TECHNOLOGY = 'technology',
SELFHOSTING = 'selfhosting',
PROGRAMMING = 'programming',
PRIVACY = 'privacy',
DEVELOPMENT = 'development',
VITE = 'vite',
SVELTE = 'svelte',
REACT = 'react',
JAVASCRIPT = 'javascript',
GATSBY = 'gatsby',
SVELTEKIT = 'sveltekit',
NEXTJS = 'nextjs',
CSS = 'css',
HTML = 'html'
}

View file

@ -1,6 +1,5 @@
import { error, type ServerLoad } from '@sveltejs/kit';
import { fetchArticlesApi } from './api';
// import type { PageServerLoad } from './$types';
export const prerender = true;
import { type ServerLoad } from '@sveltejs/kit';
export const load: ServerLoad = async ({ isDataRequest, cookies, params, setHeaders }) => {
const queryParams = {

View file

@ -5,7 +5,9 @@ import {
WALLABAG_PASSWORD,
WALLABAG_URL
} from '$env/static/private';
import type { Article } from '$root/lib/types/article';
import intersect from 'just-intersect';
import type { Article, WallabagArticle } from '$root/lib/types/article';
import { ArticleTag } from '$root/lib/types/articleTag';
import type { PageQuery } from '$root/lib/types/pageQuery';
import { URLSearchParams } from 'url';
@ -37,7 +39,7 @@ export async function fetchArticlesApi(
const pageQuery: PageQuery = {
sort: 'updated',
perPage: 6,
perPage: 500,
since: 0
};
const entriesQueryParams = new URLSearchParams(pageQuery);
@ -67,11 +69,27 @@ export async function fetchArticlesApi(
// do {
// nbEntries += entries._embedded.items.length;
console.log(`number of articles fetched: ${entries._embedded.items.length}`);
entries._embedded.items.forEach((article: Article) => {
article.created_at = new Date(article.created_at);
article.updated_at = new Date(article.updated_at);
article.archived_at = article.archived_at ? new Date(article.archived_at) : null;
articles.push(article);
entries._embedded.items.forEach((article: WallabagArticle) => {
if (articles?.length === 30) {
console.log('Reached 30 articles');
return;
}
const rawTags = article?.tags?.map((tag) => tag.slug);
if (intersect(rawTags, Object.values(ArticleTag))?.length > 0) {
const tags = rawTags.map((rawTag) => rawTag as unknown as ArticleTag);
articles.push({
tags,
title: article.title,
url: article.url,
hashed_url: article.hashed_url,
reading_time: article.reading_time,
preview_picture: article.preview_picture,
created_at: new Date(article.created_at),
updated_at: new Date(article.updated_at),
archived_at: article.archived_at ? new Date(article.archived_at) : null
});
}
});
// if (!entries._links.next) {

View file

@ -1,5 +1,7 @@
<script lang="ts">
import { page } from "$app/stores";
import { Article } from "$lib/types/article";
import { ArticleTag } from "$lib/types/articleTag";
import SEO from "$root/lib/components/SEO.svelte";
$: ({ articles } = $page.data);
@ -24,7 +26,7 @@
base="/articles"
/> -->
<div class="articlesStyles">
{#each articles as article}
{#each articles as article (article.hashed_url)}
<div class="articleStyles card">
<section>
<h3>
@ -43,7 +45,7 @@
<div class="tagStyles">
<p>Tags:</p>
{#each article.tags as tag}
<p>{tag.label}</p>
<p>{tag}</p>
{/each}
</div>
</section>

View file

@ -6,7 +6,7 @@ export const load: PageLoad = async ({ fetch, parent, url, setHeaders }) => {
const parentData = await parent();
const cacheBust = getCurrentCookieValue('articles-cache') || parentData.articlesCacheBust;
const search = url.searchParams.get('search') || '';
// const search = url.searchParams.get('search') || '';
const resp = await fetch(`/api/articles?cache=${cacheBust}`);
const articles: Article[] = await resp.json();

View file

@ -89,7 +89,7 @@
</a>
</li>
<li>
Bee, Shell, Nut, and Adventure Icons made by{' '}
Bee, Shell, Nut, and Seattle Icons made by{' '}
<a
target="_blank"
href="https://www.flaticon.com/authors/freepik"