#61 [english] wip

This commit is contained in:
Avris 2020-10-31 12:29:34 +01:00
parent b385c67901
commit d20c24db25
5 changed files with 559 additions and 298 deletions

310
components/Dictionary.vue Normal file
View File

@ -0,0 +1,310 @@
<template>
<Loading :value="nounsRaw">
<section v-if="$admin()" class="px-3">
<div class="alert alert-info">
<strong>{{ nounsCountApproved() }}</strong> <T>nouns.approved</T>,
<strong>{{ nounsCountPending() }}</strong> <T>nouns.pending</T>.
</div>
</section>
<section class="sticky-top">
<div class="input-group mb-3 bg-white">
<div class="input-group-prepend">
<span class="input-group-text">
<Icon v="filter"/>
</span>
</div>
<input class="form-control border-primary" v-model="filter" :placeholder="$t('crud.filterLong')" ref="filter"/>
<div class="input-group-append" v-if="filter">
<button class="btn btn-outline-danger" @click="filter = ''; $refs.filter.focus()">
<Icon v="times"/>
</button>
</div>
<div class="input-group-append">
<button class="btn btn-outline-success" @click="$refs.form.$el.scrollIntoView()">
<Icon v="plus-circle"/>
<T>nouns.submit.action</T>
</button>
</div>
</div>
</section>
<Table :data="visibleNouns()" :columns="$admin() ? 4 : 3" :marked="(el) => !el.approved" fixed ref="dictionarytable">
<template v-slot:header>
<th class="text-nowrap">
<Icon v="mars"/>
<T>nouns.masculine</T>
</th>
<th class="text-nowrap">
<Icon v="venus"/>
<T>nouns.feminine</T>
</th>
<th class="text-nowrap">
<Icon v="neuter"/>
<T>nouns.neuter</T>
</th>
<th v-if="$admin()"></th>
</template>
<template v-slot:row="s"><template v-if="s">
<td>
<ul class="list-singular">
<li v-for="w in s.el.masc">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in s.el.mascPl">{{ w }}</li>
</ul>
<small v-if="s.el.base && nouns[s.el.base]">
<p><strong><T>nouns.edited</T>:</strong></p>
<ul class="list-singular">
<li v-for="w in nouns[s.el.base].masc">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in nouns[s.el.base].mascPl">{{ w }}</li>
</ul>
</small>
<button v-if="!$admin()" class="btn btn-outline-primary btn-sm m-1 hover-show" @click="edit(s.el)">
<Icon v="pen"/>
<T>nouns.edit</T>
</button>
</td>
<td>
<ul class="list-singular">
<li v-for="w in s.el.fem">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in s.el.femPl">{{ w }}</li>
</ul>
<small v-if="s.el.base && nouns[s.el.base]">
<p><strong><T>nouns.edited</T>:</strong></p>
<ul class="list-singular">
<li v-for="w in nouns[s.el.base].fem">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in nouns[s.el.base].femPl">{{ w }}</li>
</ul>
</small>
</td>
<td>
<ul class="list-singular">
<li v-for="w in s.el.neutr">
<Declension :word="w"/>
</li>
</ul>
<ul class="list-plural">
<li v-for="w in s.el.neutrPl">
<Declension :word="w" plural :singularOptions="s.el.neutr"/>
</li>
</ul>
<small v-if="s.el.base && nouns[s.el.base]">
<p><strong><T>nouns.edited</T>:</strong></p>
<ul class="list-singular">
<li v-for="w in nouns[s.el.base].neutr">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in nouns[s.el.base].neutrPl">{{ w }}</li>
</ul>
</small>
</td>
<td v-if="$admin()">
<ul class="list-unstyled">
<li v-if="!s.el.approved">
<button class="btn btn-success btn-sm m-1" @click="approve(s.el)">
<Icon v="check"/>
<T>crud.approve</T>
</button>
</li>
<li v-else @click="hide(s.el)">
<button class="btn btn-outline-secondary btn-sm m-1">
<Icon v="times"/>
<T>crud.hide</T>
</button>
</li>
<li>
<button class="btn btn-outline-danger btn-sm m-1" @click="remove(s.el)">
<Icon v="trash"/>
<T>crud.remove</T>
</button>
</li>
<li>
<button class="btn btn-outline-primary btn-sm m-1" @click="edit(s.el)">
<Icon v="pen"/>
<T>crud.edit</T>
</button>
</li>
</ul>
</td>
</template></template>
<template v-slot:empty>
<Icon v="search"/>
<T>nouns.empty</T>
</template>
</Table>
<Separator icon="plus"/>
<div class="px-3">
<NounSubmitForm ref="form"/>
</div>
</Loading>
</template>
<script>
import { Noun } from "~/src/classes";
import { buildDict } from "../src/helpers";
export default {
props: {
load: {type: Boolean}
},
data() {
return {
filter: '',
nounsRaw: undefined,
}
},
mounted() {
if (this.load) {
this.loadNouns();
}
},
methods: {
async loadNouns() {
if (this.nounsRaw !== undefined) {
return;
}
this.nounsRaw = await this.$axios.$get(`/nouns/all`, { headers: this.$auth() });
},
async setFilter(filter) {
this.filter = filter;
await this.loadNouns();
this.focus();
},
focus() {
this.$el.focus();
this.$el.scrollIntoView();
setTimeout(_ => {
this.$el.scrollIntoView();
}, 1000);
},
edit(noun) {
this.$refs.form.edit(noun);
},
async approve(noun) {
await this.$axios.$post(`/nouns/approve/${noun.id}`, {}, { headers: this.$auth() });
if (noun.base) {
delete this.nouns[noun.base];
}
noun.approved = true;
noun.base = null;
this.$forceUpdate();
},
async hide(noun) {
await this.$axios.$post(`/nouns/hide/${noun.id}`, {}, { headers: this.$auth() });
noun.approved = false;
this.$forceUpdate();
},
async remove(noun) {
if (!confirm('Czy na pewno usunąć ten wpis?')) {
return false;
}
await this.$axios.$post(`/nouns/remove/${noun.id}`, {}, { headers: this.$auth() });
delete this.nouns[noun.id];
this.$forceUpdate();
},
// those must be methods, not computed, because when modified, they don't get updated in the view for some reason
visibleNouns() {
return Object.values(this.nouns).filter(n => n.matches(this.filter));
},
nounsCountApproved() {
return Object.values(this.nouns).filter(n => n.approved).length;
},
nounsCountPending() {
return Object.values(this.nouns).filter(n => !n.approved).length;
},
},
computed: {
nouns() {
if (this.nounsRaw === undefined) {
return {};
}
return buildDict(function* (that) {
const sorted = that.nounsRaw.sort((a, b) => {
if (a.approved && !b.approved) {
return 1;
}
if (!a.approved && b.approved) {
return -1;
}
return a.masc.toLowerCase().localeCompare(b.masc.toLowerCase());
});
for (let w of sorted) {
yield [w.id, new Noun(w)];
}
}, this);
},
},
watch: {
filter() {
if (process.client) {
if (this.filter) {
window.location.hash = this.filter;
} else {
history.pushState('', document.title, window.location.pathname + window.location.search);
}
if (this.$refs.dictionarytable) {
this.$refs.dictionarytable.reset();
this.$refs.dictionarytable.focus();
}
}
}
},
}
</script>
<style lang="scss">
@import "assets/style";
.list-singular {
padding-left: 0;
list-style: none;
li {
white-space: nowrap;
}
>li:before {
content: "⋅";
display: inline-block;
width: $fa-fw-width;
text-align: center;
}
}
.list-plural {
padding-left: 0;
list-style: none;
li {
white-space: nowrap;
}
>li:before {
content: "⁖";
display: inline-block;
width: $fa-fw-width;
text-align: center;
}
}
tr {
.hover-show {
opacity: 0;
}
&:hover .hover-show {
opacity: 1;
}
}
</style>

View File

@ -13,7 +13,9 @@ sources:
route: 'sources'
nouns:
enabled: false
enabled: true
route: 'nouns'
collapsable: false
names:
enabled: false
@ -25,7 +27,7 @@ english:
enabled: false
faq:
enabled: false
enabled: true
route: 'faq'
links:
@ -74,8 +76,8 @@ contact:
sources: '/sources'
-
name: 'Zuzanna Sybilla Grzybowska'
pronouns: 'he/she/they'
pronounsLink: '/he&she&they'
pronouns: 'they/she/he'
pronounsLink: '/they&she&he'
twitter: 'mykofanes'
mail: 'zuzannagrzybowska@protonmail.com'
areas:

View File

@ -84,6 +84,46 @@ sources:
Poetry: 'Poetry'
Other: 'Other'
nouns:
header: 'Nouns'
headerLong: 'Dictionary of gender neutral language'
description: 'TODO'
intro:
- >
TODO
examples: 'Przykłady'
dictionary: 'Słownik Neutratywów'
approved: 'wpisów zatwierdzonych'
pending: 'oczekuje na moderację'
edit: 'Zaproponuj zmianę'
edited: 'Propozycja zmiany z'
editing: 'Edytujesz istniejący wpis'
empty: 'Nie znaleziono słów spełniających podane kryterium.'
submit:
action: 'Zgłoś'
actionLong: 'Zgłoś propozycję'
thanks: 'Dziękujemy za zgłoszenie!'
another: 'Zgłoś kolejne słowo'
moderation: 'Propozycje będą musiały zostać zatwierdzone przed opublikowaniem.'
template: 'Użyj szablonu'
root: 'Rdzeń rzeczownika'
masculine: 'maskulatyw'
masculineShort: 'mask.'
feminine: 'feminatyw'
feminineShort: 'fem.'
neuter: 'neutratyw'
neuterShort: 'neutr.'
singular: 'liczba pojedyncza'
singularShort: 'l. poj.'
plural: 'liczba mnoga'
pluralShort: 'l. mn.'
links:
header: 'Links'
headerLong: 'Extra links'
@ -92,6 +132,198 @@ links:
social: 'Social media'
faq:
header: 'FAQ'
headerLong: 'Frequently asked questions'
questions:
nonbinary:
question: 'What is nonbinary?'
answer:
- >
Płeć jest zdecydowanie bardziej skomplikowaną sprawą niż prosty podział kobieta/mężczyzna.
Nawet pod względem czysto biologicznym wyróżniamy płeć chromosomalną, genetyczną, hormonalną, fenotypową…
Nie zawsze jedna się z drugą zgadza, nie zawsze są one zero-jedynkowe
{https://twitter.com/RebeccaRHelm/status/1207834357639139328=(więcej info tutaj)}.
Natomiast pod względem kulturowym „płeć” jest konceptem społecznym.
W zależności od miejsca i czasu bycie „kobietą” i „mężczyzną” może oznaczać radykalnie różne
prawa, obowiązki, zasady… W Europie mężczyźni nosili buty na obcasie i rajtuzy,
rdzenni mieszkańcy Ameryki Północnej od wieków rozróżniają trzecią płeć
{https://gender.wikia.org/wiki/Two-Spirit=(two-spirit)}, itd. itd.
- >
Niebinarność to zbiorczy termin („umbrella term”) opisujący doświaczenie osób,
które nie wpisują się w binarny podział kobieta/mężczyzna.
Obejmuje na przykład osoby {https://gender.wikia.org/wiki/Agender=agender},
{https://gender.wikia.org/wiki/Gender_Fluid=gender fluid},
{https://gender.wikia.org/wiki/Demigirl=demidziewczęta},
{https://gender.wikia.org/wiki/Demiboy=demichłopców},
i {https://gender.wikia.org/wiki/Non-binary=wiele innych tożsamości}.
- >
Niebinarność to niekoniecznie coś „pomiędzy” męskością a kobiecością. Raczej „poza”.
Osoby niebinarne wcale nie muszą być androgyniczne, nie muszą używać neutralnych zaimków, itp.
Chodzi o to, by być wolnymi od ról płciowych, a nie tworzyć nowe.
czemu-respektowac:
question: 'Czemu mam respektować jakieś <em>dziwne</em> formy?'
answer:
- >
Bo zwracanie się do kogoś tak, jak sobie życzy, jest podstawą relacji społecznych.
Nie powiesz do Ani “Franku”, nie powiesz “na ty” do osoby, z którą jesteś “na pan”, itp.
A są osoby, które nie chcą, by im mówić „{/on=on}” ani „{/ona=ona}”.
Czy to uszanujesz, świadczy wyłącznie o Tobie.
- >
Wiele niepolskich imion też brzmi dla polskiego ucha „dziwnie”
ale zamiast wymyślać ludziom „lepsze” imiona,
po prostu dopytujemy, jak wymówić czy zapisać to, które naprawdę noszą, no nie?
- >
„Dziwne formy” to tylko kwestia przyzwyczajenia.
skad-wiedziec-jak-sie-zwracac:
question: 'Skąd mam wiedzieć, jak się do kogoś zwracać?'
answer:
- >
Można po prostu spytać! Tak, to może być trochę niezręczne, ale przestanie być, gdy zaczniemy to częściej robić.
Nie mamy przecież problemu pytać o imię albo o przejście na „ty”, więc czemu wzbraniamy się pytać o zaimki?
- >
(Tylko, prosimy, nie pytaj „jesteś chłopakiem czy dziewczyną?”. Takie pytanie implikuje, że są tylko dwie poprawne opcje,
i sugeruje niezdrową ciekawość genitaliami danej osoby. Wystarczy spytać po prostu „jak mam się do ciebie zwracać?”)
- >
Warto też normalizować samodzielne podawanie zaimków poprzez przedstawianie się nie tylko imieniem, lecz również zaimkami.
„Hej, jestem Michał, {/on=on/jego}”. To nic trudnego a dla osób trans i niebinarnych znaczy bardzo wiele.
Jeszcze łatwiej zrobić to online: po prostu wrzucić zaimki (lub link do przykładów z naszej strony) do bio.
- >
Język polski, choć przeważnie bardzo problematyczny dla osób niebinarnych, tutaj paradoksalnie ułatwia nam sprawę.
W przeciwieństwie do np. angielskiego, gdzie zgenderyzowanych zaimków używa się mówiąc <em>o kimś</em>,
język polski wymaga określenia się przy mówieniu <em>o sobie</em> lub <em>do kogoś</em>.
Jeśli więc ktoś mówi „zrobiłom”, wiesz i bez pytania, by mówić do niego „zrobiłoś”.
- >
Pamiętaj też, że wiele osób może używać innych zaimków i innego imienia w zależności od sytuacji.
Może na przykład nie być wyoutowana przed rodziną czy współpracownikami,
ale wśród przyjaciół czuć się komfortowo używając nieortodoksyjnych form.
Bądź uważnx, obserwuj, spytaj „jak się mam do ciebie zwracać przy szefie?”, itp.
- >
Niektórzy podają wiele zestawów zaimków, na przykład „{/on&ona=on/ona}” czy „{/onu&on=onu/on}”.
Oznacza to, że pasują im wszystkie te formy. Najczęściej są one podawane w kolejności od najbardziej lubianej.
kto-uzywa:
question: 'Czy ktoś tego w ogóle używa?'
answer:
- >
Tak! Niemal wszystkie formy, które {/=tu prezentujemy},
zostały nam podesłane przez osoby rzeczywiście ich używające,
albo wzięte z tekstów literatury.
Ewentualnie {/ona/ich=uzupełniłośmy} je jedynie w miejscach, gdzie którejś części brakowało,
próbując zachować spójność całości na przykład wymyślając formę grzecznościową „szanowne pań”
dla {/ono=formy nijakiej} albo zaimek {/ony=„ony”} dla liczby mnogiej dukaizmów, którego u Dukaja brakowało.
- >
Dwie formy liczby mnogiej {/ona/ich=stowrzyłośmy} same,
próbując zaradzić brakowi takowych i by móc jakoś pisać o sobie jako grupie,
bez zdawania się na zgenderyzowane rodzaje: męsko- i niemęskoosobowy.
najlepsza-forma:
question: 'Ale dużo tego… Po co to całe mnożenie form? Która jest <em>najlepsza</em>?'
answer:
- >
Celem projektu nie jest {https://pl.wikipedia.org/wiki/Preskryptywizm_(j%C4%99zykoznawstwo)=preskryptywizm}.
Nie chcemy narzucać żadnej formy, ani twierdzić, że któraś jest lepsza od innych.
- >
Preferujemy podejście {https://pl.wikipedia.org/wiki/Deskryptywizm_(j%C4%99zykoznawstwo)=deskryptywistyczne}
opisujemy jedynie istniejące już w żywej polszczyźnie (jakkolwiek niszowo) formy,
próbujemy je ustrukturyzować, opisać, uzupełnić, zebrać w jedno miejsce przykłady użycia…
- >
Oferujemy przegląd możliwości, ale każdx może samx wybrać, jakie formy najlepiej jex reprezentują.
- >
Rozwój języka jest najczęściej procesem długotrwałym, nie zdarza się z dnia na dzień.
Póki co, wszystkie propozycje form kotłują się w kotle codziennego użycia
zapewne kiedyś coś się z niego wyklaruje.
- >
Ze względu na barwną fleksyjność języka polskiego
i silny poziom zgeneryzowania gramatyki i słownictwa
nie jest łatwo „narzucić” konkrente formy, nawet gdybyśmy chciały.
Zanim wytworzą się uniwersalne, niebinarne rozwiązania - musimy sobie jakoś z tym poradzić.
autorytet:
question: 'Czy potwierdza te wymysły czyjś autorytet?'
answer:
- >
I tak, i nie... Większość prezentowanych tutaj form
nie należy do {https://pl.wikipedia.org/wiki/Norma_językowa=normy językowej},
lecz do {https://pl.wikipedia.org/wiki/Uzus_językowy=uzusu językowego}
czyli rzeczywistego stanu funkcjonowania polszczyzny w danej wspólnocie językowej,
niezależnie od tego, co językoznawcy zdążyli już (o ile w ogóle zamierzają)
umieścić w gramatykach i słownikach.
A i samą normę możemy podzielić na wzorcową i użytkowa
bo poprawność językowa nie jest zero-jedynkowa, ma różne odcienie.
- >
Tak jak {https://pl.wikipedia.org/wiki/Neologizm=neologizmy} same w sobie nie są błędami językowymi,
nawet jeśli jeszcze nie pojawiły się w słownikach,
albo jak nie jest wymagana zgoda Rady Języka Polskiego,
by używać emojis czy akronimów kultury internetowej,
tak samo i nienormatywne zaimki nie są niczym z natury złym.
- >
Rozumiemy jednak potrzebę znalezienia jakiejś oficjalnej legitymizacji
dla używania „kontrowersyjnych” form językowych.
Dlatego w sekcji [bookmark]{/linki=Dodatkowe materiały}
linkujemy między innymi do opinii RJP,
która potwierdza poprawność gramatyczną pierwszo- i drugoosobowych nijakich czasowników („byłom”, „zrobiłoś”),
do seminariów naukowych i prac akademickich na temat niebinarności w języku, etc.
Jesteśmy też w kontakcie ze studentem slawistyki piszącym o tym pracę dyplomową
oraz lektorką polonistyki planującą wydać podręcznik obejmujący nowe formy.
Mamy nadzieję, że będziemy mogły tu ich prace opublikować, gdy zostaną ukończone.
bio:
question: 'Czemu warto wrzucić link do swoich zaimków na swoje profile na portalach społecznościowych?'
answer:
- >
Jeśli jesteś cis i używasz „{/on=on}” lub „{/ona=ona}”, możesz myśleć, że Twoje zaimki są <em>oczywiste</em>.
I być może tak jest o ile wymieniasz w profilu swoje (nacechowane płciowo) imię albo w awatarze masz swoje zdjęcie.
Wielu jednak tego nie robi i ciężko zgadnąć, jak się do nich zwrócić.
- >
Przede wszystkim chodzi jednak o co innego: nie każdy używa zaimków, które są dla innych „oczywiste”.
Osoby trans chcą, by zwracano się do nich poprawnie, niezależnie czy są „passing”,
niezależnie czy przeszły już tranzycję (o ile w ogóle chcą ją przechodzić).
Osoby niebinarne często nie wyglądają „niebinarnie”,
a silnie zgenderyzowana polszczyzna nie oferuje domyślnego neutralnego zaimka.
- >
I choć jest to dla nas niezmiernie ważne, by zwracano się do nas poprawnie,
publikowanie swoich zaimków niesie też ze sobą spore ryzyko i mocno nas eksponuje.
- >
Jeśli umieszczasz swoje zaimki w profilu, choć samx nie masz takiej potrzeby,
to pokazujesz wsparcie dla społeczności trans
i normalizujesz podawanie zaimków przez osoby, których zaimki nie są oczywiste
{https://avris.it/blog/czemu-każdy-powinien-mieć-zaimki-w-bio=(więcej powodów tutaj).}
zmiana:
question: 'Czy mogę zmienić swoje zaimki?'
answer:
- >
Jak najbardziej! Nikogo nie dziwi, gdy ktoś zmienia w ciągu życia poglądy, styl, zainteresowania…
Czemu miało by być dziwne, że ktoś odkrył część swojej tożsamości, że przestało mu się podobać jego imię,
że odkrył etykietkę, która świetnie opisuje to, jak od dawna się czuł, itp. itd.?
wlasne:
question: 'Czy to dziwne, że nie mogę się przyzwyczaić do <em>swoich własnych</em> zaimków?'
answer:
- >
Ani trochę! Znamy wiele osób, które po latach używania form zgodnych z ich płcią nadaną przy urodzeniu,
zapominają się, gdy używają nowych form. Siła przyzwyczajenia jest silna, zwłaszcza dla osób,
które nie doświadczają mocnej {https://gender.wikia.org/wiki/Dysphoria=dysforii płciowej}.
- >
Zaimki ≠ płeć.
Płeć nie zmieni ci się nagle, jeśli czasem powiesz „zrobiłem”, gdy chciałuś powiedzieć „zrobiłum”.
Nie przejmuj się. Eksperymentuj. Sprawdź, z czym czujesz się najlepiej.
preferowane-zaimki:
question: 'Czemu nie mówić „preferowane zaimki”?'
answer:
- >
Bo to sugeruje, że czyjeś zaimki to tylko fanaberia.
Jeśli ktoś tylko „preferuje” żeńskie zaimki, to nie obrazi się, jak będę mówić do niego formami męskimi, prawda?
W końcu wygląda jak facet, a mi tak będzie łatwiej!
- >
Nie. To są nasze zaimki. Nie żadne „preferowane zaimki”. To nasze imiona, nie „preferowane imiona”.
Jeśli zależy ci na twoich transpłciowych i niebinarnych znajomych i krewnych, zwracaj się do nich poprawnie.
zaimki-plciowe:
question: 'Czemu nie mówić „zaimki płciowe”?'
answer:
- >
Bo zaimki ≠ płeć. Zaimki to tylko gramatyka.
Osoby niebinarne mogą używać (i w sporej części używają) form binarnych,
niektóre lesbijki ze względów kulturowych i historycznych używają form męskich, itp.
- >
Mów po prostu „zaimki”. To prościej i sensowniej.
contact:
header: 'Contact'
authors: 'Authors of the website'

View File

@ -15,6 +15,7 @@ sources:
nouns:
enabled: true
route: 'rzeczowniki'
collapsable: true
names:
enabled: false

View File

@ -12,189 +12,28 @@
</section>
<NounsExtra>
<details class="border mb-3" ref="dictionary">
<summary class="bg-light p-3" @click="loadNouns">
<details v-if="config.nouns.collapsable" class="border mb-3" ref="dictionarywrapper">
<summary class="bg-light p-3" @click="$refs.collapsabledictionary.loadNouns()">
<h4 class="h5 d-inline">
<Icon v="book"/>
<T>nouns.dictionary</T>
</h4>
</summary>
<div class="border-top">
<Loading :value="nounsRaw">
<section v-if="$admin()" class="px-3">
<div class="alert alert-info">
<strong>{{ nounsCountApproved() }}</strong> <T>nouns.approved</T>,
<strong>{{ nounsCountPending() }}</strong> <T>nouns.pending</T>.
</div>
</section>
<section class="sticky-top">
<div class="input-group mb-3 bg-white">
<div class="input-group-prepend">
<span class="input-group-text">
<Icon v="filter"/>
</span>
</div>
<input class="form-control border-primary" v-model="filter" :placeholder="$t('crud.filterLong')" ref="filter"/>
<div class="input-group-append" v-if="filter">
<button class="btn btn-outline-danger" @click="filter = ''; $refs.filter.focus()">
<Icon v="times"/>
</button>
</div>
<div class="input-group-append">
<button class="btn btn-outline-success" @click="$refs.form.$el.scrollIntoView()">
<Icon v="plus-circle"/>
<T>nouns.submit.action</T>
</button>
</div>
</div>
</section>
<Table :data="visibleNouns()" :columns="$admin() ? 4 : 3" :marked="(el) => !el.approved" fixed ref="dictionarytable">
<template v-slot:header>
<th class="text-nowrap">
<Icon v="mars"/>
<T>nouns.masculine</T>
</th>
<th class="text-nowrap">
<Icon v="venus"/>
<T>nouns.feminine</T>
</th>
<th class="text-nowrap">
<Icon v="neuter"/>
<T>nouns.neuter</T>
</th>
<th v-if="$admin()"></th>
</template>
<template v-slot:row="s">
<td>
<ul class="list-singular">
<li v-for="w in s.el.masc">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in s.el.mascPl">{{ w }}</li>
</ul>
<small v-if="s.el.base && nouns[s.el.base]">
<p><strong><T>nouns.edited</T>:</strong></p>
<ul class="list-singular">
<li v-for="w in nouns[s.el.base].masc">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in nouns[s.el.base].mascPl">{{ w }}</li>
</ul>
</small>
<button v-if="!$admin()" class="btn btn-outline-primary btn-sm m-1 hover-show" @click="edit(s.el)">
<Icon v="pen"/>
<T>nouns.edit</T>
</button>
</td>
<td>
<ul class="list-singular">
<li v-for="w in s.el.fem">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in s.el.femPl">{{ w }}</li>
</ul>
<small v-if="s.el.base && nouns[s.el.base]">
<p><strong><T>nouns.edited</T>:</strong></p>
<ul class="list-singular">
<li v-for="w in nouns[s.el.base].fem">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in nouns[s.el.base].femPl">{{ w }}</li>
</ul>
</small>
</td>
<td>
<ul class="list-singular">
<li v-for="w in s.el.neutr">
<Declension :word="w"/>
</li>
</ul>
<ul class="list-plural">
<li v-for="w in s.el.neutrPl">
<Declension :word="w" plural :singularOptions="s.el.neutr"/>
</li>
</ul>
<small v-if="s.el.base && nouns[s.el.base]">
<p><strong><T>nouns.edited</T>:</strong></p>
<ul class="list-singular">
<li v-for="w in nouns[s.el.base].neutr">{{ w }}</li>
</ul>
<ul class="list-plural">
<li v-for="w in nouns[s.el.base].neutrPl">{{ w }}</li>
</ul>
</small>
</td>
<td v-if="$admin()">
<ul class="list-unstyled">
<li v-if="!s.el.approved">
<button class="btn btn-success btn-sm m-1" @click="approve(s.el)">
<Icon v="check"/>
<T>crud.approve</T>
</button>
</li>
<li v-else @click="hide(s.el)">
<button class="btn btn-outline-secondary btn-sm m-1">
<Icon v="times"/>
<T>crud.hide</T>
</button>
</li>
<li>
<button class="btn btn-outline-danger btn-sm m-1" @click="remove(s.el)">
<Icon v="trash"/>
<T>crud.remove</T>
</button>
</li>
<li>
<button class="btn btn-outline-primary btn-sm m-1" @click="edit(s.el)">
<Icon v="pen"/>
<T>crud.edit</T>
</button>
</li>
</ul>
</td>
</template>
<template v-slot:empty>
<Icon v="search"/>
<T>nouns.empty</T>
</template>
</Table>
<Separator icon="plus"/>
<div class="px-3">
<NounSubmitForm ref="form"/>
</div>
</Loading>
<Dictionary ref="collapsabledictionary"/>
</div>
</details>
<Dictionary v-else load ref="dictionary"/>
</NounsExtra>
</div>
</template>
<script>
import { Noun } from "~/src/classes";
import { buildDict } from "../src/helpers";
import { head } from "../src/helpers";
import NounsExtra from "../data/nouns/NounsExtra.vue";
const PER_PAGE = 30;
export default {
components: { NounsExtra },
data() {
return {
filter: '',
nounsRaw: undefined,
}
},
mounted() {
if (process.client) {
if (window.location.hash) {
@ -204,100 +43,17 @@
if ($anchor) {
$anchor.scrollIntoView();
} else {
this.filter = anchor;
this.loadNouns();
this.$refs.dictionary.open = true;
this.$refs.dictionary.focus();
this.$refs.dictionary.scrollIntoView();
setTimeout(_ => {
this.$refs.dictionary.scrollIntoView();
}, 1000);
if (this.$refs.dictionarywrapper) {
this.$refs.dictionarywrapper.open = true;
this.$refs.collapsabledictionary.setFilter(anchor);
} else {
this.$refs.dictionary.setFilter(anchor);
}
}
})
}
}
},
methods: {
async loadNouns() {
if (this.nounsRaw !== undefined) {
return;
}
this.nounsRaw = await this.$axios.$get(`/nouns/all`, { headers: this.$auth() });
},
edit(noun) {
this.$refs.form.edit(noun);
},
async approve(noun) {
await this.$axios.$post(`/nouns/approve/${noun.id}`, {}, { headers: this.$auth() });
if (noun.base) {
delete this.nouns[noun.base];
}
noun.approved = true;
noun.base = null;
this.$forceUpdate();
},
async hide(noun) {
await this.$axios.$post(`/nouns/hide/${noun.id}`, {}, { headers: this.$auth() });
noun.approved = false;
this.$forceUpdate();
},
async remove(noun) {
if (!confirm('Czy na pewno usunąć ten wpis?')) {
return false;
}
await this.$axios.$post(`/nouns/remove/${noun.id}`, {}, { headers: this.$auth() });
delete this.nouns[noun.id];
this.$forceUpdate();
},
// those must be methods, not computed, because when modified, they don't get updated in the view for some reason
visibleNouns() {
return Object.values(this.nouns).filter(n => n.matches(this.filter));
},
nounsCountApproved() {
return Object.values(this.nouns).filter(n => n.approved).length;
},
nounsCountPending() {
return Object.values(this.nouns).filter(n => !n.approved).length;
},
},
computed: {
nouns() {
if (this.nounsRaw === undefined) {
return {};
}
return buildDict(function* (that) {
const sorted = that.nounsRaw.sort((a, b) => {
if (a.approved && !b.approved) {
return 1;
}
if (!a.approved && b.approved) {
return -1;
}
return a.masc.toLowerCase().localeCompare(b.masc.toLowerCase());
});
for (let w of sorted) {
yield [w.id, new Noun(w)];
}
}, this);
},
},
watch: {
filter() {
if (process.client) {
if (this.filter) {
window.location.hash = this.filter;
} else {
history.pushState('', document.title, window.location.pathname + window.location.search);
}
if (this.$refs.dictionarytable) {
this.$refs.dictionarytable.reset();
this.$refs.dictionarytable.focus();
}
}
}
},
head() {
return head({
title: this.$t('nouns.headerLong'),
@ -307,43 +63,3 @@
},
}
</script>
<style lang="scss">
@import "assets/style";
.list-singular {
padding-left: 0;
list-style: none;
li {
white-space: nowrap;
}
>li:before {
content: "⋅";
display: inline-block;
width: $fa-fw-width;
text-align: center;
}
}
.list-plural {
padding-left: 0;
list-style: none;
li {
white-space: nowrap;
}
>li:before {
content: "⁖";
display: inline-block;
width: $fa-fw-width;
text-align: center;
}
}
tr {
.hover-show {
opacity: 0;
}
&:hover .hover-show {
opacity: 1;
}
}
</style>