mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-05 03:57:03 -04:00
200 lines
6.6 KiB
Vue
200 lines
6.6 KiB
Vue
<template>
|
|
<section v-if="config.terminology.enabled && $user()" ref="section" class="px-md-3 scroll-mt-7">
|
|
<div v-if="afterSubmit" class="alert alert-success text-center">
|
|
<p>
|
|
<T>nouns.submit.thanks</T>
|
|
</p>
|
|
<p>
|
|
<button type="button" class="btn btn-success" @click="focus()">
|
|
<Icon v="plus" />
|
|
<T>nouns.submit.another</T>
|
|
</button>
|
|
</p>
|
|
</div>
|
|
<form v-else @submit.prevent="submit">
|
|
<div class="row">
|
|
<div class="col-12 col-lg-6">
|
|
<div class="form-group">
|
|
<label class="text-nowrap"><strong>
|
|
<T>terminology.term</T>
|
|
</strong></label>
|
|
<ListInput v-model="form.term" :maxlength="128" :minitems="1" />
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-lg-6">
|
|
<div class="form-group">
|
|
<label class="text-nowrap"><strong>
|
|
<T>terminology.original</T>
|
|
</strong></label>
|
|
<ListInput v-model="form.original" :maxlength="1024" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="text-nowrap"><strong>
|
|
<T>terminology.definition</T>
|
|
</strong></label>
|
|
<textarea v-model="form.definition" class="form-control form-control-sm" required rows="6"></textarea>
|
|
</div>
|
|
|
|
<CategoriesSelector
|
|
v-model="form.categories"
|
|
:label="$t('terminology.category')"
|
|
:categories="config.terminology.categories"
|
|
/>
|
|
|
|
<div class="row">
|
|
<div class="col-12 col-lg-4">
|
|
<label for="key"><strong><T>sources.submit.key</T></strong></label>
|
|
<AutocompleteSelect v-model="form.key" :options="keys" maxlength="255" freeform />
|
|
<p class="small text-muted">
|
|
<T>sources.submit.keyInfo</T>
|
|
<T>sources.submit.keyInfoConvention</T>
|
|
</p>
|
|
</div>
|
|
<div class="col-12 col-lg-4">
|
|
<div class="form-group">
|
|
<label class="text-nowrap"><strong>
|
|
<T>profile.flags</T>
|
|
</strong></label>
|
|
<FlagList v-model="form.flags" />
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-lg-4">
|
|
<div class="form-group">
|
|
<label>
|
|
<strong><T>terminology.images</T></strong>
|
|
</label>
|
|
<ImageWidget v-model="form.images" multiple sizes="flag" small-size="flag" big-size="flag" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="form.base" class="alert alert-info">
|
|
<Icon v="info-circle" />
|
|
<T>nouns.editing</T>
|
|
<button type="button" class="btn btn-sm float-end" @click="form.base = null">
|
|
<Icon v="times" />
|
|
</button>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary w-100" :disabled="submitting">
|
|
<template v-if="submitting">
|
|
<Icon v="circle-notch fa-spin" />
|
|
</template>
|
|
<template v-else>
|
|
<Icon v="plus" />
|
|
<T>nouns.submit.actionLong</T>
|
|
</template>
|
|
</button>
|
|
<p class="small text-muted mt-1">
|
|
<T>nouns.submit.moderation</T>
|
|
</p>
|
|
</form>
|
|
</section>
|
|
<section v-else ref="section" class="text-center">
|
|
<div class="alert alert-info">
|
|
<T>crud.loginRequired</T>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent } from 'vue';
|
|
|
|
import useConfig from '../composables/useConfig.ts';
|
|
import useDialogue from '../composables/useDialogue.ts';
|
|
import type { TermsEntry } from '../src/classes.ts';
|
|
|
|
interface Data {
|
|
form: {
|
|
term: string[];
|
|
original: string[];
|
|
key: string | null;
|
|
definition: string;
|
|
categories: string[];
|
|
flags: string[];
|
|
images: string[];
|
|
base: string | null;
|
|
};
|
|
submitting: boolean;
|
|
afterSubmit: boolean;
|
|
}
|
|
|
|
export default defineComponent({
|
|
emits: ['submit'],
|
|
async setup() {
|
|
const dialogue = useDialogue();
|
|
const section = useTemplateRef<HTMLElement>('section');
|
|
const { data: keys } = await useFetch('/api/terms/keys', { lazy: true, default: () => ({}) });
|
|
|
|
return {
|
|
config: useConfig(),
|
|
dialogue,
|
|
section,
|
|
keys,
|
|
};
|
|
},
|
|
data(): Data {
|
|
return {
|
|
form: {
|
|
term: [''],
|
|
original: [],
|
|
key: '',
|
|
definition: '',
|
|
categories: [],
|
|
flags: [],
|
|
images: [],
|
|
base: null,
|
|
},
|
|
submitting: false,
|
|
afterSubmit: false,
|
|
};
|
|
},
|
|
methods: {
|
|
async submit(): Promise<void> {
|
|
this.submitting = true;
|
|
try {
|
|
await this.dialogue.postWithAlertOnError('/api/terms/submit', this.form);
|
|
|
|
this.afterSubmit = true;
|
|
this.form = {
|
|
term: [''],
|
|
original: [],
|
|
key: '',
|
|
definition: '',
|
|
categories: [],
|
|
flags: [],
|
|
images: [],
|
|
base: null,
|
|
};
|
|
this.focus(false);
|
|
this.$emit('submit');
|
|
} finally {
|
|
this.submitting = false;
|
|
}
|
|
},
|
|
edit(word: TermsEntry): void {
|
|
this.form = {
|
|
term: word.term,
|
|
original: word.original,
|
|
key: word.key,
|
|
definition: word.definition,
|
|
categories: word.categories,
|
|
flags: word.flags,
|
|
images: word.images,
|
|
base: word.id,
|
|
};
|
|
this.focus();
|
|
},
|
|
focus(editable = true): void {
|
|
if (editable) {
|
|
this.afterSubmit = false;
|
|
}
|
|
this.section?.scrollIntoView();
|
|
},
|
|
},
|
|
});
|
|
</script>
|