connection

This commit is contained in:
Troplo 2020-09-29 23:06:27 +10:00
parent d92e924139
commit cea2421860
10 changed files with 478 additions and 308 deletions

View File

@ -26,288 +26,310 @@
-ms-user-select: none; /* IE10+/Edge */
user-select: none; /* Standard */
}
.vertical {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.connSize {
font-size: 55px;
}
</style>
<template>
<div id='app'>
<main>
<modal-window v-model='showAjaxErrorsModal' style='z-index: 100' width='25rem' :no-padding='true'>
<div slot='main'>
<p :key='error' v-for='error in this.$store.state.ajaxErrors' style='margin: 1rem;'>{{error}}</p>
</div>
<button
slot='footer'
class='button button--modal'
style='z-index: 100' width='25rem'
@click='showAjaxErrorsModal = false'
ref='ajaxErrorsModalButton'
<modal-window v-model='showAjaxErrorsModal' style='z-index: 100' width='25rem' :no-padding='true'>
<div slot='main'>
<p :key='error' v-for='error in this.$store.state.ajaxErrors' style='margin: 1rem;'>{{error}}</p>
</div>
<button
slot='footer'
class='button button--modal'
style='z-index: 100' width='25rem'
@click='showAjaxErrorsModal = false'
ref='ajaxErrorsModalButton'
>
OK
</button>
</modal-window>
<b-modal :active="connModal" @update:active="value => connModal = value" v-model="connModal" full-screen>
<div class="modal-card" style="width: auto">
<section class="vertical">
<center>
<h1><i class="fal fa-spinner-third fa-spin connSize"></i></h1>
<h1>Connecting to Kaverti...</h1>
<p>Taking a while? Check the <a href="https://status.troplo.com">service status</a>, or alert us on <a href="https://twitter.com/Kaverti">Twitter</a>!</p>
</center>
</section>
</div>
</b-modal>
<modal-window v-model='showOutLinkModal' style='z-index: 100' width='25rem' :no-padding='true'>
<div slot='main'>
<p style='margin: 1rem;'>Oh uh! Do you actually wanna go to this page?</p>
</div>
<button
slot='footer'
class='button button--modal'
style='z-index: 100' width='25rem'
@click='showAjaxErrorsModal = false'
ref='ajaxErrorsModalButton'
>
I do, yes
</button>
<button
slot='footer'
class='button button--modal'
style='z-index: 100' width='25rem'
@click='showAjaxErrorsModal = false'
ref='ajaxErrorsModalButton'
>
No, I do not
</button>
</modal-window>
<modal-window
v-model='showAccountModal'
@input='closeAccountModal'
:no-padding='true'
:hide-footer='true'
>
OK
</button>
</modal-window>
<modal-window v-model='showOutLinkModal' style='z-index: 100' width='25rem' :no-padding='true'>
<div slot='main'>
<p style='margin: 1rem;'>Oh uh! Do you actually wanna go to this page?</p>
</div>
<button
slot='footer'
class='button button--modal'
style='z-index: 100' width='25rem'
@click='showAjaxErrorsModal = false'
ref='ajaxErrorsModalButton'
>
I do, yes
</button>
<button
slot='footer'
class='button button--modal'
style='z-index: 100' width='25rem'
@click='showAjaxErrorsModal = false'
ref='ajaxErrorsModalButton'
>
No, I do not
</button>
</modal-window>
<modal-window
v-model='showAccountModal'
@input='closeAccountModal'
:no-padding='true'
:hide-footer='true'
>
<tab-view
:tabs='["Register", "Login"]'
v-model="showAccountTab"
padding='true'
slot='main'
>
<template slot='Register'>
<p style='margin-top: 0;' v-if='$store.state.token'>
<strong>Providing the state token is still valid, this will create an admin account</strong>
</p>
<p style='margin-top: 0;' v-if='$store.state.passkey'>
<strong>Providing a PassKey, this will create a normal user account</strong>
</p>
<p style='margin-top: 0;' v-else>
Sign up to {{name}} today!
<br/>It's fast and easy.
</p>
<br/>
<tab-view
:tabs='["Register", "Login"]'
v-model="showAccountTab"
padding='true'
slot='main'
>
<template slot='Register'>
<p style='margin-top: 0;' v-if='$store.state.token'>
<strong>Providing the state token is still valid, this will create an admin account</strong>
</p>
<p style='margin-top: 0;' v-if='$store.state.passkey'>
<strong>Providing a PassKey, this will create a normal user account</strong>
</p>
<p style='margin-top: 0;' v-else>
Sign up to {{name}} today!
<br/>It's fast and easy.
</p>
<br/>
<form @submit.prevent='createAccount'>
<form @submit.prevent='createAccount'>
<fancy-input
v-model='signup.username'
:label-position="kavelabelPosition"
:error='signup.errors.username'
placeholder='Username'
width='100%'
>
</fancy-input>
<fancy-input
v-model='signup.email'
:label-position="kavelabelPosition"
:error='signup.errors.email'
placeholder='Email'
width='100%'
type="email"
>
</fancy-input>
<fancy-input
v-model='signup.password'
:label-position="kavelabelPosition"
:error='signup.errors.hash'
placeholder='Password'
type='password'
width='100%'
>
</fancy-input>
<fancy-input
v-model='signup.confirmPassword'
:label-position="kavelabelPosition"
:error='signup.errors.confirmPassword'
placeholder='Confirm Password'
type='password'
width='100%'
>
</fancy-input>
By pressing the "Register" button, you agree to the Kaverti <router-link to="/legal/tos" v-on:click.native="closeAccountModal">Terms of Service</router-link>, and have read the <router-link to="/legal/privacy" v-on:click.native="closeAccountModal">Privacy Policy</router-link>.
<div style='margin-top: 0.5rem;'>
<b-button
class='is-info'
style="width: 55%"
:loading='signup.loading'
@click='createAccount'
v-if='!$store.state.meta.RegistrationsDisabled'
<fancy-input
v-model='signup.username'
:label-position="kavelabelPosition"
:error='signup.errors.username'
placeholder='Username'
width='100%'
>
Register
</b-button>
<b-button
class='is-info disabled'
disabled="disabled"
style="width: 55%"
:loading='signup.loading'
@click='closeAccountModal'
v-if='$store.state.meta.RegistrationsDisabled'
</fancy-input>
<fancy-input
v-model='signup.email'
:label-position="kavelabelPosition"
:error='signup.errors.email'
placeholder='Email'
width='100%'
type="email"
>
Disabled
</b-button>
&nbsp;
<b-button style="float: right" class="is-danger-passive" @click='closeAccountModal'>
Cancel
</b-button>
</div>
</form>
</template>
<template slot='Login'>
<p style='margin-top: 0;'>
Login to {{name}} for the full experience.
</p>
<form @submit.prevent='doLogin'>
<fancy-input
v-model='login.username'
:error='login.errors.username'
placeholder='Username'
width='100%'
>
</fancy-input>
<fancy-input
v-model='login.password'
:error='login.errors.hash'
placeholder='Password'
type='password'
width='100%'
>
</fancy-input>
</fancy-input>
<fancy-input
v-model='signup.password'
:label-position="kavelabelPosition"
:error='signup.errors.hash'
placeholder='Password'
type='password'
width='100%'
>
</fancy-input>
<fancy-input
v-model='signup.confirmPassword'
:label-position="kavelabelPosition"
:error='signup.errors.confirmPassword'
placeholder='Confirm Password'
type='password'
width='100%'
>
</fancy-input>
By pressing the "Register" button, you agree to the Kaverti <router-link to="/legal/tos" v-on:click.native="closeAccountModal">Terms of Service</router-link>, and have read the <router-link to="/legal/privacy" v-on:click.native="closeAccountModal">Privacy Policy</router-link>.
<div style='margin-top: 0.5rem;'>
<b-button
class='is-info'
style="width: 55%"
:loading='signup.loading'
@click='createAccount'
v-if='!$store.state.meta.RegistrationsDisabled'
>
Register
</b-button>
<b-button
class='is-info disabled'
disabled="disabled"
style="width: 55%"
:loading='signup.loading'
@click='closeAccountModal'
v-if='$store.state.meta.RegistrationsDisabled'
>
Disabled
</b-button>
&nbsp;
<b-button style="float: right" class="is-danger-passive" @click='closeAccountModal'>
Cancel
</b-button>
</div>
</form>
</template>
<template slot='Login'>
<p style='margin-top: 0;'>
Login to {{name}} for the full experience.
</p>
<form @submit.prevent='doLogin'>
<fancy-input
v-model='login.username'
:error='login.errors.username'
placeholder='Username'
width='100%'
>
</fancy-input>
<fancy-input
v-model='login.password'
:error='login.errors.hash'
placeholder='Password'
type='password'
width='100%'
>
</fancy-input>
<div style='margin-top: 0.5rem;'>
<b-button
class='is-info'
style="width: 55%"
:loading='login.loading'
@click='doLogin'
>
Login
</b-button>
&nbsp;
<b-button style="float: right" class="is-danger-passive" @click='closeAccountModal'>
Cancel
</b-button>
</div>
</form>
</template>
</tab-view>
</modal-window>
<template>
<b-navbar v-bind:fixed-top="true">
<template slot="brand">
<b-navbar-item tag="router-link" :to="{ path: '/' }">
<div style='margin-top: 0.5rem;'>
<b-button
class='is-info'
style="width: 55%"
:loading='login.loading'
@click='doLogin'
>
Login
</b-button>
&nbsp;
<b-button style="float: right" class="is-danger-passive" @click='closeAccountModal'>
Cancel
</b-button>
</div>
</form>
</template>
</tab-view>
</modal-window>
<template>
<b-navbar v-bind:fixed-top="true">
<template slot="brand">
<b-navbar-item tag="router-link" :to="{ path: '/' }">
<img
:src = $store.state.meta.logo
>
</b-navbar-item>
</template>
<template slot="start">
<b-navbar-item tag="router-link" :to="{ path: '/forums' }"><b>
Forums
</b></b-navbar-item>
</b-navbar-item>
</template>
<template slot="start">
<b-navbar-item tag="router-link" :to="{ path: '/forums' }"><b>
Forums
</b></b-navbar-item>
<b-navbar-item tag="router-link" href="https://support.kaverti.com"><b>
Support
</b></b-navbar-item>
<b-navbar-item tag="router-link" href="https://support.kaverti.com"><b>
Support
</b></b-navbar-item>
<b-navbar-item tag="router-link" :to="{ path: '/users' }"><b>
Users
</b></b-navbar-item>
<b-navbar-item tag="router-link" :to="{ path: '/users' }"><b>
Users
</b></b-navbar-item>
<b-navbar-item tag="router-link" :to="{ path: '/marketplace' }"><b>
Marketplace
</b></b-navbar-item>
<b-navbar-item tag="router-link" :to="{ path: '/marketplace' }"><b>
Marketplace
</b></b-navbar-item>
<b-navbar-item tag="router-link" :to="{ path: '/games' }"><b>
Games
</b></b-navbar-item>
<b-navbar-item tag="router-link" :to="{ path: '/games' }"><b>
Games
</b></b-navbar-item>
<b-navbar-item tag="router-link" :to="{ path: '/teams' }"><b>
Teams
</b></b-navbar-item>
<b-navbar-item tag="router-link" :to="{ path: '/teams' }"><b>
Teams
</b></b-navbar-item>
<div class="navbar-item has-dropdown is-hoverable is-info" type="is-info">
<a class="navbar-link">
<b>More</b>
</a>
<div class="navbar-dropdown is-boxed">
<router-link class="navbar-item" to='/blog'>Blog</router-link>
<a class="navbar-item" href="https://twitter.com/Kaverti">
Twitter
<div class="navbar-item has-dropdown is-hoverable is-info" type="is-info">
<a class="navbar-link">
<b>More</b>
</a>
<a class="navbar-item" href="https://discord.gg/3jN5RAX">
Discord
</a>
<router-link class="navbar-item" to='/developers'>Developers</router-link>
<router-link class="navbar-item is-active" to='/premium'>Upgrade</router-link>
<router-link class="navbar-item" to='/licenses'>Credits and Licenses</router-link>
<router-link class="navbar-item" to='/contributors'>Contributors</router-link>
</div>
</div>
</template>
<template slot="end" v-if='$store.state.username'>
<b-navbar-item @click="dailyReward()" v-if="$store.state.koins"><b>
{{$store.state.koins}} Koins
</b></b-navbar-item>
<b-navbar-item v-if="!$store.state.koins"><b>
<i class="fas fa-circle-notch fa-spin"></i> Loading...
</b></b-navbar-item>
<b-navbar-item tag="div">
<div>
<NotificationButton></NotificationButton>
</div>
<div>
<div class="navbar-item has-dropdown is-hoverable is-info">
<a class="navbar-link">
<b>{{this.$store.state.username}}</b>
<div class="navbar-dropdown is-boxed">
<router-link class="navbar-item" to='/blog'>Blog</router-link>
<a class="navbar-item" href="https://twitter.com/Kaverti">
Twitter
</a>
<div class="navbar-dropdown is-boxed">
<router-link class="navbar-item" :to='"/user/" + this.$store.state.username'>My Profile</router-link>
<router-link class="navbar-item" to='/settings'>Settings</router-link>
<router-link to='/admin' class="navbar-item" v-if='$store.state.admin'>Admin Panel</router-link>
<router-link class="navbar-item is-active" to='/premium'>Upgrade</router-link>
<a class="navbar-item" @click='logout'>
Log out
</a>
</div>
<a class="navbar-item" href="https://discord.gg/3jN5RAX">
Discord
</a>
<router-link class="navbar-item" to='/developers'>Developers</router-link>
<router-link class="navbar-item is-active" to='/premium'>Upgrade</router-link>
<router-link class="navbar-item" to='/licenses'>Credits and Licenses</router-link>
<router-link class="navbar-item" to='/contributors'>Contributors</router-link>
</div>
</div>
<search-box header-bar='true'></search-box>
</b-navbar-item>
</template>
<template slot="end" v-else>
<b-navbar-item tag="div">
<div class="buttons">
<a class="button is-info" @click="showAccountModalTab(0)">
<strong>Sign up</strong>
</a>
<a class="button is-light" @click="showAccountModalTab(1)">
Log in
</a>
</div>
</b-navbar-item>
</template>
</b-navbar>
</template>
<div v-if='$store.state.meta.bannerEnabled && $store.state.meta.bannerText && !$store.state.username' class="container is-fullhd" style="padding-left: 5px; padding-right: 5px; padding-top: 20px; padding-bottom: 5px;">
<div class="notification is-info">
{{$store.state.meta.bannerText}}
</template>
<template slot="end" v-if='$store.state.username'>
<b-navbar-item @click="dailyReward()" v-if="$store.state.koins"><b>
{{$store.state.koins}} Koins
</b></b-navbar-item>
<b-navbar-item v-if="!$store.state.koins"><b>
<i class="fas fa-circle-notch fa-spin"></i> Loading...
</b></b-navbar-item>
<b-navbar-item tag="div">
<div>
<NotificationButton></NotificationButton>
</div>
<div>
<div class="navbar-item has-dropdown is-hoverable is-info">
<a class="navbar-link">
<b>{{this.$store.state.username}}</b>
</a>
<div class="navbar-dropdown is-boxed">
<router-link class="navbar-item" :to='"/user/" + this.$store.state.username'>My Profile</router-link>
<router-link class="navbar-item" to='/settings'>Settings</router-link>
<router-link to='/admin' class="navbar-item" v-if='$store.state.admin'>Admin Panel</router-link>
<router-link class="navbar-item is-active" to='/premium'>Upgrade</router-link>
<a class="navbar-item" @click='logout'>
Log out
</a>
</div>
</div>
</div>
<search-box header-bar='true'></search-box>
</b-navbar-item>
</template>
<template slot="end" v-else>
<b-navbar-item tag="div">
<div class="buttons">
<a class="button is-info" @click="showAccountModalTab(0)">
<strong>Sign up</strong>
</a>
<a class="button is-light" @click="showAccountModalTab(1)">
Log in
</a>
</div>
</b-navbar-item>
</template>
</b-navbar>
</template>
<div v-if='$store.state.meta.bannerEnabled && $store.state.meta.bannerText && !$store.state.username' class="container is-fullhd" style="padding-left: 5px; padding-right: 5px; padding-top: 20px; padding-bottom: 5px;">
<div class="notification is-info">
{{$store.state.meta.bannerText}}
</div>
</div>
</div>
<div v-if="!$store.state.emailVerified && $store.state.username" class="container is-fullhd" style="padding-left: 5px; padding-right: 5px; padding-top: 20px; padding-bottom: 5px;">
<div class="notification is-danger">
<b>Your email is not verified.</b> You will have limited access to Kaverti until you verify your email in <router-link to="/settings/account">User Settings</router-link>
</div>
</div>
<not-found v-show='$store.state.show404Page'></not-found>
<transition name='fade'>
<router-view v-show='!$store.state.show404Page'></router-view>
</transition>
<div v-if="!$store.state.emailVerified && $store.state.username" class="container is-fullhd" style="padding-left: 5px; padding-right: 5px; padding-top: 20px; padding-bottom: 5px;">
<div class="notification is-danger">
<b>Your email is not verified.</b> You will have limited access to Kaverti until you verify your email in <router-link to="/settings/account">User Settings</router-link>
</div>
</div>
<not-found v-show='$store.state.show404Page'></not-found>
<transition name='fade'>
<router-view v-show='!$store.state.show404Page'></router-view>
</transition>
</main>
</div>
</template>
@ -328,6 +350,7 @@
import NotFound from './components/routes/NotFound'
import AjaxErrorHandler from './assets/js/errorHandler'
export default {
name: 'app',
components: {
@ -370,7 +393,7 @@
},
loadingLogout: false,
showMenu: false,
ajaxErrorHandler: AjaxErrorHandler(this.$store)
connModal: true
}
},
computed: {
@ -393,6 +416,12 @@
get () { return this.$store.state.ajaxErrorsModal },
set (val) { this.$store.commit('setAjaxErrorsModalState', val) }
},
showConnModal: {
get () { return this.$store.state.connModal },
set (val) {
this.$store.commit('setConnModal', val);
}
},
showOutLinkModal: {
get () { return this.$store.state.showOutLinkModal },
set (val) { this.$store.commit('setOutLinkModalState', val) }
@ -477,6 +506,11 @@
this.signup.errors.email = ''
this.signup.errors.passkey = ''
},
pollConn() {
this.polling = setInterval(() => {
this.retryConnection()
}, 5000)
},
clearLogin () {
this.login.username = ''
this.login.password = ''
@ -485,6 +519,50 @@
this.login.errors.username = ''
this.login.errors.hash = ''
},
retryConnection () {
this.axios.get('/api/v1/userinfo')
.then(res => {
this.$store.commit('setUsername', res.data.username)
this.$store.commit('setEmail', res.data.email)
this.$store.commit('setEmailVerified', res.data.emailVerified)
this.$store.commit('setAdmin', res.data.admin)
this.$store.commit('setKoins', res.data.koins)
this.axios.get('/api/v1/kaverti/state')
.then(res => {
this.$store.commit('setSettings', res.data)
this.$store.dispatch('setTitle', this.$store.state.meta.title)
this.closeConn()
}).catch(err => {
this.showConn()
if(err.response.data.errors[0].name === 'noSettings') {
this.showConn()
} else {
this.showConn()
}
})
})
this.axios.get('/api/v1/kaverti/state')
.then(res => {
this.$store.commit('setSettings', res.data)
this.$store.dispatch('setTitle', this.$store.state.meta.title)
this.axios.get('/api/v1/userinfo')
.then(res => {
this.$store.commit('setUsername', res.data.username)
this.$store.commit('setEmail', res.data.email)
this.$store.commit('setEmailVerified', res.data.emailVerified)
this.$store.commit('setAdmin', res.data.admin)
this.$store.commit('setKoins', res.data.koins)
this.closeConn()
}).catch(err => {
this.showConn()
if(err.response.data.errors[0].name === 'noSettings') {
this.showConn()
} else {
this.showConn()
}
})
})
},
closeAccountModal () {
this.showAccountModal = false
this.clearLogin()
@ -492,6 +570,12 @@
this.clearLoginErrors()
this.clearSignupErrors()
},
showConn () {
this.connModal = true
},
closeConn () {
this.connModal = false
},
createAccount () {
this.clearSignupErrors()
let postParams = {
@ -519,30 +603,30 @@
this.$store.commit('setAdmin', res.data.admin)
this.closeAccountModal()
this.$socket.emit('accountEvent')
this.axios
.post('/api/v1/users/email-send')
.then(() => {
this.email.loading = false
this.axios.get('/api/v1/userinfo')
.then(res => {
this.$store.commit('setUsername', res.data.username)
this.$store.commit('setEmail', res.data.email)
this.$store.commit('setEmailVerified', res.data.emailVerified)
this.$store.commit('setAdmin', res.data.admin)
this.$store.commit('setKoins', res.data.koins)
}).catch(err => {
this.axios
.post('/api/v1/users/email-send')
.then(() => {
this.email.loading = false
this.axios.get('/api/v1/userinfo')
.then(res => {
this.$store.commit('setUsername', res.data.username)
this.$store.commit('setEmail', res.data.email)
this.$store.commit('setEmailVerified', res.data.emailVerified)
this.$store.commit('setAdmin', res.data.admin)
this.$store.commit('setKoins', res.data.koins)
}).catch(err => {
this.$router.push('/connection')
if(err.response.data.errors[0].name === 'noSettings') {
this.$router.push('/connection')
if(err.response.data.errors[0].name === 'noSettings') {
this.$router.push('/connection')
} else {
this.$router.push('/connection')
}
})
})
.catch(e => {
this.email.loading = false
AjaxErrorHandler(this.$store)(e)
} else {
this.$router.push('/connection')
}
})
})
.catch(e => {
this.email.loading = false
AjaxErrorHandler(this.$store)(e)
})
}).catch(e => {
this.signup.loading = false
@ -603,19 +687,6 @@
}
},
created () {
this.axios.get('/api/v1/kaverti/state')
.then(res => {
this.$store.commit('setSettings', res.data)
this.$store.dispatch('setTitle', this.$store.state.meta.title)
}).catch(err => {
this.$router.push('/connection')
if(err.response.data.errors[0].name === 'noSettings') {
this.$router.push('/connection')
} else {
this.$router.push('/connection')
}
})
this.axios.get('/api/v1/userinfo')
.then(res => {
this.$store.commit('setUsername', res.data.username)
@ -623,12 +694,52 @@
this.$store.commit('setEmailVerified', res.data.emailVerified)
this.$store.commit('setAdmin', res.data.admin)
this.$store.commit('setKoins', res.data.koins)
this.closeConn()
}).catch(err => {
this.$router.push('/connection')
this.showConn()
this.pollConn()
if(err.response.data.errors[0].name === 'noSettings') {
this.$router.push('/connection')
this.showConn()
this.pollConn()
} else {
this.$router.push('/connection')
this.showConn()
this.pollConn()
}
})
this.axios.get('/api/v1/kaverti/state')
.then(res => {
this.$store.commit('setSettings', res.data)
this.$store.dispatch('setTitle', this.$store.state.meta.title)
this.closeConn()
this.axios.get('/api/v1/userinfo')
.then(res => {
this.$store.commit('setUsername', res.data.username)
this.$store.commit('setEmail', res.data.email)
this.$store.commit('setEmailVerified', res.data.emailVerified)
this.$store.commit('setAdmin', res.data.admin)
this.$store.commit('setKoins', res.data.koins)
this.closeConn()
}).catch(err => {
this.showConn()
this.pollConn()
if(err.response.data.errors[0].name === 'noSettings') {
this.showConn()
this.pollConn()
} else {
this.showConn()
this.pollConn()
}
})
}).catch(err => {
this.showConn()
this.pollConn()
if(err.response.data.errors[0].name === 'noSettings') {
this.showConn()
this.pollConn()
} else {
this.showConn()
this.pollConn()
}
})
@ -642,7 +753,7 @@
this.$store.dispatch('setTitle', category.name)
}
})
},
},
watch: {
$route () {
this.showMenu = false

View File

@ -15868,6 +15868,11 @@ MIT (https://github.com/Wikiki/bulma-steps/blob/master/LICENSE)
background: #167df0;
}
.tag .delete.is-booster, .tag.is-delete.is-booster, .tag.is-booster {
background: #a929d7;
}
.tag .delete.is-info:hover, .tag.is-delete.is-info:hover {
background-color: #0d64c6;
}

View File

View File

@ -0,0 +1,3 @@
module.exports = function(vuex) {
vuex.commit('setConnModal', true)
}

View File

@ -2,11 +2,6 @@
<div class='route_container user_route'>
<div class="column is-4" style="float: left">
<div class="box has-text-centered">
<div class="field" v-if="user && !user.admin && user.username == 'admin'">
<b-tooltip label="This account is not an admin account, we put this tag on accounts that contain specific keywords that could mislead users.">
<b-tag class="is-danger">Warning</b-tag>
</b-tooltip>
</div>
<div class="columns is-vcentered is-mobile">
<div class="column is-narrow"><h1 class="title">{{username}}</h1></div>
<b-tooltip v-if='user && user.system' class="is-success" label="This user is a system user operated by administrators that mainly run API operations.">
@ -41,6 +36,12 @@
:src = userPicture
>
</figure>
<br>
<div>
<b-progress type="is-info" :value="user.levelProgress" size="is-medium" show-value>
Level {{user.level}}
</b-progress>
</div>
<div class='user_description' v-if='user && user.description && user.description.length' v-html='user.description'></div>
<br>
<div v-if='user'>{{user.createdAt | formatDate('date') }}</div>

View File

@ -27,8 +27,8 @@
<b-tag rounded>&nbsp;HIDDEN&nbsp;<i class="fas fa-info-circle"></i></b-tag>
</b-tooltip>
&nbsp;
<b-tooltip v-if='user && user.booster' class="is-primary" label="User is boosting the Kaverti Discord server.">
<b-tag class="is-primary" rounded>&nbsp;BOOSTER&nbsp;<i class="fas fa-info-circle"></i></b-tag>
<b-tooltip v-if='user && user.booster' class="is-booster" label="User is boosting the Kaverti Discord server.">
<b-tag class="is-booster" rounded>&nbsp;BOOSTER&nbsp;<i class="fas fa-info-circle"></i></b-tag>
</b-tooltip>
&nbsp;
</p>
@ -43,8 +43,8 @@
<time v-bind:datetime="user.createdAt">{{user.createdAt | formatDate}}</time>
</div>
<div>
<b-progress :value="75" size="is-medium" show-value>
Level 1
<b-progress type="is-info" :value="user.levelProgress" size="is-medium" show-value>
Level {{user.level}}
</b-progress>
</div>
</div>

View File

@ -30,6 +30,7 @@ export default new Vuex.Store({
passkey: "register",
show404Page: false,
showConnModal: false,
ajaxErrors: [],
ajaxErrorsModal: false,
@ -98,6 +99,12 @@ export default new Vuex.Store({
},
setGateway(state, value) {
state.gateway = value;
},
showConnModal(state, value) {
state.connModal = value;
},
setConnModal(state, value) {
state.connModal = value
},
setAjaxErrorsModalState(state, value) {
state.ajaxErrorsModal = value;

View File

@ -0,0 +1,34 @@
module.exports = {
up(queryInterface, Sequelize) {
return Promise.all([
queryInterface.addColumn(
'users',
'level',
{
type: Sequelize.BIGINT,
default: "1"
},
),
queryInterface.addColumn(
'users',
'levelProgress',
{
type: Sequelize.BIGINT,
default: "25"
},
)
]);
},
down(queryInterface, Sequelize) {
return Promise.all([
queryInterface.removeColumn(
'users',
'level',
),
queryInterface.removeColumn(
'users',
'levelProgress',
)
]);
},
};

View File

@ -174,7 +174,16 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.STRING,
required: false
},
level: {
type: DataTypes.BIGINT,
required: true,
default: 1
},
levelProgress: {
type: DataTypes.BIGINT,
required: true,
default: 25
},
passwordResetExpiry: {
type: DataTypes.DATE,
required: false

View File

@ -440,7 +440,7 @@ router.get('/', async function(req, res) {
}
let sql = `
SELECT X.username, X.admin, X.bot, X.booster, X.description, X.koins, X.bodyColor, X.headColor, X.leftLegColor, X.rightLegColor, X.leftArmColor, X.rightArmColor, X.hidden, X.system, X.createdAt, X.contributor, X.postCount, COUNT(Threads.id) as threadCount
SELECT X.username, X.admin, X.level, X.levelProgress, X.bot, X.booster, X.description, X.koins, X.bodyColor, X.headColor, X.leftLegColor, X.rightLegColor, X.leftArmColor, X.rightArmColor, X.hidden, X.system, X.createdAt, X.contributor, X.postCount, COUNT(Threads.id) as threadCount
FROM (
SELECT Users.*, COUNT(Posts.id) as postCount
FROM Users