#194 custom flags

This commit is contained in:
Avris 2021-04-05 17:03:13 +02:00
parent 2d0eb3ac9c
commit 34bda3fcda
17 changed files with 205 additions and 37 deletions

View File

@ -2,14 +2,18 @@
<span class="flag-wrapper"> <span class="flag-wrapper">
<a v-if="link" :href="`/${config.nouns.route}/${config.nouns.terms.route}#${link.toLowerCase()}`" :title="alt"> <a v-if="link" :href="`/${config.nouns.route}/${config.nouns.terms.route}#${link.toLowerCase()}`" :title="alt">
<img :src="img" alt="" class="flag-mini rounded"/> <img :src="img" alt="" class="flag-mini rounded"/>
<Spelling :text="name"/> <Spelling :text="name"/><sup v-if="custom" class="text-muted"><small><Icon v="user"/></small></sup>
</a> </a>
<span v-else :title="alt"> <span v-else :title="alt">
<img :src="img" alt="" class="flag-mini rounded"/> <img :src="img" alt="" class="flag-mini rounded"/>
<Spelling :text="name"/> <Spelling :text="name"/><sup v-if="custom" class="text-muted"><small><Icon v="user"/></small></sup>
</span> </span>
<span class="flag-preview bg-white rouded p-2 border"> <span class="flag-preview bg-white rouded p-2 border">
<img :src="img" alt="" class="rounded"/> <img :src="img" alt="" class="rounded"/>
<span v-if="custom" class="alert alert-warning small d-inline-block mt-2 mb-0 p-2">
<Icon v="user"/>
<T>profile.flagsCustomWarning</T>
</span>
</span> </span>
</span> </span>
</template> </template>
@ -21,6 +25,7 @@
alt: { required: true }, alt: { required: true },
img: { required: true }, img: { required: true },
terms: { }, terms: { },
custom: { type: Boolean },
}, },
computed: { computed: {
link() { link() {
@ -57,6 +62,9 @@
left: 0; left: 0;
z-index: 999; z-index: 999;
display: none; display: none;
img {
max-height: 128px;
}
} }
&:hover { &:hover {

View File

@ -1,8 +1,8 @@
<template> <template>
<a :href="buildImageUrl(id, 'big')" target="_blank" rel="noopener" class="d-inline-block" <a :href="buildImageUrl(id, bigSize)" target="_blank" rel="noopener" class="d-inline-block"
@click.prevent="$eventHub.$emit('lightbox', buildImageUrl(id, 'big'))" @click.prevent="$eventHub.$emit('lightbox', buildImageUrl(id, bigSize))"
> >
<img :src="buildImageUrl(id, 'thumb')" class="border rounded-lg"/> <img :src="buildImageUrl(id, smallSize)" class="border rounded-lg" :style="`height: ${size}; width: auto;`"/>
</a> </a>
</template> </template>
@ -10,11 +10,9 @@
export default { export default {
props: { props: {
id: {required: true}, id: {required: true},
}, smallSize: {'default': 'thumb'},
methods: { bigSize: {'default': 'big'},
getUrl(size) { size: {'default': 'auto'}
return `${process.env.BUCKET}/images/${this.id}-${size}.png`;
},
}, },
} }
</script> </script>

View File

@ -0,0 +1,82 @@
<template>
<div class="form-group">
<draggable tag="ul" v-model="images" handle=".handle" ghostClass="ghost" @end="$emit('input', images)" class="list-unstyled">
<li v-for="(image, i) in images" class="mb-4">
<div class="input-group mb-1">
<button class="btn btn-light border handle" type="button" :aria-label="$t('table.sort')">
<Icon v="bars"/>
</button>
<ImageThumb :id="image.id" smallSize="flag" bigSize="flag" size="2.4em"/>
<input v-model="images[i].desc" type="text" class="form-control"
@keyup="update" @change="update"
required :maxlength="maxLength"/>
<button class="btn btn-outline-danger" type="button" @click.prevent="removeFile(image.id)" :aria-label="$t('crud.remove')">
<Icon v="times"/>
</button>
</div>
</li>
<li slot="footer">
<ImageUploader multiple :name="name" form @uploaded="addFiles"/>
</li>
</draggable>
</div>
</template>
<script>
import draggable from 'vuedraggable'
import { curry } from "../src/helpers";
export default {
components: {
draggable,
},
props: {
value: {type: Object},
name: {'default': 'images'},
maxLength: {'default': 24},
},
data() {
return {
images: this.dictToList(this.value),
curry,
}
},
watch: {
value() {
this.images = this.dictToList(this.value);
}
},
methods: {
addFiles(files) {
this.$emit('input', this.listToDict([...this.images, ...files]));
},
async removeFile(id) {
await this.$confirm(this.$t('crud.removeConfirm'), 'danger');
this.$emit('input', this.listToDict(this.images.filter(i => i.id !== id)));
},
update() {
this.$emit('input', this.listToDict(this.images));
},
dictToList(dict) {
const images = [];
for (let id in dict) {
if (dict.hasOwnProperty(id)) {
images.push({id, desc: dict[id]});
}
}
return images;
},
listToDict(list) {
const images = {};
for (let image of list) {
if (typeof(image) === 'string') {
image = {id: image, desc: ''};
}
images[image.id] = image.desc;
}
return images;
},
},
}
</script>

View File

@ -384,6 +384,8 @@ profile:
birthdayInfo: 'Wir veröffentlichen nicht dein Geburtstag, sondern nur das errechnete Alter.' birthdayInfo: 'Wir veröffentlichen nicht dein Geburtstag, sondern nur das errechnete Alter.'
flags: 'Flaggen' flags: 'Flaggen'
flagsInfo: 'Ziehe deine Pride Flaggen per drag & drop in diesen Rahmen.' flagsInfo: 'Ziehe deine Pride Flaggen per drag & drop in diesen Rahmen.'
flagsCustom: 'Upload custom flags' # TODO
flagsCustomWarning: 'This flag has been uploaded by a user. The team of pronouns.page is not responsible for it.' # TODO
links: 'Links' links: 'Links'
column: 'Spalte' column: 'Spalte'
@ -402,6 +404,14 @@ profile:
meh: 'Okay' meh: 'Okay'
no: 'Nope' no: 'Nope'
# TODO
# banner: >
# You can also use our website to create a card, {/@andrea=like this one},
# containing your names, pronouns, pride flags, liked words, etc.
# Then you can link to it in your bio or email footer.
# Just create an account {/account=here}.
# bannerButton: 'Create a card'
share: 'Teilen' share: 'Teilen'
crud: crud:

View File

@ -293,17 +293,6 @@ faq:
Nonbinary folks can use binary pronouns, some lesbians use {/he=he/him} for cultural reasons, etc. Nonbinary folks can use binary pronouns, some lesbians use {/he=he/him} for cultural reasons, etc.
- > - >
Simply say “pronouns”. Simply say “pronouns”.
add-flags:
question: 'My flag is not in the editor. Can you add it?'
answer:
- >
To avoid potential vandalisms (flags of attack helicopters, MAPs, TERFs, etc.)
we've decided not to allow uploading your own pictures to the flags editor.
But we do offer a choice from a pretty long list of more popular flags
unfortunately that requires us to make a subjective choice.
- >
You can try using the closest matching flag you identify with instead.
And in the “description” field you can just write anything you want.
links: links:
header: 'Links' header: 'Links'
@ -397,6 +386,8 @@ profile:
birthdayInfo: 'We do not publish your birthday, just the calculated age.' birthdayInfo: 'We do not publish your birthday, just the calculated age.'
flags: 'Flags' flags: 'Flags'
flagsInfo: 'Drag & drop your pride flags into this frame.' flagsInfo: 'Drag & drop your pride flags into this frame.'
flagsCustom: 'Upload custom flags'
flagsCustomWarning: 'This flag has been uploaded by a user. The team of pronouns.page is not responsible for it.'
links: 'Links' links: 'Links'
column: 'Column' column: 'Column'

View File

@ -393,6 +393,8 @@ profile:
birthdayInfo: 'No publicamos la fecha de tu cumpleaños, sólo la edad calculada.' birthdayInfo: 'No publicamos la fecha de tu cumpleaños, sólo la edad calculada.'
flags: 'Banderas' flags: 'Banderas'
flagsInfo: 'Arrastra tus banderas de orgullo a este marco.' flagsInfo: 'Arrastra tus banderas de orgullo a este marco.'
flagsCustom: 'Upload custom flags' # TODO
flagsCustomWarning: 'This flag has been uploaded by a user. The team of pronouns.page is not responsible for it.' # TODO
links: 'Enlaces' links: 'Enlaces'
column: 'Columna' column: 'Columna'
@ -411,6 +413,14 @@ profile:
meh: 'Okey' meh: 'Okey'
no: 'No' no: 'No'
# TODO
# banner: >
# You can also use our website to create a card, {/@andrea=like this one},
# containing your names, pronouns, pride flags, liked words, etc.
# Then you can link to it in your bio or email footer.
# Just create an account {/account=here}.
# bannerButton: 'Create a card'
share: 'Compartir' share: 'Compartir'
crud: crud:

View File

@ -386,6 +386,8 @@ profile:
birthdayInfo: 'We laten jouw verjaardagsdatum niet zien, alleen de berekende leeftijd.' birthdayInfo: 'We laten jouw verjaardagsdatum niet zien, alleen de berekende leeftijd.'
flags: 'Vlaggen' flags: 'Vlaggen'
flagsInfo: 'Klik en sleep jouw pridevlaggen naar deze frame.' flagsInfo: 'Klik en sleep jouw pridevlaggen naar deze frame.'
flagsCustom: 'Upload custom flags' # TODO
flagsCustomWarning: 'This flag has been uploaded by a user. The team of pronouns.page is not responsible for it.' # TODO
links: 'Links' links: 'Links'
column: 'Kolom' column: 'Kolom'
@ -404,6 +406,14 @@ profile:
meh: 'Oké' meh: 'Oké'
no: 'Nee' no: 'Nee'
# TODO
# banner: >
# You can also use our website to create a card, {/@andrea=like this one},
# containing your names, pronouns, pride flags, liked words, etc.
# Then you can link to it in your bio or email footer.
# Just create an account {/account=here}.
# bannerButton: 'Create a card'
share: 'Deel' share: 'Deel'
crud: crud:

View File

@ -767,19 +767,6 @@ faq:
niektóre lesbijki ze względów kulturowych i historycznych używają form męskich, itp. 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. Mów po prostu „zaimki”. To prościej i sensowniej.
moja-flaga:
question: 'Mojej flagi nie ma w edytorze wizytówki'
answer:
- >
Aby uniknąć potencjalnych wandalizmów
(flaga helikopterów szturmowych, MAPów, TERFów, itp.),
zdecydowałośmy się nie umożliwiać wgrywania własnych obrazków na stronę.
Oferujemy natomiast wybór spośród dość bogatej listy co popularniejszych flag
niestety siłą rzeczy musi być to wybór subiektywny.
- >
Możesz spróbować wybrać najbliższą pasującą flagę, z którą się identyfikujesz.
No i zawsze w polu „opis” możesz wpisać, co tylko ci się podoba.
a-moj-dziadek: a-moj-dziadek:
question: 'Czy po to mój dziadek walczył na wojnie, by teraz ktoś mówił o sobie „ono”?' question: 'Czy po to mój dziadek walczył na wojnie, by teraz ktoś mówił o sobie „ono”?'
answer: answer:
@ -942,6 +929,8 @@ profile:
flagsInfo: > flagsInfo: >
Przeciągnij swoje pride''owe flagi do poniższej ramki. Przeciągnij swoje pride''owe flagi do poniższej ramki.
Więcej informacji o etykietkach znajdziesz w naszym <a href="/slowniki/terminologia" target="_blank">Słowniku Terminologii Queerowej</a>. Więcej informacji o etykietkach znajdziesz w naszym <a href="/slowniki/terminologia" target="_blank">Słowniku Terminologii Queerowej</a>.
flagsCustom: 'Dodaj inne flagi'
flagsCustomWarning: 'Ta flaga została wgrana przez osobę użytkującą. Ekipa zaimki.pl nie jest za nią odpowiedzialna.'
links: 'Linki' links: 'Linki'
column: 'Kolumna' column: 'Kolumna'

View File

@ -390,6 +390,8 @@ profile:
birthdayInfo: 'Não publicamos a data do aniversário, somente a idade calculada.' birthdayInfo: 'Não publicamos a data do aniversário, somente a idade calculada.'
flags: 'Bandeiras' flags: 'Bandeiras'
flagsInfo: 'Arrasta as bandeiras de orgulho a esse marco.' flagsInfo: 'Arrasta as bandeiras de orgulho a esse marco.'
flagsCustom: 'Upload custom flags' # TODO
flagsCustomWarning: 'This flag has been uploaded by a user. The team of pronouns.page is not responsible for it.' # TODO
links: 'Enlaces' links: 'Enlaces'
column: 'Coluna' column: 'Coluna'
@ -408,6 +410,14 @@ profile:
meh: 'OK' meh: 'OK'
no: 'Não' no: 'Não'
# TODO
# banner: >
# You can also use our website to create a card, {/@andrea=like this one},
# containing your names, pronouns, pride flags, liked words, etc.
# Then you can link to it in your bio or email footer.
# Just create an account {/account=here}.
# bannerButton: 'Create a card'
share: 'Compartilhar' share: 'Compartilhar'
crud: crud:

View File

@ -925,6 +925,8 @@ profile:
birthdayInfo: 'Nie pokazujemy publicznie pełnej daty urodzenia, jedynie obliczony wiek.' birthdayInfo: 'Nie pokazujemy publicznie pełnej daty urodzenia, jedynie obliczony wiek.'
flags: 'Flagi' flags: 'Flagi'
flagsInfo: 'Przeciągnij swoje pride''owe flagi do poniższej ramki.' flagsInfo: 'Przeciągnij swoje pride''owe flagi do poniższej ramki.'
flagsCustom: 'Upload custom flags' # TODO
flagsCustomWarning: 'This flag has been uploaded by a user. The team of pronouns.page is not responsible for it.' # TODO
links: 'Linki' links: 'Linki'
column: 'Kolumna' column: 'Kolumna'
@ -943,6 +945,14 @@ profile:
meh: 'Spoko' meh: 'Spoko'
no: 'Nie' no: 'Nie'
# TODO
# banner: >
# You can also use our website to create a card, {/@andrea=like this one},
# containing your names, pronouns, pride flags, liked words, etc.
# Then you can link to it in your bio or email footer.
# Just create an account {/account=here}.
# bannerButton: 'Create a card'
census: census:
header: 'Spis' header: 'Spis'
headerLong: 'Niebinarny spis powszechny' headerLong: 'Niebinarny spis powszechny'

View File

@ -404,6 +404,8 @@ profile:
birthdayInfo: 'We do not publish your birthday, just the calculated age.' birthdayInfo: 'We do not publish your birthday, just the calculated age.'
flags: 'פֿענער' flags: 'פֿענער'
flagsInfo: 'Drag & drop your pride flags into this frame.' flagsInfo: 'Drag & drop your pride flags into this frame.'
flagsCustom: 'Upload custom flags' # TODO
flagsCustomWarning: 'This flag has been uploaded by a user. The team of pronouns.page is not responsible for it.' # TODO
links: 'פֿאַרבינדונגען' links: 'פֿאַרבינדונגען'
column: 'Column' column: 'Column'
@ -422,6 +424,14 @@ profile:
meh: 'אָקײ' meh: 'אָקײ'
no: 'נײן' no: 'נײן'
# TODO
# banner: >
# You can also use our website to create a card, {/@andrea=like this one},
# containing your names, pronouns, pride flags, liked words, etc.
# Then you can link to it in your bio or email footer.
# Just create an account {/account=here}.
# bannerButton: 'Create a card'
share: 'Share' share: 'Share'
crud: crud:

View File

@ -371,6 +371,8 @@ profile:
birthdayInfo: '我們不發布您的生日,只發布計算出的年齡。' birthdayInfo: '我們不發布您的生日,只發布計算出的年齡。'
flags: '旗幟' flags: '旗幟'
flagsInfo: '將您的驕傲旗幟拖放到此框架中.' flagsInfo: '將您的驕傲旗幟拖放到此框架中.'
flagsCustom: 'Upload custom flags' # TODO
flagsCustomWarning: 'This flag has been uploaded by a user. The team of pronouns.page is not responsible for it.' # TODO
links: '鏈接' links: '鏈接'
column: '列' column: '列'
@ -389,6 +391,14 @@ profile:
meh: 'OK' meh: 'OK'
no: '不好' no: '不好'
# TODO
# banner: >
# You can also use our website to create a card, {/@andrea=like this one},
# containing your names, pronouns, pride flags, liked words, etc.
# Then you can link to it in your bio or email footer.
# Just create an account {/account=here}.
# bannerButton: 'Create a card'
share: '這裡' share: '這裡'
crud: crud:

View File

@ -0,0 +1,5 @@
-- Up
ALTER TABLE profiles ADD COLUMN customFlags TEXT NOT NULL DEFAULT '{}';
-- Down

View File

@ -44,7 +44,17 @@
<section v-if="profile.flags.length"> <section v-if="profile.flags.length">
<ul class="list-inline"> <ul class="list-inline">
<li v-for="flag in profile.flags" v-if="allFlags[flag]" class="list-inline-item pr-2"> <li v-for="flag in profile.flags" v-if="allFlags[flag]" class="list-inline-item pr-2">
<Flag :name="flag.startsWith('-') ? allFlags[flag] : $translateForPronoun(allFlags[flag], mainPronoun)" :alt="allFlags[flag]" :img="`/flags/${flag}.png`" :terms="terms"/> <Flag :name="flag.startsWith('-') ? allFlags[flag] : $translateForPronoun(allFlags[flag], mainPronoun)"
:alt="allFlags[flag]"
:img="`/flags/${flag}.png`"
:terms="terms"/>
</li>
<li v-for="(desc, flag) in profile.customFlags" class="list-inline-item pr-2">
<Flag :name="desc"
:alt="desc"
:img="buildImageUrl(flag, 'flag')"
:terms="terms"
custom/>
</li> </li>
</ul> </ul>
</section> </section>

View File

@ -96,6 +96,15 @@
</ButtonList> </ButtonList>
</div> </div>
<details class="form-group border rounded" open>
<summary class="px-3 py-2 small">
<T>profile.flagsCustom</T>
</summary>
<div class="border-top">
<ImageWidgetRich v-model="customFlags"/>
</div>
</details>
<div class="form-group"> <div class="form-group">
<h3 class="h4"> <h3 class="h4">
<Icon v="link"/> <Icon v="link"/>
@ -178,6 +187,7 @@
birthday: profile.birthday, birthday: profile.birthday,
links: Object.keys(profile.links).length ? profile.links : [], links: Object.keys(profile.links).length ? profile.links : [],
flags: profile.flags, flags: profile.flags,
customFlags: profile.customFlags,
words: profile.words.map(x => dictToList(x)), words: profile.words.map(x => dictToList(x)),
teamName: profile.teamName, teamName: profile.teamName,
footerName: profile.footerName, footerName: profile.footerName,
@ -198,6 +208,7 @@
birthday: profile.birthday, birthday: profile.birthday,
links: Object.keys(profile.links).length ? profile.links : [], links: Object.keys(profile.links).length ? profile.links : [],
flags: profile.flags.filter(f => !f.startsWith('-')), flags: profile.flags.filter(f => !f.startsWith('-')),
customFlags: profile.customFlags,
words: defaultWords, words: defaultWords,
teamName: profile.teamName, teamName: profile.teamName,
footerName: profile.footerName, footerName: profile.footerName,
@ -212,6 +223,7 @@
birthday: null, birthday: null,
links: [], links: [],
flags: [], flags: [],
customFlags: {},
words: defaultWords, words: defaultWords,
teamName: '', teamName: '',
footerName: '', footerName: '',
@ -234,6 +246,7 @@
birthday: this.birthday, birthday: this.birthday,
links: [...this.links], links: [...this.links],
flags: [...this.flags], flags: [...this.flags],
customFlags: {...this.customFlags},
words: this.words.map(x => listToDict(x)), words: this.words.map(x => listToDict(x)),
teamName: this.teamName, teamName: this.teamName,
footerName: this.footerName, footerName: this.footerName,

View File

@ -8,6 +8,7 @@ import S3 from 'aws-sdk/clients/s3';
const sizes = { const sizes = {
big: [1600, false], big: [1600, false],
flag: [256, false],
thumb: [240, true], thumb: [240, true],
} }

View File

@ -44,6 +44,7 @@ const fetchProfiles = async (db, username, self) => {
age: calcAge(profile.birthday), age: calcAge(profile.birthday),
links: JSON.parse(profile.links), links: JSON.parse(profile.links),
flags: JSON.parse(profile.flags), flags: JSON.parse(profile.flags),
customFlags: JSON.parse(profile.customFlags),
words: JSON.parse(profile.words), words: JSON.parse(profile.words),
avatar: await avatar(db, profile), avatar: await avatar(db, profile),
birthday: self ? profile.birthday : undefined, birthday: self ? profile.birthday : undefined,
@ -67,9 +68,9 @@ router.post('/profile/save', async (req, res) => {
} }
await req.db.get(SQL`DELETE FROM profiles WHERE userId = ${req.user.id} AND locale = ${req.config.locale}`); await req.db.get(SQL`DELETE FROM profiles WHERE userId = ${req.user.id} AND locale = ${req.config.locale}`);
await req.db.get(SQL`INSERT INTO profiles (id, userId, locale, names, pronouns, description, birthday, links, flags, words, active, teamName, footerName, footerAreas) await req.db.get(SQL`INSERT INTO profiles (id, userId, locale, names, pronouns, description, birthday, links, flags, customFlags, words, active, teamName, footerName, footerAreas)
VALUES (${ulid()}, ${req.user.id}, ${req.config.locale}, ${JSON.stringify(req.body.names)}, ${JSON.stringify(req.body.pronouns)}, VALUES (${ulid()}, ${req.user.id}, ${req.config.locale}, ${JSON.stringify(req.body.names)}, ${JSON.stringify(req.body.pronouns)},
${req.body.description}, ${req.body.birthday || null}, ${JSON.stringify(req.body.links.filter(x => !!x))}, ${JSON.stringify(req.body.flags)}, ${req.body.description}, ${req.body.birthday || null}, ${JSON.stringify(req.body.links.filter(x => !!x))}, ${JSON.stringify(req.body.flags)}, ${JSON.stringify(req.body.customFlags)},
${JSON.stringify(req.body.words)}, 1, ${JSON.stringify(req.body.words)}, 1,
${req.isGranted('users') ? req.body.teamName || null : ''}, ${req.isGranted('users') ? req.body.teamName || null : ''},
${req.isGranted('users') ? req.body.footerName || null : ''}, ${req.isGranted('users') ? req.body.footerName || null : ''},