This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Zaimki/components/Account.vue

238 lines
9.5 KiB
Vue
Raw Normal View History

2020-10-15 11:29:56 -07:00
<template>
<section>
2020-10-15 15:41:41 -07:00
<div class="card mb-3">
<div class="card-body d-flex flex-column flex-md-row">
2020-10-16 01:08:48 -07:00
<div class="mx-2 text-center">
<p class="mb-0">
2020-10-15 15:41:41 -07:00
<Avatar :user="$user()"/>
</p>
2020-12-24 04:00:37 -08:00
<div class="mb-2">
2021-01-08 06:14:53 -08:00
<div v-if="$user().avatarSource === 'gravatar'" class="mt-3">
2020-12-24 04:00:37 -08:00
<a href="https://gravatar.com" target="_blank" rel="noopener" class="small">
<Icon v="external-link"/>
<T>user.avatar.change</T>
2021-01-08 06:14:53 -08:00
Gravatar
</a>
</div>
<div v-else class="mt-3">
Gravatar:
<a href="#" @click.prevent="setAvatar('gravatar')">
<Avatar :user="$user()" :src="gravatar($user())" dsize="2rem"/>
2020-12-24 04:00:37 -08:00
</a>
</div>
<div v-if="$user().avatarSource">
<a href="#" @click.prevent="setAvatar(null)" class="small">
<Icon v="trash"/>
<T>crud.remove</T>
</a>
</div>
2021-01-08 06:14:53 -08:00
<ImageUploader small @uploaded="uploaded"/>
2020-12-24 04:00:37 -08:00
</div>
2020-12-30 15:03:30 -08:00
<p v-if="$isGranted('panel') || $isGranted('users')">
2020-10-29 15:41:40 -07:00
<nuxt-link to="/admin" class="badge badge-primary"><T>user.account.admin</T></nuxt-link>
2020-10-16 01:08:48 -07:00
</p>
2020-10-15 15:41:41 -07:00
</div>
<div class="mx-2 flex-grow-1">
<Alert type="danger" :message="error"/>
2020-10-27 10:15:18 -07:00
<div v-if="changeEmailAuthId" class="alert alert-success">
<p class="mb-0 narrow-message">
<Icon v="envelope-open-text"/>
<T>user.login.emailSent</T>
</p>
</div>
2020-10-15 15:41:41 -07:00
<form @submit.prevent="changeUsername">
<h3 class="h6"><T>user.account.changeUsername.header</T></h3>
<div class="input-group mb-3">
<input type="text" class="form-control" v-model="username"
required minlength="4" maxlength="16"/>
<div class="input-group-append">
<button class="btn btn-outline-primary">
<T>user.account.changeUsername.action</T>
</button>
</div>
</div>
</form>
2020-10-27 10:15:18 -07:00
<form @submit.prevent="changeEmail">
2020-10-15 15:41:41 -07:00
<h3 class="h6"><T>user.account.changeEmail.header</T></h3>
2020-10-27 10:15:18 -07:00
<div v-if="!changeEmailAuthId" class="input-group mb-3">
<input type="email" class="form-control" v-model="email" required/>
<div class="input-group-append">
<button class="btn btn-outline-primary">
<T>user.account.changeEmail.action</T>
</button>
</div>
</div>
<div v-else class="input-group mb-3">
<input type="text" class="form-control text-center" v-model="code"
placeholder="000000" autofocus required minlength="0" maxlength="6"
inputmode="numeric" pattern="[0-9]{6}" autocomplete="one-time-code"
ref="code"
/>
<div class="input-group-append">
<button class="btn btn-outline-primary">
<Icon v="key"/>
<T>user.code.action</T>
</button>
</div>
</div>
</form>
2020-10-15 11:29:56 -07:00
</div>
</div>
</div>
<Loading :value="profiles">
2020-11-02 10:31:05 -08:00
<template v-slot:header>
<h3 class="h4"><T>profile.list</T>:</h3>
2020-11-02 10:31:05 -08:00
</template>
<ul v-if="profiles !== undefined" class="list-group">
<li v-for="(options, locale) in locales" :key="locale" :class="['list-group-item', locale === config.locale ? 'profile-current' : '']">
<ProfileOverview :profile="profiles[locale]" :locale="locale" @update="setProfiles"/>
2020-11-02 10:31:05 -08:00
</li>
</ul>
</Loading>
<Loading :value="socialConnections">
2020-11-02 10:31:05 -08:00
<template v-slot:header>
<h3 class="h4"><T>user.socialConnection.list</T>:</h3>
2020-11-02 10:31:05 -08:00
</template>
<ul v-if="socialConnections !== undefined" class="list-group">
2020-11-02 12:25:48 -08:00
<li v-for="(providerOptions, provider) in socialProviders" :key="provider" :class="['list-group-item', socialConnections[provider] !== undefined ? 'profile-current' : '']">
<SocialConnection :provider="provider" :providerOptions="providerOptions" :connection="socialConnections[provider]"
@disconnected="socialConnections[provider] = undefined" @setAvatar="setAvatar"/>
</li>
</ul>
2020-11-02 10:31:05 -08:00
</Loading>
2020-10-27 08:33:45 -07:00
<section>
<a href="#" class="badge badge-light border" @click.prevent="logout">
2020-10-15 15:41:41 -07:00
<Icon v="sign-out"/>
<T>user.logout</T>
2020-10-27 08:33:45 -07:00
</a>
<a href="#" class="badge badge-light border" @click.prevent="deleteAccount">
<Icon v="trash-alt"/>
<T>user.deleteAccount</T>
</a>
</section>
2020-10-15 11:29:56 -07:00
</section>
</template>
<script>
2020-11-02 10:31:05 -08:00
import {socialProviders} from "../src/data";
2020-12-24 04:00:37 -08:00
import {gravatar} from "../src/helpers";
2020-11-02 10:31:05 -08:00
2020-10-15 11:29:56 -07:00
export default {
data() {
return {
username: this.$user().username,
email: this.$user().email,
error: '',
2020-10-27 10:15:18 -07:00
changeEmailAuthId: null,
code: '',
profiles: undefined,
2020-11-02 10:31:05 -08:00
socialProviders,
socialConnections: undefined,
2020-12-24 04:00:37 -08:00
gravatar,
}
},
async mounted() {
this.profiles = await this.$axios.$get(`/profile/get/${this.$user().username}`);
2020-11-02 10:31:05 -08:00
this.socialConnections = await this.$axios.$get(`/user/social-connections`);
if (process.client) {
const redirectTo = window.sessionStorage.getItem('after-login');
if (this.$user() && redirectTo) {
window.sessionStorage.removeItem('after-login')
await this.$router.push(redirectTo);
}
}
2020-10-15 11:29:56 -07:00
},
methods: {
async changeUsername() {
this.error = '';
2020-10-27 10:15:18 -07:00
const response = await this.$axios.$post(`/user/change-username`, {
username: this.username,
2020-11-02 10:31:05 -08:00
});
2020-10-15 11:29:56 -07:00
if (response.error) {
this.error = response.error;
return;
}
this.$store.commit('setToken', response.token);
this.$cookies.set('token', this.$store.state.token);
},
2020-10-27 10:15:18 -07:00
async changeEmail() {
this.error = '';
const response = await this.$axios.$post(`/user/change-email`, {
email: this.email,
authId: this.changeEmailAuthId,
code: this.code,
2020-11-02 10:31:05 -08:00
});
2020-10-27 10:15:18 -07:00
if (response.error) {
this.error = response.error;
return;
}
if (!this.changeEmailAuthId) {
this.changeEmailAuthId = response.authId;
this.$nextTick(_ => {
this.$refs.code.focus();
});
} else {
this.changeEmailAuthId = null;
this.code = null;
this.$store.commit('setToken', response.token);
this.$cookies.set('token', this.$store.state.token);
}
},
2020-10-15 11:29:56 -07:00
logout() {
this.$store.commit('setToken', null);
this.$cookies.removeAll();
2020-10-15 15:41:41 -07:00
},
2020-10-24 13:32:12 -07:00
setProfiles(profiles) {
this.profiles = profiles;
},
2020-10-27 08:33:45 -07:00
async deleteAccount() {
await this.$confirm(this.$t('user.deleteAccountConfirm'), 'danger');
2020-11-02 10:31:05 -08:00
const response = await this.$axios.$post(`/user/delete`);
2020-10-27 08:33:45 -07:00
this.logout();
},
2020-11-02 12:12:15 -08:00
async setAvatar(source) {
const response = await this.$axios.$post(`/user/set-avatar`, {source});
this.$store.commit('setToken', response.token);
this.$cookies.set('token', this.$store.state.token);
},
2021-01-08 06:14:53 -08:00
async uploaded(ids) {
await this.setAvatar(`${process.env.BUCKET}/images/${ids[0]}-thumb.png`);
},
2020-10-15 11:29:56 -07:00
},
}
</script>
<style lang="scss" scoped>
@import "assets/variables";
.profile-current {
border-left: 3px solid $primary;
}
2020-10-27 10:15:18 -07:00
.narrow-message {
max-width: 56ch;
}
</style>