mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-16 19:16:54 -04:00
(ts) migrate sources components to composition API with typescript
This commit is contained in:
parent
50a9c7afbe
commit
0b602028ee
@ -62,7 +62,7 @@
|
|||||||
<p><strong><T>sources.referenced</T><T>quotation.colon</T></strong></p>
|
<p><strong><T>sources.referenced</T><T>quotation.colon</T></strong></p>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li v-for="source in s.el.sourcesData">
|
<li v-for="source in s.el.sourcesData">
|
||||||
<Source :source="source" />
|
<SourceItem :source="source" />
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,3 +1,24 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { getPronoun } from '~/src/buildPronoun.ts';
|
||||||
|
import type { Pronoun, Source } from '~/src/classes.ts';
|
||||||
|
import { pronouns } from '~/src/data.ts';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
pronoun?: Pronoun;
|
||||||
|
sources: Record<string, Source[] | undefined>;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { $translator: translator } = useNuxtApp();
|
||||||
|
|
||||||
|
const glue = ` ${translator.translate('pronouns.or')} `;
|
||||||
|
|
||||||
|
const visibleSources = computed((): Record<string, Source[]> => {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(props.sources).filter(([_, sources]) => sources),
|
||||||
|
) as Record<string, Source[]>;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="Object.keys(visibleSources).length">
|
<div v-if="Object.keys(visibleSources).length">
|
||||||
<h2 class="h4">
|
<h2 class="h4">
|
||||||
@ -25,33 +46,3 @@
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import type { PropType } from 'vue';
|
|
||||||
|
|
||||||
import { getPronoun } from '../src/buildPronoun.ts';
|
|
||||||
import type { Source } from '../src/classes.ts';
|
|
||||||
import { pronouns } from '../src/data.ts';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
props: {
|
|
||||||
pronoun: { },
|
|
||||||
sources: { required: true, type: Object as PropType<Record<string, Source[] | undefined>> },
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pronouns,
|
|
||||||
getPronoun,
|
|
||||||
glue: ` ${this.$t('pronouns.or')} `,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
visibleSources(): Record<string, Source[]> {
|
|
||||||
return Object.fromEntries(
|
|
||||||
Object.entries(this.sources).filter(([_, sources]) => sources),
|
|
||||||
) as Record<string, Source[]>;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,48 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { LazyHydrationWrapper } from 'vue3-lazy-hydration';
|
||||||
|
|
||||||
|
import type { Source } from '~/src/classes.ts';
|
||||||
|
import { pronounLibrary } from '~/src/data.ts';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
source: Source;
|
||||||
|
manage?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'edit-source': [Source];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { $translator: translator } = useNuxtApp();
|
||||||
|
|
||||||
|
const config = useConfig();
|
||||||
|
const dialogue = useDialogue();
|
||||||
|
|
||||||
|
const deleted = ref(false);
|
||||||
|
const versionsShown = ref(false);
|
||||||
|
const showSpoiler = ref(false);
|
||||||
|
|
||||||
|
const approve = async () => {
|
||||||
|
await dialogue.postWithAlertOnError(`/api/sources/approve/${props.source.id}`);
|
||||||
|
props.source.approved = true;
|
||||||
|
props.source.base_id = null;
|
||||||
|
};
|
||||||
|
const hide = async () => {
|
||||||
|
await dialogue.postWithAlertOnError(`/api/sources/hide/${props.source.id}`);
|
||||||
|
props.source.approved = false;
|
||||||
|
};
|
||||||
|
const remove = async () => {
|
||||||
|
await dialogue.confirm(translator.translate('crud.removeConfirm'), 'danger');
|
||||||
|
|
||||||
|
await dialogue.postWithAlertOnError(`/api/sources/remove/${props.source.id}`);
|
||||||
|
deleted.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addMarks = (t: string) => {
|
||||||
|
return t.replace(/\[\[/g, '<mark>').replace(/]]/g, '</mark>');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LazyHydrationWrapper when-visible>
|
<LazyHydrationWrapper when-visible>
|
||||||
<div v-if="!deleted" class="my-2 clearfix">
|
<div v-if="!deleted" class="my-2 clearfix">
|
||||||
@ -44,7 +89,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<a href="#" class="badge bg-light text-dark border border-primary btn-sm m-1" @click.prevent="$emit('edit-source', source)">
|
<a href="#" class="badge bg-light text-dark border border-primary btn-sm m-1" @click.prevent="emit('edit-source', source)">
|
||||||
<Icon v="pen" />
|
<Icon v="pen" />
|
||||||
<span class="btn-label">
|
<span class="btn-label">
|
||||||
<T>crud.edit</T>
|
<T>crud.edit</T>
|
||||||
@ -101,7 +146,7 @@
|
|||||||
>{{ $locales[version.locale].name }}</a>:
|
>{{ $locales[version.locale].name }}</a>:
|
||||||
</strong>
|
</strong>
|
||||||
</h4>
|
</h4>
|
||||||
<Source :source="version" />
|
<SourceItem :source="version" />
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
@ -110,60 +155,6 @@
|
|||||||
</LazyHydrationWrapper>
|
</LazyHydrationWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { LazyHydrationWrapper } from 'vue3-lazy-hydration';
|
|
||||||
|
|
||||||
import useConfig from '../composables/useConfig.ts';
|
|
||||||
import useDialogue from '../composables/useDialogue.ts';
|
|
||||||
import { pronounLibrary } from '../src/data.ts';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: { LazyHydrationWrapper },
|
|
||||||
props: {
|
|
||||||
source: { required: true },
|
|
||||||
manage: { type: Boolean },
|
|
||||||
},
|
|
||||||
emits: ['edit-source'],
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
config: useConfig(),
|
|
||||||
dialogue: useDialogue(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pronounLibrary,
|
|
||||||
deleted: false,
|
|
||||||
versionsShown: false,
|
|
||||||
showSpoiler: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async approve() {
|
|
||||||
await this.dialogue.postWithAlertOnError(`/api/sources/approve/${this.source.id}`);
|
|
||||||
this.source.approved = true;
|
|
||||||
this.source.base = null;
|
|
||||||
this.$forceUpdate();
|
|
||||||
},
|
|
||||||
async hide() {
|
|
||||||
await this.dialogue.postWithAlertOnError(`/api/sources/hide/${this.source.id}`);
|
|
||||||
this.source.approved = false;
|
|
||||||
this.$forceUpdate();
|
|
||||||
},
|
|
||||||
async remove() {
|
|
||||||
await this.dialogue.confirm(this.$t('crud.removeConfirm'), 'danger');
|
|
||||||
|
|
||||||
await this.dialogue.postWithAlertOnError(`/api/sources/remove/${this.source.id}`);
|
|
||||||
this.deleted = true;
|
|
||||||
this.$forceUpdate();
|
|
||||||
},
|
|
||||||
addMarks(t) {
|
|
||||||
return t.replace(/\[\[/g, '<mark>').replace(/]]/g, '</mark>');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "assets/variables";
|
@import "assets/variables";
|
||||||
|
|
@ -1,3 +1,42 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { Source, Filter, Pronoun } from '~/src/classes.ts';
|
||||||
|
import { makeId } from '~/src/helpers.ts';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
sources: Source[];
|
||||||
|
pronoun?: Pronoun;
|
||||||
|
filter?: Filter;
|
||||||
|
manage?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits< {
|
||||||
|
'edit-source': [Source];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const sourcesUnique = computed(() => {
|
||||||
|
const sourcesMap: Record<string, Source> = {};
|
||||||
|
for (const source of props.sources) {
|
||||||
|
sourcesMap[source.id] = source;
|
||||||
|
}
|
||||||
|
return Object.values(sourcesMap);
|
||||||
|
});
|
||||||
|
|
||||||
|
const edit = (source: Source) => {
|
||||||
|
// TODO it should be possible to do it nicer
|
||||||
|
emit('edit-source', source);
|
||||||
|
};
|
||||||
|
|
||||||
|
const visibleSources = computed(() => {
|
||||||
|
return sourcesUnique.value.filter((source) => !props.filter || source.matches(props.filter));
|
||||||
|
});
|
||||||
|
|
||||||
|
const notEmpty = computed(() => {
|
||||||
|
return visibleSources.value.length > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const listId = makeId(6);
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="notEmpty">
|
<div v-if="notEmpty">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
@ -8,59 +47,8 @@
|
|||||||
<SourcesChart :sources="sources" :label="pronoun ? pronoun.name() : ''" />
|
<SourcesChart :sources="sources" :label="pronoun ? pronoun.name() : ''" />
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li v-for="source in visibleSources" :key="`${source.id}-${listId}`" class="my-2 clearfix">
|
<li v-for="source in visibleSources" :key="`${source.id}-${listId}`" class="my-2 clearfix">
|
||||||
<Source :source="source" :manage="manage" @edit-source="edit" />
|
<SourceItem :source="source" :manage="manage" @edit-source="edit" />
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { makeId } from '../src/helpers.ts';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
sources: { required: true },
|
|
||||||
pronoun: { },
|
|
||||||
filter: { default: '' },
|
|
||||||
filterType: { default: '' },
|
|
||||||
manage: { type: Boolean },
|
|
||||||
},
|
|
||||||
emits: ['edit-source'],
|
|
||||||
data() {
|
|
||||||
const sourcesMap = {};
|
|
||||||
for (const source of this.sources) {
|
|
||||||
sourcesMap[source.id] = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
listId: makeId(6),
|
|
||||||
sourcesUnique: Object.values(sourcesMap),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
visibleSources() {
|
|
||||||
return this.sourcesUnique.filter(this.isVisible);
|
|
||||||
},
|
|
||||||
notEmpty() {
|
|
||||||
return this.visibleSources.length > 0;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
isVisible(source) {
|
|
||||||
if (this.filterType && this.filterType !== source.type) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.filter) {
|
|
||||||
return source.index.includes(this.filter.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
edit(source) {
|
|
||||||
// TODO it should be possible to do it nicer
|
|
||||||
this.$emit('edit-source', source);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,47 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { SourceRaw, Source } from '~/src/classes.ts';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
sources: (SourceRaw | Source)[] | null;
|
||||||
|
label: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const open = ref(false);
|
||||||
|
|
||||||
|
const publishDates = computed(() => {
|
||||||
|
if (props.sources === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const dates: Record<number, number> = {};
|
||||||
|
let count = 0;
|
||||||
|
let min, max;
|
||||||
|
for (const source of props.sources) {
|
||||||
|
if (source.year) {
|
||||||
|
if (dates[source.year] === undefined) {
|
||||||
|
dates[source.year] = 0;
|
||||||
|
}
|
||||||
|
dates[source.year]++;
|
||||||
|
count++;
|
||||||
|
if (min === undefined || source.year < min) {
|
||||||
|
min = source.year;
|
||||||
|
}
|
||||||
|
if (max === undefined || source.year > max) {
|
||||||
|
max = source.year;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(dates).length < 2 || count < 5 || min === undefined || max === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (let i = min + 1; i < max; i++) {
|
||||||
|
if (dates[i] === undefined) {
|
||||||
|
dates[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dates;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="publishDates !== null && $isGranted('sources')" class="card">
|
<div v-if="publishDates !== null && $isGranted('sources')" class="card">
|
||||||
<a class="card-header cursor-pointer" href="#" @click.prevent="open = !open">
|
<a class="card-header cursor-pointer" href="#" @click.prevent="open = !open">
|
||||||
@ -14,51 +58,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
sources: { required: true },
|
|
||||||
label: { required: true },
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
open: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
publishDates() {
|
|
||||||
if (this.sources === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const dates = {};
|
|
||||||
let count = 0;
|
|
||||||
let min, max;
|
|
||||||
for (const source of this.sources) {
|
|
||||||
if (source.year) {
|
|
||||||
if (dates[source.year] === undefined) {
|
|
||||||
dates[source.year] = 0;
|
|
||||||
}
|
|
||||||
dates[source.year]++;
|
|
||||||
count++;
|
|
||||||
if (min === undefined || source.year < min) {
|
|
||||||
min = source.year;
|
|
||||||
}
|
|
||||||
if (max === undefined || source.year > max) {
|
|
||||||
max = source.year;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Object.keys(dates).length < 2 || count < 5) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (let i = min + 1; i < max; i++) {
|
|
||||||
if (dates[i] === undefined) {
|
|
||||||
dates[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dates;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,68 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type SourceSubmitForm from '~/components/SourceSubmitForm.vue';
|
||||||
|
import { Source, SourceLibrary } from '~/src/classes.ts';
|
||||||
|
import type { SourceRaw } from '~/src/classes.ts';
|
||||||
|
import { pronouns, pronounLibrary } from '~/src/data.ts';
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
translatedPaths: (config) => translatedPathByConfigModule(config.sources),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { $translator: translator } = useNuxtApp();
|
||||||
|
const config = useConfig();
|
||||||
|
useSimpleHead({
|
||||||
|
title: translator.translate('sources.headerLonger'),
|
||||||
|
description: translator.translate('sources.subheader'),
|
||||||
|
}, translator);
|
||||||
|
|
||||||
|
const filter = useFilterWithCategory();
|
||||||
|
|
||||||
|
const { data: sources } = await useFetch<SourceRaw[]>('/api/sources', { lazy: true });
|
||||||
|
const sourceLibrary = computed(() => {
|
||||||
|
if (sources.value === null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return new SourceLibrary(config, sources.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const tocShown = ref(false);
|
||||||
|
const glue = ` ${translator.translate('pronouns.or')} `;
|
||||||
|
const submitShown = ref(false);
|
||||||
|
|
||||||
|
const tocPronounGroups = computed(() => {
|
||||||
|
const pronounGroups = pronounLibrary.split((pronoun) => {
|
||||||
|
if (sourceLibrary.value === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return sourceLibrary.value.getForPronoun(pronoun.canonicalName).length > 0;
|
||||||
|
}, false);
|
||||||
|
return [...pronounGroups].filter(([_, groupPronouns]) => groupPronouns.length > 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const categories = computed(() => {
|
||||||
|
return Object.entries(Source.TYPES)
|
||||||
|
.filter(([type]) => type)
|
||||||
|
.map(([type, icon]) => ({
|
||||||
|
key: type,
|
||||||
|
text: translator.translate(`sources.type.${type}`),
|
||||||
|
icon,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
const toId = (str: string): string => {
|
||||||
|
return str.replace(/\//g, '-').replace(/&/g, '_');
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = useTemplateRef<InstanceType<typeof SourceSubmitForm>>('form');
|
||||||
|
|
||||||
|
const edit = (source: Source) => {
|
||||||
|
submitShown.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
form.value?.edit(source);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page v-if="config.sources.enabled">
|
<Page v-if="config.sources.enabled">
|
||||||
<h2>
|
<h2>
|
||||||
@ -96,8 +161,7 @@
|
|||||||
<SourceList
|
<SourceList
|
||||||
:sources="sourceLibrary.getForPronoun(pronoun.canonicalName)"
|
:sources="sourceLibrary.getForPronoun(pronoun.canonicalName)"
|
||||||
:pronoun="pronoun"
|
:pronoun="pronoun"
|
||||||
:filter="filter.text"
|
:filter="filter"
|
||||||
:filter-type="filter.category"
|
|
||||||
manage
|
manage
|
||||||
@edit-source="edit"
|
@edit-source="edit"
|
||||||
>
|
>
|
||||||
@ -116,8 +180,7 @@
|
|||||||
<section v-if="sourceLibrary.getForPronoun(multiple).length">
|
<section v-if="sourceLibrary.getForPronoun(multiple).length">
|
||||||
<SourceList
|
<SourceList
|
||||||
:sources="sourceLibrary.getForPronoun(multiple)"
|
:sources="sourceLibrary.getForPronoun(multiple)"
|
||||||
:filter="filter.text"
|
:filter="filter"
|
||||||
:filter-type="filter.category"
|
|
||||||
manage
|
manage
|
||||||
@edit-source="edit"
|
@edit-source="edit"
|
||||||
>
|
>
|
||||||
@ -134,8 +197,7 @@
|
|||||||
<section v-if="sourceLibrary.getForPronoun('', pronounLibrary)">
|
<section v-if="sourceLibrary.getForPronoun('', pronounLibrary)">
|
||||||
<SourceList
|
<SourceList
|
||||||
:sources="sourceLibrary.getForPronoun('', pronounLibrary)"
|
:sources="sourceLibrary.getForPronoun('', pronounLibrary)"
|
||||||
:filter="filter.text"
|
:filter="filter"
|
||||||
:filter-type="filter.category"
|
|
||||||
manage
|
manage
|
||||||
@edit-source="edit"
|
@edit-source="edit"
|
||||||
>
|
>
|
||||||
@ -150,95 +212,3 @@
|
|||||||
<AdPlaceholder :phkey="['content-1', 'content-mobile-1']" />
|
<AdPlaceholder :phkey="['content-1', 'content-mobile-1']" />
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { useNuxtApp, useFetch } from 'nuxt/app';
|
|
||||||
import { defineComponent, computed } from 'vue';
|
|
||||||
|
|
||||||
import type SourceSubmitForm from '../components/SourceSubmitForm.vue';
|
|
||||||
import useConfig from '../composables/useConfig.ts';
|
|
||||||
import useSimpleHead from '../composables/useSimpleHead.ts';
|
|
||||||
import { Source, SourceLibrary } from '../src/classes.ts';
|
|
||||||
import type { SourceRaw } from '../src/classes.ts';
|
|
||||||
import { pronouns, pronounLibrary } from '../src/data.ts';
|
|
||||||
|
|
||||||
interface Refs {
|
|
||||||
form: InstanceType<typeof SourceSubmitForm> | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
async setup() {
|
|
||||||
definePageMeta({
|
|
||||||
translatedPaths: (config) => translatedPathByConfigModule(config.sources),
|
|
||||||
});
|
|
||||||
|
|
||||||
const { $translator: translator } = useNuxtApp();
|
|
||||||
const config = useConfig();
|
|
||||||
useSimpleHead({
|
|
||||||
title: translator.translate('sources.headerLonger'),
|
|
||||||
description: translator.translate('sources.subheader'),
|
|
||||||
}, translator);
|
|
||||||
|
|
||||||
const filter = useFilterWithCategory();
|
|
||||||
|
|
||||||
const { data: sources } = await useFetch<SourceRaw[]>('/api/sources', { lazy: true });
|
|
||||||
const sourceLibrary = computed(() => {
|
|
||||||
if (sources.value === null) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return new SourceLibrary(config, sources.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
config,
|
|
||||||
filter,
|
|
||||||
sources,
|
|
||||||
sourceLibrary,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pronouns,
|
|
||||||
pronounLibrary,
|
|
||||||
tocShown: false,
|
|
||||||
sourceTypes: Source.TYPES,
|
|
||||||
glue: ` ${this.$t('pronouns.or')} `,
|
|
||||||
submitShown: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
$tRefs(): Refs {
|
|
||||||
return this.$refs as unknown as Refs;
|
|
||||||
},
|
|
||||||
tocPronounGroups() {
|
|
||||||
const pronounGroups = this.pronounLibrary.split((pronoun) => {
|
|
||||||
if (this.sourceLibrary === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this.sourceLibrary.getForPronoun(pronoun.canonicalName).length > 0;
|
|
||||||
}, false);
|
|
||||||
return [...pronounGroups].filter(([_, groupPronouns]) => groupPronouns.length > 0);
|
|
||||||
},
|
|
||||||
categories() {
|
|
||||||
return Object.entries(Source.TYPES)
|
|
||||||
.filter(([type]) => type)
|
|
||||||
.map(([type, icon]) => ({
|
|
||||||
key: type,
|
|
||||||
text: this.$t(`sources.type.${type}`),
|
|
||||||
icon,
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toId(str: string): string {
|
|
||||||
return str.replace(/\//g, '-').replace(/&/g, '_');
|
|
||||||
},
|
|
||||||
edit(source: Source) {
|
|
||||||
this.submitShown = true;
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$tRefs.form?.edit(source);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
@ -273,6 +273,11 @@ export class Source {
|
|||||||
icon(): string {
|
icon(): string {
|
||||||
return Source.TYPES[this.type];
|
return Source.TYPES[this.type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matches(filter: Filter) {
|
||||||
|
return (!filter.text || !!this.index?.includes(filter.text.toLowerCase())) &&
|
||||||
|
(!filter.category || this.type === filter.category);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SourceLibrary {
|
export class SourceLibrary {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user