PronounsPage/components/SourceSubmitForm.vue

279 lines
10 KiB
Vue

<template>
<div class="card">
<div class="card-header">
<Icon v="plus-circle" />
<T>sources.submit.header</T>
</div>
<div v-if="$user()" class="card-body">
<div v-if="afterSubmit" class="alert alert-success text-center">
<p>
<T>sources.submit.thanks</T>
</p>
<p>
<button class="btn btn-success" @click="afterSubmit = false">
<Icon v="plus" />
<T>sources.submit.another</T>
</button>
</p>
</div>
<form v-else @submit.prevent="submit">
<div class="form-group">
<label for="type" class="required"><T>sources.submit.type</T></label>
<select id="type" v-model="form.type" class="form-control" required>
<option value=""></option>
<template v-for="t in Object.keys(sourceTypes)">
<option v-if="t !== ''" :key="t" :value="t">
{{ $t(`sources.type.${t}`) }}
</option>
</template>
</select>
</div>
<div class="form-group">
<label for="author"><T>sources.submit.author</T></label>
<input
id="author"
v-model="form.author"
type="text"
class="form-control"
maxlength="255"
>
</div>
<div class="form-group">
<label for="title" class="required"><T>sources.submit.title</T></label>
<input
id="title"
v-model="form.title"
type="text"
class="form-control"
required
maxlength="255"
>
</div>
<div class="form-group">
<label for="extra"><T>sources.submit.extra</T></label>
<input
id="extra"
v-model="form.extra"
type="text"
class="form-control"
maxlength="255"
>
</div>
<div class="form-group">
<label for="year"><T>sources.submit.year</T></label>
<input
id="year"
v-model="form.year"
type="number"
class="form-control"
min="0"
max="2100"
>
</div>
<div class="form-group">
<label for="fragments"><T>sources.submit.fragments</T></label>
<p class="small text-muted mb-0">
<T>sources.submit.fragmentsInfo</T>
</p>
<ListInput id="fragments" v-slot="s" v-model="form.fragments">
<textarea v-model="s.val" class="form-control" rows="3" required @keyup="s.update(s.val)"></textarea>
</ListInput>
</div>
<div class="form-group">
<div class="form-check form-switch my-2">
<label>
<input v-model="form.spoiler" class="form-check-input" type="checkbox">
<T>sources.submit.spoiler</T>
</label>
</div>
</div>
<div class="form-group">
<label for="pronouns" class="required"><T>sources.submit.pronouns</T></label>
<p class="small text-muted mb-0">
<T>sources.submit.pronounsInfo</T>
</p>
<ListInput v-model="form.pronouns">
<template #default="s">
<input
v-model="s.val"
type="text"
class="form-control"
required
maxlength="24"
@keyup="s.update(s.val)"
>
</template>
<template #validation="s">
<p
v-if="s.val && !pronounLibrary.isCanonical(s.val) && !($config.sources.extraTypes || []).includes(s.val)"
class="small text-danger"
>
<Icon v="exclamation-triangle" />
<span class="ml-1"><T>profile.pronounsNotFound</T></span>
</p>
</template>
</ListInput>
</div>
<div class="form-group">
<label for="comment"><T>sources.submit.comment</T></label>
<input
id="comment"
v-model="form.comment"
type="text"
class="form-control"
maxlength="255"
>
</div>
<div class="form-group">
<label for="link"><T>sources.submit.link</T></label>
<input
id="link"
v-model="form.link"
type="url"
class="form-control"
maxlength="255"
>
</div>
<div class="form-group">
<label><T>sources.submit.images</T></label>
<ImageWidget v-model="form.images" multiple sizes="big,thumb" />
</div>
<div v-if="$isGranted('sources')" class="form-group">
<label for="key"><T>sources.submit.key</T></label>
<input
id="key"
v-model="form.key"
type="text"
class="form-control"
maxlength="255"
>
<p class="small text-muted">
<T>sources.submit.keyInfo</T>
</p>
</div>
<div v-if="form.base" class="alert alert-info">
<Icon v="info-circle" />
<T>nouns.editing</T>
<button class="btn btn-sm float-end" @click="form.base = null">
<Icon v="times" />
</button>
</div>
<button class="btn btn-success w-100" :disabled="submitting">
<Icon v="plus-circle" />
<T>sources.submit.action</T>
</button>
<p class="small text-muted mt-1">
<T>sources.submit.moderation</T>
</p>
</form>
</div>
<div v-else class="card-body py-5 text-center">
<T>crud.loginRequired</T>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { pronounLibrary } from '../src/data.ts';
import type { PronounLibrary } from '../src/classes.ts';
import { Source } from '../src/classes.ts';
interface Data {
form: {
pronouns: string[],
type: string,
author: string,
title: string,
extra: string,
year: number | null,
fragments: string[],
comment: string | null,
images: string[],
link: string | null,
spoiler: boolean,
key: string | null,
base: string | null,
};
sourceTypes: typeof Source.TYPES;
submitting: boolean;
afterSubmit: boolean;
pronounLibrary: PronounLibrary;
}
export default Vue.extend({
data(): Data {
return {
form: {
pronouns: [''],
type: '',
author: '',
title: '',
extra: '',
year: null,
fragments: [],
comment: '',
images: [],
link: '',
spoiler: false,
key: null,
base: null,
},
sourceTypes: Source.TYPES,
submitting: false,
afterSubmit: false,
pronounLibrary,
};
},
methods: {
async submit(): Promise<void> {
this.submitting = true;
try {
await this.$post('/sources/submit', this.form);
this.afterSubmit = true;
this.form = {
pronouns: [''],
type: '',
author: '',
title: '',
extra: '',
year: null,
fragments: [],
comment: '',
images: [],
link: '',
spoiler: false,
key: null,
base: null,
};
} finally {
this.submitting = false;
}
},
edit(source: Source): void {
this.form = {
pronouns: source.pronouns,
type: source.type,
author: source.author,
title: source.title,
extra: source.extra,
year: source.year,
fragments: source.fragments,
comment: source.comment,
images: source.images,
link: source.link,
spoiler: source.spoiler,
key: source.key,
base: source.id,
};
this.afterSubmit = false;
this.$el.scrollIntoView();
},
},
});
</script>