mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-05 03:57:03 -04:00
120 lines
3.8 KiB
Vue
120 lines
3.8 KiB
Vue
<script setup lang="ts">
|
|
import Suml from 'suml';
|
|
|
|
import useConfig from '~/composables/useConfig.ts';
|
|
import useDialogue from '~/composables/useDialogue.ts';
|
|
import { useMainStore } from '~/store/index.ts';
|
|
|
|
const { $isGranted: isGranted } = useNuxtApp();
|
|
|
|
const config = useConfig();
|
|
const store = useMainStore();
|
|
|
|
onMounted(() => {
|
|
if (isGranted('translations')) {
|
|
store.showTranslationMode();
|
|
}
|
|
});
|
|
|
|
const changesCount = computed(() => {
|
|
return Object.keys(store.translationChanges).length;
|
|
});
|
|
|
|
const dialogue = useDialogue();
|
|
const translationsCookie = useCookie('translations');
|
|
const startTranslating = () => {
|
|
store.translationInit();
|
|
};
|
|
const commitChanges = async () => {
|
|
await dialogue.confirm(`Do you want to commit ${changesCount.value} changes?`, 'success');
|
|
await dialogue.postWithAlertOnError('/api/translations/propose', {
|
|
changes: store.translationChanges,
|
|
});
|
|
store.translationCommit();
|
|
translationsCookie.value = null;
|
|
|
|
setTimeout(
|
|
() => dialogue.alert({ header: 'Your translation proposals were saved', message: 'Thank you for contributing!' }, 'success'),
|
|
500,
|
|
);
|
|
};
|
|
const revertChanges = async () => {
|
|
if (changesCount.value) {
|
|
await dialogue.confirm(`Do you want to revert ${changesCount.value} changes?`, 'danger');
|
|
}
|
|
store.translationAbort();
|
|
translationsCookie.value = null;
|
|
};
|
|
const showChanges = async () => {
|
|
await dialogue.alert({
|
|
header: 'Changes overview',
|
|
message: `<pre>${new Suml().dump(store.translationChanges)}</pre>`,
|
|
margin: false,
|
|
size: 'lg',
|
|
}, 'info');
|
|
};
|
|
const pause = async () => {
|
|
store.translationPause();
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
v-if="store.translationModeVisible && $user() && !config.disableTranslationProposals"
|
|
:class="['scroll-btn', 'd-print-none', 'd-flex', 'align-items-center', config.ads && config.ads.enabled ? 'higher' : '']"
|
|
>
|
|
<template v-if="store.translationMode">
|
|
<button
|
|
type="button"
|
|
class="btn btn-info btn-sm m-1 px-3 py-1 d-flex justify-content-center align-items-center"
|
|
@click="showChanges"
|
|
>
|
|
<small><T>translationMode.changes</T><T>quotation.colon</T> {{ changesCount }}</small>
|
|
</button>
|
|
<div v-if="changesCount" @click.prevent="commitChanges">
|
|
<SquareButton link="#" colour="success" :title="$t('translationMode.commit')">
|
|
<Icon v="check-circle" />
|
|
</SquareButton>
|
|
</div>
|
|
<div v-if="changesCount" @click.prevent="revertChanges">
|
|
<SquareButton link="#" colour="danger" :title="$t('translationMode.revert')">
|
|
<Icon v="times-circle" />
|
|
</SquareButton>
|
|
</div>
|
|
<div @click.prevent="pause">
|
|
<SquareButton link="#" colour="info" :title="$t('translationMode.header')">
|
|
<Icon v="pause-circle" />
|
|
</SquareButton>
|
|
</div>
|
|
</template>
|
|
<div v-else @click.prevent="startTranslating">
|
|
<SquareButton link="#" colour="info" :title="$t('translationMode.header')">
|
|
<Icon v="language" />
|
|
</SquareButton>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "assets/variables";
|
|
|
|
.scroll-btn {
|
|
position: fixed;
|
|
bottom: 2 * $spacer + $square-button-size;
|
|
right: $spacer;
|
|
z-index: 1030;
|
|
}
|
|
|
|
@include media-breakpoint-down('lg', $grid-breakpoints) {
|
|
.higher {
|
|
bottom: 4 * $spacer + $square-button-size;
|
|
}
|
|
}
|
|
@include media-breakpoint-up('lg', $grid-breakpoints) {
|
|
.higher {
|
|
z-index: 100001;
|
|
bottom: 6 * $spacer + $square-button-size;
|
|
}
|
|
}
|
|
</style>
|