Skip to content
Snippets Groups Projects
Commit 8d33275f authored by Remi  PLANEL's avatar Remi PLANEL
Browse files

get article from meilisearch + cache

parent 4d4bba17
No related branches found
No related tags found
1 merge request!224Resolve "Rework references"
Pipeline #124708 canceled with stages
in 1 minute and 5 seconds
<script setup lang="ts">
import { useDisplay } from "vuetify";
import { useArticlesStore } from '@/stores/articles'
import type { WikiArticle } from '@/types/articles';
export interface Props {
index?: number;
......@@ -19,11 +19,14 @@ const props = withDefaults(defineProps<Props>(), {
isRelevant: false,
});
const { article } = useFetchArticle(props.doi);
const article = ref<WikiArticle | undefined>(undefined)
const { mobile } = useDisplay();
const show = ref(false);
onMounted(async () => {
const { article: articleOnMounted } = await useFetchArticle(props.doi);
article.value = articleOnMounted.value
})
const articleTitle = computed(() => {
return props?.title ?? article?.value?.title ?? props.doi;
});
......@@ -32,16 +35,11 @@ const articleAbstract = computed(() => {
});
</script>
<template>
<v-list-item :href="article?.href" :id="`ref-${props.doi}`" :target="article?.target" density="compact" color="transparent"
class="px-1">
<v-list-item :href="article?.href" :id="`ref-${props.doi}`" :target="article?.target" density="compact"
color="transparent" class="px-1">
<template v-if="!mobile" #prepend>
<v-icon icon="md:star" :color="props.isRelevant ? 'info' : 'transparent'"></v-icon>
</template>
<!-- <template v-if="!mobile" #append>
<v-btn v-if="articleAbstract" size="x-small" variant="plain"
:append-icon="show ? 'mdi-chevron-up' : 'mdi-chevron-down'" class="px-0"
@click.stop.prevent="show = !show">Abstract</v-btn>
</template> -->
<v-card flat color="transparent" density="compact" class="my-0 article-ref">
<v-card-item density="compact" class="pa-0">
<v-toolbar class="py-0 d-flex align-start article-toolbar" color="transparent" :height="20">
......@@ -51,9 +49,6 @@ const articleAbstract = computed(() => {
:append-icon="show ? 'mdi-chevron-up' : 'mdi-chevron-down'" class="px-1 align-center"
@click.stop.prevent="show = !show">Abstract</v-btn>
</v-toolbar>
<!-- <v-card-title class="py-0"><span class="font-weight-bold">{{
articleTitle
}}</span></v-card-title> -->
<v-card-subtitle class="py-0">
{{ article?.subtitle ?? "no authors" }}</v-card-subtitle>
<v-card-subtitle class="py-0">
......
import { useArticlesStore } from '../stores/articles'
import { ref, computed, watchEffect, toValue } from "vue"
// import { useFetch } from '#app';
// import { useFetch } from "nuxt"
import { type MaybeRef, useFetch } from '#imports'
import type { CslJson, CrossrefArticle, SrcArticle } from '@/types/articles';
import { ref, toValue } from "vue"
import { StorageSerializers } from "@vueuse/core"
import type { CslJson, WikiArticle } from '@/types/articles';
import type { SearchParams } from 'meilisearch'
export function useFetchArticle(doi: MaybeRef<string> = ref("")) {
// const article = ref<Article>()
// const rawArticle = ref<RawArticle>()
const srcArticle = ref<SrcArticle | null>(null)
const store = useArticlesStore()
const pending = ref(false)
export async function useFetchArticle(doi: string = "") {
const doiBaseUrl = ref(new URL("https://doi.org/"));
const url = ref(new URL(`/works/${toValue(doi)}`, " https://api.crossref.org/").href);
const article = ref()
const zoteroArticles = ref()
// const article = ref<WikiArticle | undefined>(undefined)
const article = useSessionStorage<WikiArticle>(doi, null, { serializer: StorageSerializers.object })
const client = useMeiliSearchRef()
const index = ref("article")
const params = ref<SearchParams>({
facets: ["*"],
filter: [`DOI='${doi}'`],
limit: 1
})
function getReferenceUrl(doi: string) {
return new URL(doi, doiBaseUrl.value).href;
}
function toAuthorsString(authors: Array<{ family: string; given: string }>) {
return authors
.map((curr) => {
......@@ -28,12 +24,7 @@ export function useFetchArticle(doi: MaybeRef<string> = ref("")) {
})
.join(", ");
}
function getReferenceUrl(doi: string) {
return new URL(doi, doiBaseUrl.value).href;
}
function zoteroArticleToArticle(zoteroArticle: CslJson) {
function zoteroArticleToArticle(zoteroArticle: CslJson): WikiArticle | undefined {
if (zoteroArticle != undefined) {
const {
DOI,
......@@ -56,74 +47,38 @@ export function useFetchArticle(doi: MaybeRef<string> = ref("")) {
target: "_blank",
prependIcon: "mdi-newspaper-variant-outline",
}
}
} else { return undefined }
}
if (!article.value) {
const { data, error } = await useAsyncData(
doi,
async () => {
return await client.index(toValue(index)).search<CslJson>("", toValue(params))
},
{
transform: function (data) {
if (data !== undefined && data?.hits.length >= 1) {
return zoteroArticleToArticle(data.hits[0])
}
}
}
)
}
function crossrefToArticle(article: CrossrefArticle): WikiArticle {
const { title, DOI, type, "container-title": ct, "short-container-title": sct, abstract, author, issued } = article
// let sanitizedAbstract = abstract
const sanitizedAbstract = abstract ? /(?:\<jats\:p\>)?(.*)(?:\<\/jats\:p\>)?/.exec(abstract)?.[1] ?? '' : ''
const sanitizedContainerTitle = sct?.length > 0 ? sct[0] : ct?.length > 0 ? ct[0] : ""
return {
title: title?.length > 0 ? title[0] : "",
DOI,
abstract: sanitizedAbstract,
containerTitle: sanitizedContainerTitle,
subtitle: toAuthorsString(author || []),
author,
year: issued?.["date-parts"][0][0] ?? '',
href: getReferenceUrl(DOI),
target: "_blank",
prependIcon: "mdi-newspaper-variant-outline"
if (error.value) {
throw createError({
...error.value,
statusMessage: `Could not fetch article ${doi}`
})
}
article.value = data.value
}
return { article }
}
function crossrefToCsl(article: CrossrefArticle): CslJson {
const { title, DOI, type, "container-title": ct, "short-container-title": sct, abstract, author, issued } = article
// let sanitizedAbstract = abstract
const sanitizedAbstract = abstract ? /(?:\<jats\:p\>)?(.*)(?:\<\/jats\:p\>)?/.exec(abstract)?.[1] ?? '' : ''
const sanitizedContainerTitle = sct?.length > 0 ? sct[0] : ct?.length > 0 ? ct[0] : ""
return {
title: title?.length > 0 ? title[0] : "",
type,
DOI,
abstract: sanitizedAbstract,
author,
"container-title": sanitizedContainerTitle,
issued
}
}
if (store.articles.has(toValue(doi))) {
const cslArticle = store.articles.get(toValue(doi))
article.value = cslArticle ? zoteroArticleToArticle(cslArticle) : undefined
}
else {
useFetch<RawArticle>(toValue(url), {
lazy: true, server: false,
}).then(({ data, pending: pendingUseFetch }) => {
if (data.value?.message) {
article.value = crossrefToArticle(data.value.message)
store.add(crossrefToCsl(data.value.message))
}
pending.value = pendingUseFetch.value
})
}
// const fetchCrossRef = () => {
// useFetch<RawArticle>(toValue(url), {
// lazy: true, server: false,
// }).then(({ data, pending: pendingUseFetch }) => {
// if (data.value?.message) {
// srcArticle.value = data.value.message
// }
// pending.value = pendingUseFetch.value
// })
// }
return { article, pending }
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment