#50 user cards – flags
|
@ -0,0 +1,69 @@
|
|||
<template>
|
||||
<div>
|
||||
<draggable tag="ul" v-model="iVal" ghostClass="ghost" @end="$emit('input', iVal)" :group="ulid"
|
||||
class="list-inline border rounded drop-empty px-3 py-2">
|
||||
<li v-for="val in iVal" class="list-inline-item py-1">
|
||||
<a href="#" class="badge badge-light border p-2" @click.prevent>
|
||||
<slot v-bind:v="val" v-bind:desc="options[val]">
|
||||
{{ val }}
|
||||
</slot>
|
||||
</a>
|
||||
</li>
|
||||
</draggable>
|
||||
|
||||
<draggable tag="ul" v-model="remainingOptions" ghostClass="ghost" @end="$emit('input', iVal)" class="list-inline" :group="ulid">
|
||||
<li v-for="val in remainingOptions" class="list-inline-item py-1">
|
||||
<a href="#" class="badge badge-light p-2" @click.prevent>
|
||||
<slot v-bind:v="val" v-bind:desc="options[val]">
|
||||
{{ val }}
|
||||
</slot>
|
||||
</a>
|
||||
</li>
|
||||
</draggable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable';
|
||||
import { ulid } from 'ulid';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
draggable,
|
||||
},
|
||||
props: {
|
||||
value: {},
|
||||
options: {},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
iVal: this.value,
|
||||
remainingOptions: this.buildRemainingOptions(),
|
||||
ulid: ulid(),
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
this.iVal = this.value;
|
||||
this.remainingOptions = this.buildRemainingOptions();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
buildRemainingOptions() {
|
||||
return Object.keys(this.options).filter(o => !this.value.includes(o));
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ghost {
|
||||
opacity: 0.5;
|
||||
background: #c8ebfb;
|
||||
}
|
||||
|
||||
.drop-empty:empty {
|
||||
min-height: 3em;
|
||||
}
|
||||
</style>
|
|
@ -690,6 +690,8 @@ profile:
|
|||
words: 'Słowa'
|
||||
birthday: 'Wiek'
|
||||
birthdayInfo: 'Nie pokazujemy publicznie pełnej daty urodzenia, jedynie obliczony wiek.'
|
||||
flags: 'Flagi'
|
||||
flagsInfo: 'Przeciągnij swoje pride''owe flagi do poniższej ramki.'
|
||||
links: 'Linki'
|
||||
column: 'Kolumna'
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import translations from './server/translations';
|
||||
import config from './server/config';
|
||||
import fs from 'fs';
|
||||
import {buildDict} from "./src/helpers";
|
||||
|
||||
const locale = config.locale;
|
||||
const title = translations.title;
|
||||
|
@ -87,6 +88,16 @@ export default {
|
|||
BASE_URL: process.env.BASE_URL,
|
||||
PUBLIC_KEY: fs.readFileSync(__dirname + '/keys/public.pem').toString(),
|
||||
LOCALE: config.locale,
|
||||
FLAGS: buildDict(function *() {
|
||||
for (let flag of fs.readdirSync(__dirname + '/static/flags/')) {
|
||||
yield [
|
||||
flag.replace(new RegExp('\.png$'), ''),
|
||||
flag.replace(new RegExp('\.png$'), '')
|
||||
.replace(new RegExp('_', 'g'), '')
|
||||
.trim()
|
||||
];
|
||||
}
|
||||
}),
|
||||
},
|
||||
serverMiddleware: {
|
||||
'/': bodyParser.json(),
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
</p>
|
||||
</section>
|
||||
|
||||
<section v-if="Object.keys(profile.links).length">
|
||||
<section v-if="profile.links.length">
|
||||
<ul class="list-inline">
|
||||
<li v-for="link in profile.links" class="list-inline-item pr-2">
|
||||
<ProfileLink :link="link"/>
|
||||
|
@ -41,10 +41,10 @@
|
|||
</ul>
|
||||
</section>
|
||||
|
||||
<section v-if="Object.keys(profile.flags).length">
|
||||
<section v-if="profile.flags.length">
|
||||
<ul class="list-inline">
|
||||
<li v-for="(name, flag) in profile.flags" class="list-inline-item pr-2">
|
||||
<Flag :name="name" :src="`/flags/${flag}.png`"/>
|
||||
<li v-for="flag in profile.flags" class="list-inline-item pr-2">
|
||||
<Flag :name="allFlags[flag]" :src="`/flags/${flag}.png`"/>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
@ -102,6 +102,7 @@
|
|||
username: this.$route.params.pathMatch,
|
||||
profiles: {},
|
||||
glue: ' ' + this.$t('template.or') + ' ',
|
||||
allFlags: process.env.FLAGS,
|
||||
}
|
||||
},
|
||||
async asyncData({ app, route }) {
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
<Icon v="link"/>
|
||||
<T>profile.pronouns</T>
|
||||
</h3>
|
||||
<OpinionListInput v-model="pronouns"/>
|
||||
<p class="small text-muted">
|
||||
<p class="small text-muted mb-0">
|
||||
<T>profile.pronounsInfo</T>
|
||||
</p>
|
||||
<OpinionListInput v-model="pronouns"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -42,6 +42,19 @@
|
|||
<textarea class="form-control" v-model="description" maxlength="256" rows="4"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<h3 class="h4">
|
||||
<Icon v="flag"/>
|
||||
<T>profile.flags</T>
|
||||
</h3>
|
||||
<p class="small text-muted mb-0">
|
||||
<T>profile.flagsInfo</T>
|
||||
</p>
|
||||
<ButtonList v-model="flags" :options="allFlags" v-slot="s">
|
||||
<Flag :name="s.desc" :src="`/flags/${s.v}.png`"/>
|
||||
</ButtonList>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<h3 class="h4">
|
||||
<Icon v="link"/>
|
||||
|
@ -57,10 +70,10 @@
|
|||
<Icon v="birthday-cake"/>
|
||||
<T>profile.birthday</T>
|
||||
</h3>
|
||||
<input type="date" class="form-control" v-model="birthday"/>
|
||||
<p class="small text-muted">
|
||||
<p class="small text-muted mb-0">
|
||||
<T>profile.birthdayInfo</T>
|
||||
</p>
|
||||
<input type="date" class="form-control" v-model="birthday"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -100,6 +113,7 @@
|
|||
data() {
|
||||
return {
|
||||
saving: false,
|
||||
allFlags: process.env.FLAGS,
|
||||
};
|
||||
},
|
||||
async asyncData({ app, store }) {
|
||||
|
@ -123,7 +137,7 @@
|
|||
description: profile.description,
|
||||
birthday: profile.birthday,
|
||||
links: Object.keys(profile.links).length ? profile.links : [],
|
||||
flags: dictToList(profile.flags),
|
||||
flags: profile.flags,
|
||||
words: profile.words.map(x => dictToList(x)),
|
||||
};
|
||||
}
|
||||
|
@ -140,7 +154,7 @@
|
|||
description: '',
|
||||
birthday: profile.birthday,
|
||||
links: Object.keys(profile.links).length ? profile.links : [],
|
||||
flags: dictToList(profile.flags),
|
||||
flags: profile.flags,
|
||||
words: defaultWords,
|
||||
};
|
||||
}
|
||||
|
@ -166,8 +180,8 @@
|
|||
pronouns: listToDict(this.pronouns),
|
||||
description: this.description,
|
||||
birthday: this.birthday,
|
||||
links: this.links,
|
||||
flags: listToDict(this.flags),
|
||||
links: [...this.links],
|
||||
flags: [...this.flags],
|
||||
words: this.words.map(x => listToDict(x)),
|
||||
}, { headers: this.$auth() });
|
||||
this.saving = false;
|
||||
|
|
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 348 B |
After Width: | Height: | Size: 321 B |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 317 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 985 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 372 B |
After Width: | Height: | Size: 348 B |
After Width: | Height: | Size: 314 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 372 B |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 355 B |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 408 B |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 8.3 KiB |