#256 credentials

This commit is contained in:
Avris 2021-08-26 14:25:59 +02:00
parent 951637bdaf
commit b88e13055a
7 changed files with 156 additions and 1 deletions

View File

@ -930,6 +930,18 @@ contact:
members: 'Obecny skład'
member: 'Osoba członkowska kolektywu'
upcoming: 'Nadchodzące wersje językowe'
credentials:
header: 'Kwalifikacje'
description:
- >
Promujemy postrzeganie kształtowania języka jako procesu oddolnego,
w którym uczestniczy każda używająca go osoba, dlatego „legitymizując” naszą działalność
wolimy skupiać się raczej na fakcie bycia po prostu
1) osobami używającymi języka polskiego, 2) osobami niebinarnymi i sojuszniczymi.
Wszystkie mamy prawo kształtować nasz język!
- >
Rozumiemy też jednak, że aby niektóre osoby brały nas na poważnie,
musimy podzielić się naszym formalnym wykształceniem. Oto zatem (niepełna) lista:
support:
header: 'Wsparcie'

View File

@ -0,0 +1,40 @@
-- Up
ALTER TABLE profiles ADD COLUMN credentials TEXT NULL DEFAULT NULL;
ALTER TABLE profiles ADD COLUMN credentialsLevel INTEGER NULL DEFAULT NULL;
ALTER TABLE profiles ADD COLUMN credentialsName INTEGER NULL DEFAULT NULL;
UPDATE profiles
SET credentials = 'magistra filologii angielskiej',
credentialsLevel = 5,
credentialsName = 'Karolina Grenda'
WHERE locale = 'pl' AND userId = (SELECT id FROM users WHERE usernameNorm = 'kafka');
UPDATE profiles
SET credentials = 'magister filologii angielskiej|student filologii hiszpańskiej',
credentialsLevel = 5
WHERE locale = 'pl' AND userId = (SELECT id FROM users WHERE usernameNorm = 'ausir');
UPDATE profiles
SET credentials = 'magistra filologii słowiańskiej (z językiem czeskim) i filologii polskiej na UAM|{http://gazetylokalne.pl/sgl-local-press-2018-nominacje/=dziennikarka nominowana do SGL Local Press 2018 za reportaż „Film »Kler« i kler wrzesiński”}',
credentialsLevel = 5,
credentialsName = 'Anna Tess Gołębiowska'
WHERE locale = 'pl' AND userId = (SELECT id FROM users WHERE usernameNorm = 'tess');
UPDATE profiles
SET credentials = 'magistru językoznawstwa',
credentialsLevel = 5
WHERE locale = 'pl' AND userId = (SELECT id FROM users WHERE usernameNorm = 'cake');
UPDATE profiles
SET credentials = 'magister językoznawstwa|absolwent Gender Studies w PAN|doktorant w Instytucie Anglistyki UW|https://orcid.org/0000-0002-0214-0387',
credentialsLevel = 6
WHERE locale = 'pl' AND userId = (SELECT id FROM users WHERE usernameNorm = 'szymon');
UPDATE profiles
SET credentials = 'inżynierze Informatyki|finaliszcze Olimpiady Literatury i Języka Polskiego',
credentialsLevel = 1
WHERE locale = 'pl' AND userId = (SELECT id FROM users WHERE usernameNorm = 'andrea');
-- Down

View File

@ -46,6 +46,10 @@ const LINK_PROVIDERS = {
homepage: 'https://cake.avris.it',
name: 'Attraction Layer Cake',
},
orcid: {
regex: '^https?://(?:www.)?orcid.org/([^/]+)',
icon: 'https://orcid.org/assets/icons/favicon.ico',
},
};
export default {

View File

@ -50,6 +50,40 @@
<label for="footerAreas">Areas responsible for / contributing to:</label>
<ListInput v-model="footerAreas"/>
</div>
<template v-if="$te('contact.team.credentials')">
<hr/>
<p class="small text-muted mb-0">
This will be displayed on the team page in the "Credentials" section.
You might want to put here your full legal name here, but it's not required
(you can leave this field empty).
</p>
<div class="form-group">
<label for="credentials">Credentials:</label>
<ListInput v-model="credentials"/>
</div>
<div class="form-group">
<label for="credentials">Credentials level:</label>
<select v-model="credentialsLevel" class="form-select">
<option :value="null"></option>
<option :value="1">Higher education, but irrelevant field</option>
<option :value="2">Bachelor (not completed yet)</option>
<option :value="3">Bachelor</option>
<option :value="4">Master (not completed yet)</option>
<option :value="5">Master</option>
<option :value="6">PhD (not completed yet)</option>
<option :value="7">PhD</option>
</select>
</div>
<div class="form-group">
<label for="credentials">Name for credentials:</label>
<input v-model="credentialsName" class="form-control" placeholder="(not required)"/>
</div>
</template>
</div>
<section>
@ -211,6 +245,9 @@
teamName: profile.teamName,
footerName: profile.footerName,
footerAreas: profile.footerAreas,
credentials: profile.credentials,
credentialsLevel: profile.credentialsLevel,
credentialsName: profile.credentialsName,
};
}
}
@ -232,6 +269,9 @@
teamName: profile.teamName,
footerName: profile.footerName,
footerAreas: [],
credentials: [],
credentialsLevel: null,
credentialsName: null,
};
}
@ -247,6 +287,9 @@
teamName: '',
footerName: '',
footerAreas: [],
credentials: [],
credentialsLevel: null,
credentialsName: null,
};
},
mounted() {
@ -271,6 +314,9 @@
teamName: this.teamName,
footerName: this.footerName,
footerAreas: this.footerAreas,
credentials: this.credentials,
credentialsLevel: this.credentialsLevel,
credentialsName: this.credentialsName,
});
this.$router.push(`/@${this.$user().username}`);
} finally {

View File

@ -25,6 +25,30 @@
<Mission/>
<section v-if="$te('contact.team.credentials')">
<h3>
<Icon v="graduation-cap"/>
<T>contact.team.credentials.header</T>
</h3>
<T>contact.team.credentials.description</T>
<ul>
<li v-for="credential in credentials">
<strong>{{ credential.credentialsName || credential.teamName }}</strong>
<a :href="`https://pronouns.page/@${credential.username}`" class="badge bg-light text-dark border">
@{{credential.username}}
</a>
<ul>
<li v-for="item in credential.credentials">
<ProfileLink v-if="item.startsWith('https://') || item.startsWith('http://')" :link="item"/>
<LinkedText v-else :text="item"/>
</li>
</ul>
</li>
</ul>
</section>
<section>
<h3>
<Icon v="user-friends"/>
@ -76,6 +100,26 @@
membersByLocale: await app.$axios.$get(`/admin/list`),
}
},
computed: {
credentials() {
const r = [];
for (let locale in this.membersByLocale) {
if (!this.membersByLocale.hasOwnProperty(locale)) { continue; }
for (let member of this.membersByLocale[locale]) {
if (member.locale === this.config.locale && member.credentials !== null) {
r.push(member);
}
}
}
return r.sort((a, b) => {
if (a.credentialsLevel > b.credentialsLevel) { return -1; }
if (a.credentialsLevel < b.credentialsLevel) { return 1; }
return Math.random() > 0.5 ? 1 : -1;
});
},
},
}
</script>

View File

@ -13,7 +13,7 @@ const router = Router();
router.get('/admin/list', handleErrorAsync(async (req, res) => {
return res.json(await caches.admins.fetch(async () => {
const admins = await req.db.all(SQL`
SELECT u.username, p.teamName, p.locale, u.id, u.email, u.avatarSource
SELECT u.username, p.teamName, p.locale, u.id, u.email, u.avatarSource, p.credentials, p.credentialsLevel, p.credentialsName
FROM users u
LEFT JOIN profiles p ON p.userId = u.id
WHERE p.teamName IS NOT NULL
@ -34,6 +34,9 @@ router.get('/admin/list', handleErrorAsync(async (req, res) => {
admin.avatar = await avatar(req.db, admin);
delete admin.id;
delete admin.email;
if (admin.credentials) {
admin.credentials = admin.credentials.split('|');
}
if (adminsGroupped[admin.locale] !== undefined) {
adminsGroupped[admin.locale].push(admin);

View File

@ -47,6 +47,9 @@ const fetchProfiles = async (db, username, self, isAdmin) => {
teamName: profile.teamName,
footerName: profile.footerName,
footerAreas: profile.footerAreas ? profile.footerAreas.split(',') : [],
credentials: profile.credentials ? profile.credentials.split('|') : [],
credentialsLevel: profile.credentialsLevel,
credentialsName: profile.credentialsName,
card: profile.card,
};
}
@ -160,6 +163,9 @@ router.post('/profile/save', handleErrorAsync(async (req, res) => {
teamName = ${req.isGranted() ? req.body.teamName || null : ''},
footerName = ${req.isGranted() ? req.body.footerName || null : ''},
footerAreas = ${req.isGranted() ? req.body.footerAreas.join(',') || null : ''},
credentials = ${req.isGranted() ? req.body.credentials.join('|') || null : null},
credentialsLevel = ${req.isGranted() ? req.body.credentialsLevel || null : null},
credentialsName = ${req.isGranted() ? req.body.credentialsName || null : null},
card = NULL
WHERE id = ${ids[0]}
`);