2025-01-12 14:12:15 +01:00

221 lines
9.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 { useNuxtApp, useFetch } from 'nuxt/app';
import Suml from 'suml';
import useDialogue from '~/composables/useDialogue.ts';
import useSimpleHead from '~/composables/useSimpleHead.ts';
import { deepSet } from '~/src/helpers.ts';
interface TranslationProposal {
id: string;
tKey: string;
tValue: string | string[];
author: string;
status?: 0 | 1;
}
interface Contributor {
username: string;
isMember: boolean;
count: number;
}
const { $translator: translator } = useNuxtApp();
const dialogue = useDialogue();
useSimpleHead({
title: `${translator.translate('admin.header')} • Translation proposals`,
}, translator);
const { data: translationProposals } = useFetch<TranslationProposal[]>('/api/translations/proposals', {
default: () => [],
});
const { data: contributors } = useFetch<Contributor[]>('/api/translations/contributors', {
default: () => [],
});
await Promise.all([translationProposals, contributors]);
const translationsProposalsSuml = computed((): string => {
const data = {};
for (const tp of translationProposals.value || []) {
if (tp.status === 1) {
deepSet(data, tp.tKey, tp.tValue);
}
}
return new Suml().dump(data);
});
const acceptTranslationProposal = async (id: string): Promise<void> => {
// await this.dialogue.confirm('Do you want to accept this translation proposal?', 'success');
await dialogue.postWithAlertOnError('/api/translations/accept-proposal', { id });
translationProposals.value = translationProposals.value.map((tp) => {
if (tp.id === id) {
tp.status = 1;
}
return tp;
});
};
const rejectTranslationProposal = async (id: string): Promise<void> => {
await dialogue.confirm('Do you want to reject this translation proposal?', 'danger');
await dialogue.postWithAlertOnError('/api/translations/reject-proposal', { id });
translationProposals.value = translationProposals.value.filter((tp) => tp.id !== id);
};
const unapproveTranslationProposal = async (id: string): Promise<void> => {
await dialogue.confirm('Do you want to unmark this translation proposal as approved?', 'danger');
await dialogue.postWithAlertOnError('/api/translations/unapprove-proposal', { id });
translationProposals.value = translationProposals.value.map((tp) => {
if (tp.id === id) {
tp.status = 0;
}
return tp;
});
};
const markTranslationProposalsDone = async (): Promise<void> => {
await dialogue.confirm(`This will mark all approved translations as done and they'll disappear from here
but they'll only actually show up on production if they are added to the <code>translations.suml</code> file
and merged to the <code>main</code> branch.
Do you confirm that those translations are present in the <code>main</code> branch?`, 'success');
await dialogue.postWithAlertOnError('/api/translations/proposals-done');
translationProposals.value = translationProposals.value.filter((tp) => tp.status !== 1);
};
</script>
<template>
<Page wide>
<NotFound v-if="!$isGranted('translations') && !$isGranted('code')" />
<div v-else>
<p>
<nuxt-link to="/admin">
<Icon v="user-cog" />
<T>admin.header</T>
</nuxt-link>
</p>
<h2>
<Icon v="language" />
Translation proposals ({{ translationProposals.length }})
</h2>
<section v-if="translationProposals && translationProposals.length">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>key</th>
<th>base</th>
<th>current translation</th>
<th>new translation</th>
<th>author & status</th>
</tr>
</thead>
<tbody>
<tr v-for="tp in translationProposals">
<td>{{ tp.tKey }}</td>
<td>{{ $translator.get(tp.tKey, false, true) }}</td>
<td>{{ $te(tp.tKey) ? $t(tp.tKey) : '' }}</td>
<td>{{ tp.tValue }}</td>
<td>
<nuxt-link :to="`/@${tp.author}`">@{{ tp.author }}</nuxt-link>
<br>
<template v-if="tp.status === 0">
<span class="badge bg-warning text-white">Awaiting approval</span>
<button
v-if="$isGranted('translations')"
class="btn btn-sm btn-outline-success"
@click="acceptTranslationProposal(tp.id)"
>
Accept
</button>
<button
v-if="$isGranted('translations')"
class="btn btn-sm btn-outline-danger"
@click="rejectTranslationProposal(tp.id)"
>
Reject
</button>
</template>
<template v-else>
<span class="badge bg-success text-white">Approved</span>
<button
v-if="$isGranted('translations')"
class="btn btn-sm btn-outline-danger"
@click="unapproveTranslationProposal(tp.id)"
>
Unapprove
</button>
</template>
</td>
</tr>
</tbody>
</table>
</div>
<details class="border mb-3" :open="$isGranted('code')">
<summary class="bg-light p-3">
<span class="badge bg-success">Merge</span>
</summary>
<div class="p-2">
<p>
We still need to <strong>manually</strong> move the translations to the <code>translations.suml</code> file,
but at least it should be easy to copy paste bits from here:
</p>
<hr>
<pre dir="ltr">{{ translationsProposalsSuml }}</pre>
<hr>
<button v-if="$isGranted('code')" class="btn btn-success" @click="markTranslationProposalsDone">
Merged to the main branch, mark as done
</button>
<p v-else>
If you know Git and YAML/SUML, you can create a pull request for these changes.
You can also ask <nuxt-link to="/@andrea">@andrea</nuxt-link> for `code` permissions
`code` access means you'll be getting notifications about new translations awaiting merging
and will be able to mark them as merged in the database.
</p>
</div>
</details>
</section>
<details v-if="contributors.length" class="border mb-3">
<summary class="bg-light p-3">
Contributors
</summary>
<div class="p-2">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Contributor</th>
<th>Approved translations</th>
</tr>
</thead>
<tbody>
<tr v-for="{ username, isMember, count } in contributors">
<td>
<nuxt-link :to="`/@${username}`">@{{ username }}</nuxt-link>
<span v-if="isMember" class="badge bg-primary text-white">
<Icon v="collective-logo.svg" class="inverted" />
<T>contact.team.member</T>
</span>
</td>
<td>
{{ count }}
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2" class="small">
This overview only considers translations submitted via the web interface, not gitlab/gdocs.
Let's use it to consider inviting people to the team.
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</details>
</div>
</Page>
</template>