Skip to content

Commit

Permalink
Fetch news on load, not on build
Browse files Browse the repository at this point in the history
  • Loading branch information
arildm committed Apr 24, 2024
1 parent a5e22b0 commit be1b5cd
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 26 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ VITE_LOGOUT_URL=https://sp.spraakbanken.gu.se/Shibboleth.sso/Logout
# VITE_JWT_URL=https://sp.spraakbanken.gu.se/auth/jwt
VITE_KORP_URL=https://spraakbanken.gu.se/korp/
VITE_STRIX_URL=https://spraakbanken.gu.se/strix/
VITE_NEWS_URL=https://raw.githubusercontent.com/spraakbanken/newsdesk/main/data/mink.yaml
VITE_MATOMO_URL=https://spraakbanken.gu.se/stats/
# VITE_MATOMO_ID= # Do not report to the real backend when developing
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ As this project is a user-facing application, the places in the semantic version
- Restructured panels on corpus overview to better match backend concepts:
- New _Analysis_ panel with the run button from _Status_ and the downloads from _Results_
- Renamed _Result_ to _Explore_ [#115](https://github.com/spraakbanken/mink-frontend/issues/115)
- Fetching news from the Newsdesk repo on page load, instead of a static file at build time
- The `on` prop of `PendingContent` now matches by start of string

### Fixed
Expand Down
1 change: 1 addition & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface ImportMetaEnv {
readonly VITE_JWT_URL?: string;
readonly VITE_KORP_URL: string;
readonly VITE_STRIX_URL: string;
readonly VITE_NEWS_URL: string;
readonly VITE_MATOMO_URL: string;
readonly VITE_MATOMO_ID?: number;
}
Expand Down
6 changes: 3 additions & 3 deletions src/api/corpusConfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const yaml = import("js-yaml").then((m) => m.default);
const Yaml = import("js-yaml").then((m) => m.default);

import type { ByLang } from "@/util.types";
import type {
Expand Down Expand Up @@ -150,7 +150,7 @@ export async function makeConfig(id: string, options: ConfigOptions) {
);
}

return (await yaml).dump(config as SparvConfig);
return (await Yaml).dump(config as SparvConfig);
}

export function emptyConfig(): ConfigOptions {
Expand All @@ -167,7 +167,7 @@ export function emptyConfig(): ConfigOptions {
* May throw all kinds of errors, the sky is the limit.
*/
export async function parseConfig(configYaml: string): Promise<ConfigOptions> {
const config = (await yaml).load(configYaml) as any;
const config = (await Yaml).load(configYaml) as any;

if (!config)
throw new TypeError(`Parsing config failed, returned "${config}"`);
Expand Down
25 changes: 20 additions & 5 deletions src/home/HomeNews.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
<script setup lang="ts">
import items from "@/home/news.yaml";
import { onMounted, reactive } from "vue";
import useLocale from "@/i18n/locale.composable";
import { fetchFeaturedNews, type NewsItem } from "@/home/news.service";
const { th2 } = useLocale();
const { locale, th } = useLocale();
const items = reactive<NewsItem[]>([]);
onMounted(async () => {
try {
items.push(...(await fetchFeaturedNews()));
} catch (error) {
console.error("Could not fetch and parse news", error);
}
});
function getDate(date: Date) {
return date.toISOString().slice(0, 10);
return date.toLocaleDateString(locale.value, { dateStyle: "short" });
}
</script>

Expand All @@ -16,9 +26,14 @@ function getDate(date: Date) {
:key="i"
class="bg-sky-50 dark:bg-sky-800 shadow shadow-sky-200 dark:shadow-sky-600 text-sky-800 dark:text-sky-200 p-1 px-2 my-2"
>
<strong>{{ getDate(item.date) }}: {{ th2(item.title) }}</strong>
<header class="font-bold">{{ th(item.title) }}</header>

<time :datetime="item.created.toString()" class="my-1 text-sm italic">
{{ getDate(item.created) }}
</time>

<!-- eslint-disable-next-line vue/no-v-html -->
<div v-html="th2(item.body)"></div>
<div v-html="th(item.body)"></div>
</article>
</div>
</template>
52 changes: 52 additions & 0 deletions src/home/news.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const Yaml = import("js-yaml").then((m) => m.default);
import once from "lodash/once";
import { retry } from "@/util";
import type { ByLang } from "@/util.types";

const NEWS_URL: string = import.meta.env.VITE_NEWS_URL;

/** A news item in the Newsdesk repo */
export type NewsItem = {
title: ByLang | string;
body: ByLang | string;
created: Date;
expires?: Date;
tags?: NewsTag[];
};

/** News item tags recognized by this frontend */
type NewsTag = "featured" | string;

/**
* Fetch and parse a YAML newsfeed
*
* @returns All items
* @throws Fetch or parse errors
*/
export const fetchAllNews = once(async (): Promise<NewsItem[]> => {
if (!NEWS_URL) return [];
const response = await retry(() => fetch(NEWS_URL));
const yaml = await response.text();
return (await Yaml).load(yaml) as NewsItem[];
});

/**
* Fetch news and select recent items
*
* @returns News items considered interesting for users
* @throws Fetch or parse errors
*/
export async function fetchNews(): Promise<NewsItem[]> {
const items = await fetchAllNews();
return items.filter((item) => !item.expires || item.expires > new Date());
}

/**
* Fetch news and select *featured* recent items
*
* @returns News items that the user really should see
* @throws Fetch or parse errors
*/
export async function fetchFeaturedNews(): Promise<NewsItem[]> {
return (await fetchNews()).filter((item) => item.tags?.includes("featured"));
}
9 changes: 0 additions & 9 deletions src/home/news.yaml

This file was deleted.

12 changes: 3 additions & 9 deletions src/i18n/locale.composable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,10 @@ export default function useLocale() {
});

/** Translate here - picks the current language out of a strings-by-language object. */
function th(map?: ByLang): string | undefined {
function th(map?: ByLang | string): string | undefined {
if (!map) return undefined;
return th2({ sv: map.swe, en: map.eng });
}

/** Translate here - picks the current language out of a strings-by-language object. */
function th2(map?: Record<SvEn, string>): string | undefined {
if (!map) return undefined;
return map[locale.value as SvEn];
if (typeof map == "string") return map;
return map[locale3.value];
}

/** Wrap the filesize lib with some sane defaults and avoiding exponential notation. */
Expand All @@ -59,7 +54,6 @@ export default function useLocale() {
locale,
locale3,
th,
th2,
filesize: myFilesize,
};
}

0 comments on commit be1b5cd

Please sign in to comment.