(nouns) add optional filter for templates in subpage and nouns submit and enable it for (pl) and (ru)

This commit is contained in:
Valentyne Stigloher 2024-06-06 13:36:18 +02:00
parent 4fad0e0fd7
commit 7123b88229
6 changed files with 123 additions and 45 deletions

View File

@ -91,9 +91,36 @@
<T>nouns.template.header</T>
</a>
<div class="card-body">
<T>nouns.template.root</T><T>quotation.colon</T>
<input v-model="templateBase" class="form-control form-control-sm d-inline-block w-auto" autofocus>
<NounTemplatesTable :template-base="templateBase">
<div class="input-group mb-3 bg-white">
<span class="input-group-text">
<Icon v="scroll-old" />
</span>
<input
v-model="templateBase"
class="form-control form-control-sm border-primary"
autofocus
:placeholder="$t('nouns.template.root')"
>
<template v-if="$config.nouns.templates.filter">
<span class="input-group-text">
<Icon v="filter" />
</span>
<input
ref="templateFilter"
v-model="templateFilter"
class="form-control form-control-sm border-primary"
:placeholder="$t('crud.filterLong')"
>
<button
v-if="templateFilter"
class="btn btn-sm btn-outline-danger"
@click="templateFilter = ''; $tRefs.templateFilter?.focus()"
>
<Icon v="times" />
</button>
</template>
</div>
<NounTemplatesTable :template-base="templateBase" :filter="templateFilter">
<template #buttons="{ template }">
<li>
<button
@ -144,6 +171,10 @@ import { abbreviations } from '../src/data.ts';
import type { Noun, MinimalNoun } from '../src/classes.ts';
import type { Config } from '../locale/config.ts';
interface Refs {
templateFilter: HTMLInputElement | undefined;
}
const emptyForm = (config: Config): MinimalNoun => {
return {
masc: [''],
@ -164,10 +195,16 @@ export default Vue.extend({
submitting: false,
afterSubmit: false,
templateBase: '',
templateFilter: '',
templateVisible: false,
abbreviations,
};
},
computed: {
$tRefs(): Refs {
return this.$refs as unknown as Refs;
},
},
methods: {
async applyTemplate(template: MinimalNoun): Promise<void> {
if (JSON.stringify(this.form) !== JSON.stringify(emptyForm(this.$config))) {

View File

@ -1,27 +1,21 @@
<template>
<table class="table table-striped table-hover table-fixed-3 mt-2">
<thead>
<tr>
<Table :data="templates" :columns="3" fixed>
<template #header>
<th class="text-nowrap">
<Icon v="mars" />
<span class="d-none d-md-inline"><T>nouns.masculine</T></span>
<span class="d-md-none"><T>nouns.masculineShort</T></span>
<T>nouns.masculine</T>
</th>
<th class="text-nowrap">
<Icon v="venus" />
<span class="d-none d-md-inline"><T>nouns.feminine</T></span>
<span class="d-md-none"><T>nouns.feminineShort</T></span>
<T>nouns.feminine</T>
</th>
<th class="text-nowrap">
<Icon v="neuter" />
<span class="d-none d-md-inline"><T>nouns.neuter</T></span>
<span class="d-md-none"><T>nouns.neuterShort</T></span>
<T>nouns.neuter</T>
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(template, i) in templates" :key="i">
</template>
<template #row="{ el: template }">
<td>
<Noun :noun="template" gender="masc" />
</td>
@ -36,23 +30,37 @@
<slot name="buttons" :template="template"></slot>
</ul>
</th>
</tr>
</tbody>
</table>
</template>
<template #empty>
<Icon v="search" />
<T>nouns.empty</T>
</template>
</Table>
</template>
<script lang="ts">
import Vue from 'vue';
import type { MinimalNoun } from '../src/classes.ts';
import { gendersWithNumerus } from '../src/classes.ts';
import { nounTemplates } from '../src/data.ts';
export default Vue.extend({
props: {
templateBase: { default: '', type: String },
filter: { default: '', type: String },
},
computed: {
templates(): MinimalNoun[] {
return nounTemplates.map((template) => {
return nounTemplates.filter((template) => {
for (const field of gendersWithNumerus) {
for (const value of template[field]) {
if (value.toLowerCase().includes(this.filter)) {
return true;
}
}
}
}).map((template) => {
return template.fill(this.templateBase || '-');
});
},

View File

@ -389,6 +389,11 @@ interface NounTemplatesConfig {
* route path for noun templates (translated)
*/
route?: string;
/**
* whether a filter is shown for templates, useful when the language has several templates
* @default false
*/
filter?: boolean;
}
interface CommunityConfig {

View File

@ -226,6 +226,7 @@ nouns:
submit: true
templates:
enabled: true
filter: true
subroutes:
- 'neutratywy'
- 'dukatywy'

View File

@ -105,6 +105,7 @@ nouns:
templates:
enabled: true
route: 'endings'
filter: true
community:
route: 'terminology'

View File

@ -15,7 +15,19 @@
<AdPlaceholder :phkey="['content-0', 'content-mobile-0']" />
<NounTemplatesTable />
<section v-if="$config.nouns.templates?.filter" class="sticky-top">
<div class="input-group mb-3 bg-white">
<span class="input-group-text">
<Icon v="filter" />
</span>
<input ref="filter" v-model="filter" class="form-control border-primary" :placeholder="$t('crud.filterLong')">
<button v-if="filter" class="btn btn-outline-danger" @click="filter = ''; $tRefs.filter?.focus()">
<Icon v="times" />
</button>
</div>
</section>
<NounTemplatesTable :filter="filter" />
</Page>
</template>
@ -23,12 +35,26 @@
import Vue from 'vue';
import { head } from '../src/helpers.ts';
interface Refs {
filter: HTMLInputElement | undefined;
}
export default Vue.extend({
data() {
return {
filter: '',
};
},
head() {
return head({
title: this.$t('nouns.headerLonger'),
description: this.$t('nouns.description'),
}, this.$translator);
},
computed: {
$tRefs(): Refs {
return this.$refs as unknown as Refs;
},
},
});
</script>