Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into 234-collapse-searc…
Browse files Browse the repository at this point in the history
…h-accordion-on-search-submit
  • Loading branch information
simar0at committed Feb 13, 2025
2 parents 1cb8ae4 + 892d407 commit d365909
Show file tree
Hide file tree
Showing 7 changed files with 364 additions and 104 deletions.
91 changes: 68 additions & 23 deletions components/corpus-text-window-content.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import "v3-infinite-loading/lib/style.css"; //required if you're not going to override default slots
import { Play } from "lucide-vue-next";
import { Pause, Play } from "lucide-vue-next";
import InfiniteLoading from "v3-infinite-loading";
import type { StateHandler } from "v3-infinite-loading/lib/types";
Expand All @@ -22,6 +22,8 @@ const currentPage = ref(1);
const api = useApiClient();
const scrollComplete = ref<boolean>(false);
const teiHeader = simpleItems.value.find((header) => header.id === props.params.textId);
const publication = teiHeader?.publication;
const loadNextPage = async function () {
const text = await api.vicav.getCorpusText(
{
Expand Down Expand Up @@ -99,9 +101,23 @@ watch(utteranceElements.value, (value) => {
if (value.length > 0) {
value.forEach((u) => {
const playButton = u.querySelector("a.play");
const stopButton = u.querySelector("a.stop");
const audio = u.querySelector("audio");
if (playButton && audio) {
playButton!.addEventListener("click", (_e) => audio!.play());
playButton!.addEventListener("click", () => {
audio!.play();
playButton?.classList.add("hidden");
stopButton?.classList.remove("hidden");
});
audio!.addEventListener("ended", () => {
stopButton?.classList.add("hidden");
playButton?.classList.remove("hidden");
});
stopButton!.addEventListener("click", () => {
audio!.pause();
stopButton?.classList.add("hidden");
playButton?.classList.remove("hidden");
});
}
});
}
Expand All @@ -117,27 +133,53 @@ watch(utteranceElements.value, (value) => {
<div :id="params.textId" ref="utterancesWrapper" class="p-4">
<h2 class="m-3 text-lg">{{ props.params.label }}</h2>

<table class="m-3 border border-gray-300">
<thead>
<tr></tr>
<tr></tr>
</thead>
<tbody>
<tr>
<th>Recording:</th>
<td>{{ teiHeader?.resp }}</td>
</tr>
<tr>
<th>Speakers:</th>
<td>
<span v-for="(person, index) in teiHeader?.person" :key="index">
{{ person.name }} (age: {{ person.age }}, sex: {{ person.sex }})
<span v-if="index < (teiHeader?.person.length || 1) - 1">, </span>
</span>
</td>
</tr>
</tbody>
</table>
<div class="m-3 rounded-sm border border-gray-300 bg-gray-50 p-4">
<table>
<thead>
<tr></tr>
<tr></tr>
</thead>
<tbody>
<tr>
<th class="w-44">Recording:</th>
<td>
{{ teiHeader?.recording?.map((p) => [p.given, p.family].join(" ")).join(", ") }}
</td>
</tr>
<tr>
<th>Recording date:</th>
<td>{{ teiHeader?.recordingDate }}</td>
</tr>
<tr>
<th>Transcribed by:</th>
<td>
{{ teiHeader?.transcription?.map((p) => [p.given, p.family].join(" ")).join(", ") }}
</td>
</tr>
<tr v-if="teiHeader?.hasOwnProperty('transfer to ELAN')">
<th>Transferred to ELAN:</th>
<td>
{{
teiHeader["transfer to ELAN"].map((p) => [p.given, p.family].join(" ")).join(", ")
}}
</td>
</tr>
<tr v-if="publication">
<th class="align-text-top">Published in:</th>
<td><Citation v-bind="publication" /></td>
</tr>
<tr>
<th>Speakers:</th>
<td>
<span v-for="(person, index) in teiHeader?.person" :key="index">
{{ person.name }} (age: {{ person.age }}, sex: {{ person.sex }})
<span v-if="index < (teiHeader?.person.length || 1) - 1">, </span>
</span>
</td>
</tr>
</tbody>
</table>
</div>
<table>
<tr
v-for="u in utterances"
Expand All @@ -150,6 +192,9 @@ watch(utteranceElements.value, (value) => {
<a v-if="u.audio" class="play mt-1"
><Play class="size-4" /><span class="hidden">Play</span></a
>
<a v-if="u.audio" class="stop mt-1 hidden">
<Pause class="size-4" /><span class="hidden">Stop</span>
</a>
<!-- eslint-disable-next-line vuejs-accessibility/media-has-caption -->
<audio v-if="u.audio" hidden="hidden">
<source :src="u.audio" />
Expand Down
29 changes: 9 additions & 20 deletions components/data-list-window-content.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<!-- eslint-disable @typescript-eslint/sort-type-constituents -->
<script lang="ts" setup>
import { Volume2, VolumeX } from "lucide-vue-next";
import type { JsonObject } from "type-fest";

import type { DataListWindowItem, DataTypesEnum } from "@/types/global.d";
Expand Down Expand Up @@ -82,7 +83,7 @@ const debugString = debug ? JSON.stringify(groupedItems, null, 2) : "";
{{ dataTypes[dataType]!.name }}
</em>
<ul v-for="item in items" :key="item.id">
<li class="text-base">
<li class="flex text-base">
<a
v-if="item.dataType !== 'CorpusText' || item['@hasTEIw'] === 'true'"
class="text-primary underline"
Expand All @@ -94,27 +95,15 @@ const debugString = debug ? JSON.stringify(groupedItems, null, 2) : "";
{{ item.label }}
</a>
<span v-else> {{ item.label }} </span>
<span> &nbsp; </span>
<span
v-if="
item.teiHeader.fileDesc.sourceDesc.recordingStmt &&
(item.teiHeader.fileDesc.sourceDesc.recordingStmt.recording.media?.['@url'] ||
item.teiHeader.fileDesc.sourceDesc.recordingStmt.recording.p?.ref)
"
v-if="item.audioAvailability === 'free'"
title="Audio recording is publicly available"
>
&nbsp; {{ item.teiHeader.fileDesc.sourceDesc.recordingStmt.recording["@type"] }}
<span v-if="item.teiHeader.fileDesc.sourceDesc.recordingStmt.recording.media">
: {{ item.teiHeader.fileDesc.sourceDesc.recordingStmt.recording.media["@url"] }}
</span>
<span v-if="item.teiHeader.fileDesc.sourceDesc.recordingStmt.recording.p?.ref">
:
{{
item.teiHeader.fileDesc.sourceDesc.recordingStmt.recording.p.ref["@target"]
}}
</span>
<span v-if="item.teiHeader.profileDesc?.settingDesc?.setting?.placeName.$">
:
{{ item.teiHeader.profileDesc.settingDesc.setting.placeName.$ }}
</span>
<Volume2 class="mx-2 mt-[2px] size-5" />
</span>
<span v-else title="Audio recording is restricted">
<VolumeX class="mx-2 mt-[2px] size-5" />
</span>
</li>
</ul>
Expand Down
94 changes: 71 additions & 23 deletions components/ui/citation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,102 @@ import type { simpleTEIMetadata } from "@/types/teiCorpus";
interface Props {
type: string;
refType?: "internal" | "external";
header?: simpleTEIMetadata;
bibl?: {
author: Array<CSLName>;
editor?: Array<CSLName>;
title: string;
"container-title"?: string;
issued?: Array<string>;
publisherPlace?: string;
page?: string;
volume?: string;
};
}
const { data: config } = useProjectInfo();
const props = defineProps<Props>();
const date = new Date();
const data = computed<CSLJSON>(() =>
props.type === "entry" && props.header
? {
type: "entry",
editor: config.value?.projectConfig?.editors as Array<CSLName>,
"container-title": config.value?.projectConfig?.title as string,
title: props.header.title as string,
author: props.header.author as Array<CSLName>,
issued: { "date-parts": [config.value?.projectConfig?.pubDate] } as CSLDate,
}
: {
type: "software",
editor: config.value?.projectConfig?.editors as Array<CSLName>,
title: config.value?.projectConfig?.title,
issued: { "date-parts": [config.value?.projectConfig?.pubDate] } as CSLDate,
},
);
const data = computed<CSLJSON>(() => {
if (props.type === "entry" && props.header) {
return {
type: "entry",
editor: config.value?.projectConfig?.editors as Array<CSLName>,
"container-title": config.value?.projectConfig?.title as string,
title: props.header.title as string,
author: (props.header.author ?? props.header.transcription ?? []) as Array<CSLName>,
issued: { "date-parts": [config.value?.projectConfig?.pubDate] } as CSLDate,
};
} else if (props.type === "book" && props.bibl) {
return {
type: "book",
title: props.bibl.title as string,
author: props.bibl.author as Array<CSLName>,
issued: { "date-parts": [props.bibl.issued?.map((i) => parseInt(i))] } as CSLDate,
publisherPlace: props.bibl.publisherPlace!,
};
} else if (props.type === "chapter" && props.bibl) {
return {
type: "chapter",
editor: props.bibl.editor as Array<CSLName>,
"container-title": props.bibl["container-title"] ? props.bibl["container-title"] : "",
title: props.bibl.title as string,
author: props.bibl.author as Array<CSLName>,
issued: { "date-parts": [props.bibl.issued?.map((i) => parseInt(i))] } as CSLDate,
publisherPlace: props.bibl.publisherPlace,
page: props.bibl.page,
};
} else if (props.type === "journalArticle" && props.bibl) {
return {
type: "article-journal",
editor: props.bibl.editor as Array<CSLName>,
"container-title": props.bibl["container-title"] ? props.bibl["container-title"] : "",
title: props.bibl.title as string,
author: props.bibl.author as Array<CSLName>,
issued: { "date-parts": [props.bibl.issued?.map((i) => parseInt(i))] } as CSLDate,
publisherPlace: props.bibl.publisherPlace,
page: props.bibl.page,
volume: props.bibl.volume,
};
} else {
return {
type: "software",
editor: config.value?.projectConfig?.editors as Array<CSLName>,
title: config.value?.projectConfig?.title,
issued: { "date-parts": [config.value?.projectConfig?.pubDate] } as CSLDate,
};
}
});
const url = window.location.href.replace(/(https?:\/\/.+)[/?].*/, "$1");
const cite = new Cite(data.value);
const appendText =
props.refType === "external"
? ""
: ` [Available online at ${url}. Accessed on ${String(date.getFullYear())}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}.]`;
const citation = computed(() =>
cite.format("bibliography", {
format: "html",
template: "apa",
// prepend (entry) {
// return `[${entry.id}]: `
// },
append: ` [Available online at ${url}.
Accessed on ${String(date.getFullYear())}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}.]`,
append: appendText,
}),
);
const citationText = computed(() =>
cite.format("bibliography", {
format: "text",
template: "apa",
// prepend (entry) {
// return `[${entry.id}]: `
// },
append: ` [Available online at ${url}.
Accessed on ${String(date.getFullYear())}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}.]`,
append: appendText,
}),
);
Expand All @@ -76,7 +122,9 @@ async function copyToClipboard(e: Event) {
</script>

<template>
<div class="m-4 flex flex-wrap gap-3 rounded-sm border-gray-300 bg-gray-100 p-4">
<!-- eslint-disable vue/no-v-html -->
<div v-if="props.refType === 'external'" v-html="citation" />
<div v-else class="m-4 flex flex-wrap gap-3 rounded-sm border-gray-300 bg-gray-100 p-4">
<div class="flex-none"><Quote class="h-4" /></div>
<!-- eslint-disable vue/no-v-html -->
<div class="flex-1" v-html="citation" />
Expand Down
Loading

0 comments on commit d365909

Please sign in to comment.