mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-05 03:57:03 -04:00
165 lines
6.9 KiB
Vue
165 lines
6.9 KiB
Vue
<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>
|