PronounsPage/components/SourceItem.vue

165 lines
6.9 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import type { Source } from '~/src/classes.ts';
import { loadPronounLibrary } from '~/src/data.ts';
import { getUrlForLocale } from '~/src/domain.ts';
import { changeSourceInjectionKey } from '~/src/injectionKeys.ts';
defineProps<{
source: Source;
}>();
const config = useConfig();
const pronounLibrary = await loadPronounLibrary(config);
const versionsShown = ref(false);
const showSpoiler = ref(false);
const changeSource = inject(changeSourceInjectionKey, undefined);
const addMarks = (t: string) => {
return t.replace(/\[\[/g, '<mark>').replace(/]]/g, '</mark>');
};
</script>
<template>
<div class="my-2 clearfix">
<h3 class="h6">
<Icon :v="source.icon()" />
<strong><Spelling v-if="source.author" :text="source.author.replace('^', '')" /><span v-if="source.author"> </span><em><a v-if="source.link" :href="source.link" target="_blank" rel="noopener"><Spelling :text="addMarks(source.title)" /></a><Spelling v-else :text="addMarks(source.title)" /></em></strong><template v-if="source.extra">
(<Spelling :text="source.extra" />)
</template>, {{ source.year }}<template v-if="source.comment">
; <Spelling :text="source.comment" />
</template>
<ul v-if="changeSource !== undefined && !$isGranted('sources')" class="list-inline float-end">
<li class="list-inline-item">
<button type="button" class="btn btn-outline-secondary btn-sm btn-concise" @click="changeSource.edit(source)">
<Icon v="pen" />
<span class="btn-label">
<T>nouns.edit</T>
</span>
</button>
</li>
</ul>
</h3>
<ul v-if="changeSource !== undefined && $isGranted('sources')" class="list-inline">
<li v-if="!source.approved" class="list-inline-item">
<span class="badge bg-danger">
<Icon v="map-marker-question" />
<T>nouns.pending</T>
</span>
</li>
<li v-if="source.submitter" class="list-inline-item">
<nuxt-link :to="`/@${source.submitter}`" class="badge bg-light text-dark border btn-sm m-1">
<Icon v="user" />
<span class="btn-label">
<T>crud.author</T><T>quotation.colon</T>
@{{ source.submitter }}
</span>
</nuxt-link>
</li>
<li v-if="!source.approved" class="list-inline-item">
<button type="button" class="badge btn btn-success btn-sm" @click="changeSource.approve(source)">
<Icon v="check" />
<span class="btn-label"><T>crud.approve</T></span>
</button>
</li>
<li v-else class="list-inline-item">
<button type="button" class="badge btn btn-secondary btn-sm" @click="changeSource.hide(source)">
<Icon v="times" />
<span class="btn-label"><T>crud.hide</T></span>
</button>
</li>
<li class="list-inline-item">
<button type="button" class="badge btn btn-danger btn-sm" @click="changeSource.remove(source)">
<Icon v="trash" />
<span class="btn-label"><T>crud.remove</T></span>
</button>
</li>
<li class="list-inline-item">
<button type="button" class="badge btn btn-secondary btn-sm" @click="changeSource.edit(source)">
<Icon v="pen" />
<span class="btn-label">
<T>crud.edit</T>
</span>
</button>
</li>
<li class="list-inline-item">
<span
v-for="p in source.pronouns"
:class="['badge', pronounLibrary.isCanonical(p) || (config.sources.extraTypes || []).includes(p) ? 'bg-success' : 'bg-danger', 'm-1']"
>
<Spelling :text="p" />
</span>
</li>
<li v-if="source.key" class="list-inline-item">
<span class="badge bg-primary text-white">
<T>sources.submit.key</T><T>quotation.colon</T> {{ source.key }}
</span>
</li>
</ul>
<div v-if="source.spoiler && !showSpoiler" class="py-3">
<button type="button" class="btn btn-outline-primary" @click="showSpoiler = true">
<Icon v="eye-slash" />
<T>sources.submit.spoiler</T>
</button>
</div>
<div v-else>
<div v-if="source.images.length" class="source-images">
<ImageThumb v-for="image in source.images" :id="image" :key="image" class="m-2" size="8rem" />
</div>
<ul v-if="source.fragments.length">
<li v-for="fragment in source.fragments" class="text-break">
<T>quotation.start</T><Spelling :text="addMarks(fragment.replace(/\n/g, '<br/>'))" /><T>quotation.end</T>
</li>
</ul>
</div>
<div v-if="source.versions.length" class="my-3">
<p>
<button
type="button"
:class="['btn', versionsShown ? 'btn-primary' : 'btn-outline-primary', 'btn-sm']"
@click="versionsShown = !versionsShown"
>
<Icon v="language" />
<T>sources.otherVersions</T>
<Icon :v="versionsShown ? 'caret-up' : 'caret-down'" />
</button>
</p>
<ul v-if="versionsShown" class="clearfix">
<template v-for="version in source.versions">
<li v-if="$locales[version.locale] !== undefined">
<h4 class="h6 mb-2">
<strong>
<a
:href="`${getUrlForLocale(version.locale)}/${version.pronouns[0]}`"
target="_blank"
rel="noopener"
>{{ $locales[version.locale].fullName }}</a>:
</strong>
</h4>
<SourceItem :source="version" />
</li>
</template>
</ul>
</div>
</div>
</template>
<style lang="scss" scoped>
@import "assets/variables";
@include media-breakpoint-down('sm', $grid-breakpoints) {
.source-images {
text-align: center;
}
}
@include media-breakpoint-up('md', $grid-breakpoints) {
.source-images {
float: right;
max-width: 18rem;
}
}
</style>