#50 pronouns cards - delete

This commit is contained in:
Avris 2020-10-24 22:32:12 +02:00
parent 5a38be5af4
commit 9772e7db30
7 changed files with 151 additions and 8 deletions

View File

@ -42,7 +42,7 @@ $container-max-widths: (
@import "~bootstrap/scss/list-group";
//@import "~bootstrap/scss/close";
//@import "~bootstrap/scss/toasts";
//@import "~bootstrap/scss/modal";
@import "~bootstrap/scss/modal";
//@import "~bootstrap/scss/tooltip";
//@import "~bootstrap/scss/popover";
//@import "~bootstrap/scss/carousel";

View File

@ -44,7 +44,7 @@
<h3 class="h4"><T>profile.list</T>:</h3>
<ul class="list-group mb-3">
<li v-for="(options, locale) in locales" :key="locale" :class="['list-group-item', locale === config.locale ? 'profile-current' : '']">
<ProfileOverview :profile="profiles[locale]" :locale="locale"/>
<ProfileOverview :profile="profiles[locale]" :locale="locale" @update="setProfiles"/>
</li>
</ul>
</template></Loading>
@ -96,6 +96,9 @@
this.$store.commit('setToken', null);
this.$cookies.removeAll();
},
setProfiles(profiles) {
this.profiles = profiles;
},
},
}
</script>

94
components/Confirm.vue Normal file
View File

@ -0,0 +1,94 @@
<template>
<div :class="['modal', shown ? 'd-block' : '']" @click="hideClick">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content shadow">
<div class="modal-header">
<p class="h5 modal-title">
<Icon v="map-marker-question"/>
{{$t('confirm.header')}}
</p>
</div>
<div class="modal-body">
<p class="py-5 text-center" v-html="message"></p>
</div>
<div class="modal-footer">
<button class="btn btn-outline-dark" @click="cancel">
{{$t('confirm.no')}}
</button>
<button :class="'btn btn-' + (color || 'primary')" @click="confirm">
{{$t('confirm.yes')}}
</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
shown: false,
message: undefined,
resolve: undefined,
reject: undefined,
color: null,
}
},
mounted() {
if (process.client) {
window.addEventListener('keydown', e => {
if (e.keyCode === 27) {
this.cancel();
} else if (e.keyCode === 13) {
this.confirm();
}
});
}
},
methods: {
show(message, color, resolve, reject) {
this.message = message;
this.resolve = resolve;
this.reject = reject;
this.color = color;
this.shown = true;
},
confirm() {
const resolve = this.resolve;
this.shown = false;
this.message = undefined;
this.resolve = undefined;
this.reject = undefined;
this.color = null;
if (resolve) {
resolve();
}
},
cancel(event) {
const reject = this.reject;
this.shown = false;
this.message = undefined;
this.resolve = undefined;
this.reject = undefined;
this.color = null;
if (reject) {
reject();
}
},
hideClick(event) {
if (event.target === this.$el) {
this.cancel();
}
},
},
};
</script>
<style lang="scss" scoped>
@import "assets/style";
.modal {
background-color: rgba($black, 0.5);
}
</style>

View File

@ -10,9 +10,10 @@
<Icon v="edit"/>
<T>profile.edit</T>
</LocaleLink>
<LocaleLink :locale="locale" link="/TODOS" class="badge badge-light">
<Spinner v-if="deleting"/>
<a v-else href="#" class="badge badge-light" @click.prevent="removeProfile(locale)">
<Icon v="trash-alt"/>
</LocaleLink>
</a>
</span>
<span v-else>
<LocaleLink :locale="locale" :link="`/${config.user.profileEditorRoute}`" class="badge badge-light border">
@ -28,6 +29,21 @@
props: {
profile: { required: true },
locale: { required: true },
},
data() {
return {
deleting: false,
}
},
methods: {
async removeProfile() {
await this.$confirm(this.$t('profile.deleteConfirm'), 'danger');
this.deleting = true;
const response = await this.$axios.$post(`/profile/delete/${this.config.locale}`, {}, { headers: this.$auth() });
this.deleting = false;
this.$emit('update', response);
},
},
}
</script>

View File

@ -8,9 +8,24 @@
<div class="container">
<Footer/>
</div>
<Confirm ref="confirm"/>
</div>
</template>
<script>
import Vue from 'vue';
export default {
mounted() {
Vue.prototype.$confirm = (message, color='primary') => {
return new Promise((resolve, reject) => {
this.$refs.confirm.show(message, color, resolve, reject);
});
};
}
}
</script>
<style lang="scss">
@import "assets/style";
</style>

View File

@ -698,6 +698,7 @@ profile:
show: 'Pokaż'
edit: 'Edytuj'
delete: 'Usuń'
deleteConfirm: 'Czy na pewno chcesz usunąć tę wizytówkę?'
editor:
header: 'Edytor wizytówki'
save: 'Zapisz wizytówkę'
@ -725,3 +726,8 @@ footer:
notFound:
message: 'Strony nie znaleziono'
back: 'Wróć na główną'
confirm:
header: 'Czy jesteś pewnx?'
yes: 'Tak, na pewno'
no: 'Nie, anuluj'

View File

@ -38,7 +38,7 @@ const buildProfile = profile => {
};
};
const fetchProfile = async (db, res, username, self) => {
const fetchProfiles = async (db, res, username, self) => {
const profiles = await db.all(SQL`
SELECT profiles.*, users.username, users.email FROM profiles LEFT JOIN users on users.id == profiles.userId
WHERE users.username = ${username}
@ -65,7 +65,7 @@ export default async function (req, res, next) {
if (req.method === 'GET' && req.url.startsWith('/get/')) {
const username = req.url.substring(5);
return await fetchProfile(db, res, username, user && user.authenticated && user.username === username)
return await fetchProfiles(db, res, username, user && user.authenticated && user.username === username)
}
if (!user || !user.authenticated) {
@ -83,7 +83,16 @@ export default async function (req, res, next) {
${JSON.stringify(req.body.words)}, 1
)`);
return fetchProfile(db, res, user.username, true);
return fetchProfiles(db, res, user.username, true);
}
if (req.method === 'POST' && req.url.startsWith('/delete/')) {
const locale = req.url.substring(8);
const userId = (await db.get(SQL`SELECT id FROM users WHERE username = ${user.username}`)).id;
await db.get(SQL`DELETE FROM profiles WHERE userId = ${userId} AND locale = ${locale}`);
return fetchProfiles(db, res, user.username, true);
}
return renderJson(res, { error: 'notfound' }, 404);