Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use getApiResponse on infinite scrolls, too #880

Merged
merged 3 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 3 additions & 1 deletion src/langs/json/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@
"pageAbbrev": "p.",
"pageCount": "{n, plural, one {# page} other {# pages}}",
"select": "Select",
"noteCount": "{n, plural, one {# note} other {# notes}}"
"noteCount": "{n, plural, one {# note} other {# notes}}",
"more": "Load more",
"retry": "Please try again."
},
"error": {
"report": "Report a problem"
Expand Down
35 changes: 22 additions & 13 deletions src/lib/components/addons/History.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,46 @@
import type { Run } from "$lib/api/types";

import { _ } from "svelte-i18n";
import { History16, History24, Hourglass24 } from "svelte-octicons";
import { Alert16, History16, History24, Hourglass24 } from "svelte-octicons";
eyeseast marked this conversation as resolved.
Show resolved Hide resolved

import HistoryEvent from "./HistoryEvent.svelte";
import Paginator from "$lib/components/common/Paginator.svelte";
import SidebarGroup from "../sidebar/SidebarGroup.svelte";
import SidebarItem from "../sidebar/SidebarItem.svelte";
import Empty from "../common/Empty.svelte";

import { getApiResponse } from "$lib/utils/api";

export let runs: Run[];
export let previous: Maybe<Nullable<string>> = undefined;
export let next: Maybe<Nullable<string>> = undefined;

export let loading = false;

let error: string = "";

$: empty = runs.length === 0;

// load the next set of results
async function load(url: URL) {
loading = true;

// todo: better error handling
const res = await fetch(url, { credentials: "include" }).catch(
const resp = await fetch(url, { credentials: "include" }).catch(
console.error,
);
if (!res) return console.error("API error");
if (!res.ok) {
console.error(res.statusText);
loading = false;

const { data: results, error: err } = await getApiResponse<Page<Run>>(resp);

if (err) {
error = err.message;
}

const results: Page<Run> = await res.json();
if (results) {
runs = results.results;
next = results.next;
previous = results.previous;
}

runs = results.results;
next = results.next;
previous = results.previous;
loading = false;
}
</script>
Expand All @@ -50,6 +55,10 @@

{#if loading}
<Empty icon={Hourglass24}>Loading past runs…</Empty>
{:else if error}
<Empty icon={Alert16}>
eyeseast marked this conversation as resolved.
Show resolved Hide resolved
{error}
</Empty>
{:else}
{#each runs as run}
<HistoryEvent {run} />
Expand All @@ -62,10 +71,10 @@
<Paginator
has_next={Boolean(next)}
has_previous={Boolean(previous)}
on:next={(e) => {
on:next={() => {
if (next) load(new URL(next));
}}
on:previous={(e) => {
on:previous={() => {
if (previous) load(new URL(previous));
}}
/>
Expand Down
36 changes: 23 additions & 13 deletions src/lib/components/addons/Scheduled.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,45 @@
import type { Maybe, Nullable, Page, Event } from "$lib/api/types";

import { _ } from "svelte-i18n";
import { Clock16, Hourglass24 } from "svelte-octicons";
import { Alert16, Clock16, Hourglass24 } from "svelte-octicons";
eyeseast marked this conversation as resolved.
Show resolved Hide resolved

import ScheduledEvent from "./ScheduledEvent.svelte";
import SidebarGroup from "../sidebar/SidebarGroup.svelte";
import SidebarItem from "../sidebar/SidebarItem.svelte";
import Paginator from "$lib/components/common/Paginator.svelte";
import Empty from "../common/Empty.svelte";

import { getApiResponse } from "$lib/utils/api";

export let events: Event[];
export let previous: Maybe<Nullable<string>> = undefined;
export let next: Maybe<Nullable<string>> = undefined;

export let loading = false;

let error: string = "";

// load the next set of results
async function load(url: URL) {
loading = true;

// todo: better error handling
const res = await fetch(url, { credentials: "include" }).catch(
const resp = await fetch(url, { credentials: "include" }).catch(
console.error,
);
if (!res) return console.error("API error");
if (!res.ok) {
console.error(res.statusText);
loading = false;

const { data: results, error: err } =
await getApiResponse<Page<Event>>(resp);

if (err) {
error = err.message;
}

const results: Page<Event> = await res.json();
if (results) {
events = results.results;
next = results.next;
previous = results.previous;
}

events = results.results;
next = results.next;
previous = results.previous;
loading = false;
}
</script>
Expand All @@ -47,6 +53,10 @@

{#if loading}
<Empty icon={Hourglass24}>{$_("common.loading")}</Empty>
{:else if error}
<Empty icon={Alert16}>
eyeseast marked this conversation as resolved.
Show resolved Hide resolved
{error}
</Empty>
{:else}
{#each events as event}
<ScheduledEvent {event} />
Expand All @@ -61,12 +71,12 @@
<Paginator
has_next={Boolean(next)}
has_previous={Boolean(previous)}
on:next={(e) => {
on:next={() => {
if (next) {
load(new URL(next));
}
}}
on:previous={(e) => {
on:previous={() => {
if (previous) {
load(new URL(previous));
}
Expand Down
45 changes: 30 additions & 15 deletions src/lib/components/documents/ResultsList.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script context="module" lang="ts">
import type { Document, DocumentResults, Maybe } from "$lib/api/types";
import {
derived,
writable,
type Readable,
type Writable,
} from "svelte/store";
import type { Document, DocumentResults, Maybe } from "$lib/api/types";

// IDs might be strings or numbers, depending on the API endpoint
// enforce type consistency here to avoid comparison bugs later
Expand All @@ -32,6 +32,8 @@
import NoteHighlights from "./NoteHighlights.svelte";
import PageHighlights from "./PageHighlights.svelte";

import { getApiResponse } from "$lib/utils/api";

export let results: Document[] = [];
export let count: Maybe<number> = undefined;
export let next: string | null = null;
Expand All @@ -41,6 +43,7 @@
let loading = false;
let end: HTMLElement;
let observer: IntersectionObserver;
let error: string = "";

const embed: boolean = getContext("embed");

Expand All @@ -50,24 +53,25 @@
// load the next set of results
async function load(url: URL) {
loading = true;
const res = await fetch(url, { credentials: "include" }).catch(
const resp = await fetch(url, { credentials: "include" }).catch(
console.error,
);

// todo: better error handling
if (!res) return console.error("API error");
if (!res.ok) {
console.error(res.statusText);
loading = false;
const { data, error: err } = await getApiResponse<DocumentResults>(resp);

if (err) {
// show an error message, but let the user try loading more
error = err.message;
}

const r: DocumentResults = await res.json();
if (data) {
results = [...results, ...data.results];
$total = data.count ?? $total;
next = data.next;
if (auto) watch(end);
}

results = [...results, ...r.results];
$total = r.count ?? $total;
next = r.next;
loading = false;
if (auto) watch(end);
}

function watch(el: HTMLElement) {
Expand Down Expand Up @@ -145,12 +149,17 @@
}}
>
{#if loading}
Loading &hellip;
{$_("common.loading")}
{:else}
Load more
{$_("documents.more")}
{/if}
</Button>
{/if}

{#if error}
<p class="error">{error}</p>
<p class="error">{$_("documents.retry")}</p>
{/if}
</div>

<slot name="end" />
Expand All @@ -177,6 +186,12 @@

.end {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}

.error {
color: var(--error, red);
eyeseast marked this conversation as resolved.
Show resolved Hide resolved
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import Unverified from "../../accounts/Unverified.svelte";

import { me } from "@/test/fixtures/accounts";
import { documents as mock } from "@/test/handlers/documents";

// typescript complains without the type assertion
import searchResults from "@/test/fixtures/documents/search-highlight.json";
Expand All @@ -24,7 +25,6 @@
export const meta = {
title: "Components / Documents / Results list",
component: ResultsList,
tags: ["autodocs"],
};

const user = { ...me, verified_journalist: false };
Expand Down Expand Up @@ -57,3 +57,7 @@
<Unverified {user} slot="start" />
</ResultsList>
</Story>

<Story name="Loading error" parameters={{ msw: { handlers: [mock.error] } }}>
<ResultsList {results} {count} {next} auto />
</Story>
4 changes: 4 additions & 0 deletions src/test/handlers/documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export const documents = {
new URL("documents/pending/", BASE_API_URL).href,
(req, res, ctx) => res(ctx.json(pending)),
),
error: rest.get(
new URL("documents/search/", "https://api.www.documentcloud.org/api/").href,
(req, res, ctx) => res(ctx.status(500, "Something went wrong")),
),
};

export const revisionControl = {
Expand Down