forked from kaverti/website
1012 lines
33 KiB
Vue
1012 lines
33 KiB
Vue
<style>
|
|
trpl-title {
|
|
font-size: 32px ;
|
|
background: -webkit-linear-gradient(#00b3ff, #007aff) ;
|
|
-webkit-background-clip: text ;
|
|
-webkit-text-fill-color: transparent ;
|
|
}
|
|
trpl-para {
|
|
background: #007aff ;
|
|
-webkit-background-clip: text ;
|
|
-webkit-text-fill-color: transparent ;
|
|
font-weight: bold ;
|
|
}
|
|
h1 {
|
|
font-size: 32px ;
|
|
}
|
|
h2 {
|
|
font-size: 24px ;
|
|
}
|
|
mini-br {
|
|
border-width: 0.1em;
|
|
}
|
|
unselectable {
|
|
-webkit-user-select: none; /* Safari */
|
|
-moz-user-select: none; /* Firefox */
|
|
-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%);
|
|
}
|
|
</style>
|
|
<template>
|
|
<div id='app'>
|
|
<main>
|
|
<modal-window v-model='showAjaxErrorsModal' style='z-index: 100' width='25rem' :no-padding='true' :is-error="true">
|
|
<div slot="header">
|
|
Oh uh!
|
|
</div>
|
|
<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 is-info'
|
|
style='z-index: 100; width: 100%;'
|
|
@click='showAjaxErrorsModal = false'
|
|
ref='ajaxErrorsModalButton'
|
|
>
|
|
Okay
|
|
</button>
|
|
</modal-window>
|
|
<b-modal :can-cancel="false" :active="connModal" @update:active="value => connModal = value" v-model="connModal" full-screen>
|
|
<div class="modal-card" style="width: auto">
|
|
<section class="vertical">
|
|
<center>
|
|
<sync-loader color="#445159" :size="20" :sizeUnit="px"></sync-loader>
|
|
<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='showAccountModal'
|
|
@input='closeAccountModal'
|
|
style="z-index: 99"
|
|
:no-padding='true'
|
|
:hide-footer='true'
|
|
:hide-header="true"
|
|
>
|
|
<tab-view
|
|
:tabs='["Register", "Login", "Recovery"]'
|
|
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'>
|
|
|
|
<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'
|
|
>
|
|
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>
|
|
|
|
<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>
|
|
|
|
<b-button style="float: right" class="is-danger-passive" @click='closeAccountModal'>
|
|
Cancel
|
|
</b-button>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
<template slot='Recovery'>
|
|
<p style='margin-top: 0;'>
|
|
{{name}} Account Recovery
|
|
</p>
|
|
<form @submit.prevent='doRecovery'>
|
|
<fancy-input
|
|
v-model='recovery.email'
|
|
:error='recovery.errors.email'
|
|
placeholder='Email'
|
|
width='100%'
|
|
>
|
|
</fancy-input>
|
|
|
|
<div style='margin-top: 0.5rem;'>
|
|
<b-button
|
|
class='is-info'
|
|
style="width: 55%"
|
|
:loading='recovery.loading'
|
|
@click='doRecovery'
|
|
>
|
|
Send email
|
|
</b-button>
|
|
|
|
<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: '/' }">
|
|
<VueSkipTo to="#main" label="Skip to main content" />
|
|
<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 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: '/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: '/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
|
|
</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>
|
|
<router-link class="navbar-item is-active" to='/jobs'>We're Hiring!</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">
|
|
<NotificationButton class="is-hidden-mobile"></NotificationButton>
|
|
<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='"/u/" + this.$store.state.username'>My Profile</router-link>
|
|
<router-link class="navbar-item" to='/settings'>Settings</router-link>
|
|
<router-link class="navbar-item is-hidden-desktop" to='/notifications'>Notifications</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.clientVersion !== $store.state.latestClientVersion' class="container is-fullhd" style="padding-left: 5px; padding-right: 5px; padding-top: 20px; padding-bottom: 5px;">
|
|
<div class="notification is-info">
|
|
You are using an outdated client, refresh to update.
|
|
</div>
|
|
</div>
|
|
<div v-if='$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 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 id="main" v-show='!$store.state.show404Page'></router-view>
|
|
</transition>
|
|
<footer class="footer">
|
|
<div class="content has-text-centered">
|
|
<p>
|
|
<strong>Kaverti</strong> by <a href="https://troplo.com">Troplo</a> and <router-link to="/contributors">Contributors</router-link>
|
|
<br/>
|
|
Be sure to read the <router-link to="/legal/tos">Terms of Service</router-link> and <router-link to="/legal/privacy">Privacy Policy</router-link>
|
|
</p>
|
|
</div>
|
|
</footer>
|
|
</main>
|
|
</div>
|
|
</template>
|
|
<style>
|
|
@import 'https://kit-pro.fontawesome.com/releases/v5.14.0/css/pro.min.css';
|
|
</style>
|
|
<style lang="scss">
|
|
$primary: #007aff ;
|
|
$navbar-dropdown-arrow: #007aff ;
|
|
</style>
|
|
<script>
|
|
import ModalWindow from './components/ModalWindow'
|
|
import TabView from './components/TabView'
|
|
import FancyInput from './components/FancyInput'
|
|
import NotificationButton from './components/NotificationButton'
|
|
import SearchBox from './components/SearchBox'
|
|
import { SyncLoader } from '@saeris/vue-spinners'
|
|
|
|
import NotFound from './components/routes/NotFound'
|
|
|
|
import AjaxErrorHandler from './assets/js/errorHandler'
|
|
export default {
|
|
name: 'app',
|
|
components: {
|
|
ModalWindow,
|
|
TabView,
|
|
FancyInput,
|
|
NotificationButton,
|
|
SearchBox,
|
|
NotFound,
|
|
SyncLoader
|
|
},
|
|
data () {
|
|
return {
|
|
kavelabelPosition: 'on-border',
|
|
signup: {
|
|
username: '',
|
|
password: '',
|
|
email: '',
|
|
confirmPassword: '',
|
|
passkey: '',
|
|
|
|
loading: false,
|
|
|
|
errors: {
|
|
username: '',
|
|
email: '',
|
|
hash: '',
|
|
confirmPassword: ''
|
|
}
|
|
},
|
|
login: {
|
|
username: '',
|
|
password: '',
|
|
|
|
loading: false,
|
|
|
|
errors: {
|
|
username: '',
|
|
hash: ''
|
|
}
|
|
},
|
|
recovery: {
|
|
email: '',
|
|
|
|
loading: false,
|
|
|
|
errors: {
|
|
email: ''
|
|
}
|
|
},
|
|
loadingLogout: false,
|
|
showMenu: false,
|
|
connModal: true,
|
|
ajaxErrorHandler: AjaxErrorHandler(this.$store)
|
|
}
|
|
},
|
|
computed: {
|
|
name () {
|
|
return this.$store.state.meta.name
|
|
},
|
|
logo () {
|
|
if(this.$store.state.meta.logo) {
|
|
this.$store.state.meta.logo
|
|
}
|
|
return "https://cdn.kaverti.com/logo.png";
|
|
},
|
|
theme () {
|
|
return this.$store.state.theme
|
|
},
|
|
showAccountModal: {
|
|
get () { return this.$store.state.accountModal },
|
|
set (val) {
|
|
this.$store.commit('setAccountModalState', val);
|
|
}
|
|
},
|
|
showAjaxErrorsModal: {
|
|
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) }
|
|
},
|
|
showAccountTab : {
|
|
get () { return this.$store.state.accountTabs },
|
|
set (index) { this.$store.commit('setAccountTabs', index) }
|
|
},
|
|
categories() {
|
|
return this.$store.state.meta.categories
|
|
}
|
|
},
|
|
methods: {
|
|
darkTheme() {
|
|
let darkThemeLinkEl = document.createElement("link");
|
|
darkThemeLinkEl.setAttribute("rel", "stylesheet");
|
|
darkThemeLinkEl.setAttribute("href", "https://cdn.kaverti.com/css/dark.css");
|
|
darkThemeLinkEl.setAttribute("id", "dark-theme");
|
|
|
|
let docHead = document.querySelector("head");
|
|
docHead.append(darkThemeLinkEl);
|
|
},
|
|
disableDarkTheme() {
|
|
let darkThemeLinkEl = document.removeElement("dark-theme");
|
|
|
|
let docHead = document.querySelector("head");
|
|
docHead.append(darkThemeLinkEl);
|
|
},
|
|
recaptcha() {
|
|
this.$recaptcha('login').then((token) => {
|
|
console.log(token) // Will print the token
|
|
})},
|
|
showAccountModalTab (index) {
|
|
this.toggleMenu()
|
|
this.showAccountModal = true
|
|
this.showAccountTab = index
|
|
},
|
|
toggleMenu () {
|
|
this.showMenu = !this.showMenu
|
|
},
|
|
dailyReward () {
|
|
this.loadingLogout = true
|
|
this.axios.get(
|
|
'/api/v1/users/reward'
|
|
|
|
).then(res => {
|
|
this.$store.commit('setKoins', res.data.koins)
|
|
}).catch(err => {
|
|
this.loadingLogout = false
|
|
this.ajaxErrorHandler(err)
|
|
})
|
|
},
|
|
logout () {
|
|
this.toggleMenu()
|
|
this.loadingLogout = true
|
|
this.axios.post(
|
|
'/api/v1/user/' +
|
|
this.$store.state.username +
|
|
'/logout'
|
|
|
|
).then(res => {
|
|
this.loadingLogout = false
|
|
this.$store.commit('setUsername', '')
|
|
this.$store.commit('setAdmin', res.data.admin)
|
|
|
|
this.$socket.emit('accountEvent')
|
|
}).catch(err => {
|
|
this.loadingLogout = false
|
|
this.ajaxErrorHandler(err)
|
|
})
|
|
},
|
|
botLogout (res) {
|
|
this.loadingLogout = false
|
|
this.$store.commit('setUsername', '')
|
|
this.$store.commit('setAdmin', res.data.admin)
|
|
|
|
this.$socket.emit('accountEvent')
|
|
|
|
this.$router.push('/')
|
|
},
|
|
clearSignup () {
|
|
this.signup.username = ''
|
|
this.signup.password = ''
|
|
this.signup.confirmPassword = ''
|
|
this.signup.email = ''
|
|
this.signup.passkey = ''
|
|
|
|
this.$store.commit('setToken', null)
|
|
this.$store.commit('setPassKey', null)
|
|
},
|
|
clearSignupErrors () {
|
|
this.signup.errors.username = ''
|
|
this.signup.errors.hash = ''
|
|
this.signup.errors.confirmPassword = ''
|
|
this.signup.errors.email = ''
|
|
this.signup.errors.passkey = ''
|
|
},
|
|
clearRecovery () {
|
|
this.recovery.email = ''
|
|
|
|
this.$store.commit('setToken', null)
|
|
this.$store.commit('setPassKey', null)
|
|
},
|
|
clearRecoveryErrors () {
|
|
this.recovery.errors.email = ''
|
|
},
|
|
pollConn() {
|
|
this.polling = setInterval(() => {
|
|
this.retryConnection()
|
|
}, 5000)
|
|
},
|
|
pollConnAlt() {
|
|
this.polling = setInterval(() => {
|
|
this.retryConnection()
|
|
}, 25000)
|
|
},
|
|
clearLogin () {
|
|
this.login.username = ''
|
|
this.login.password = ''
|
|
},
|
|
clearLoginErrors () {
|
|
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.$store.commit('setDevMode', res.data.developerMode)
|
|
this.$store.commit('setTheme', res.data.theme)
|
|
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.$store.commit('setAPIVersion', res.data.latestAPIVersion)
|
|
this.$store.commit('setLatestVersion', res.data.latestStableVersion)
|
|
this.closeConn()
|
|
}).catch(err => {
|
|
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.$store.commit('setAPIVersion', res.data.latestAPIVersion)
|
|
this.$store.commit('setLatestVersion', res.data.latestStableVersion)
|
|
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.$store.commit('setDevMode', res.data.developerMode)
|
|
this.$store.commit('setTheme', res.data.theme)
|
|
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()
|
|
this.clearSignup()
|
|
this.clearLoginErrors()
|
|
this.clearSignupErrors()
|
|
},
|
|
showConn () {
|
|
this.connModal = true
|
|
},
|
|
closeConn () {
|
|
this.connModal = false
|
|
},
|
|
createAccount () {
|
|
this.clearSignupErrors()
|
|
let postParams = {
|
|
username: this.signup.username,
|
|
password: this.signup.password,
|
|
email: this.signup.email,
|
|
passkey: this.signup.passkey
|
|
}
|
|
if(this.$store.state.token) {
|
|
postParams.admin = true
|
|
postParams.token = this.$store.state.token
|
|
}
|
|
if(this.$store.state.passkey) {
|
|
postParams.passkey = this.$store.state.passkey
|
|
}
|
|
|
|
if(this.signup.password !== this.signup.confirmPassword) {
|
|
this.signup.errors.confirmPassword = 'Passwords must match'
|
|
} else {
|
|
this.signup.loading = true
|
|
|
|
this.axios.post(`/api/v1/passkey/${this.$store.state.passkey}`, postParams).then(res => {
|
|
this.signup.loading = false
|
|
this.$store.commit('setUsername', res.data.username)
|
|
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
|
|
})
|
|
.catch(e => {
|
|
this.email.loading = false
|
|
AjaxErrorHandler(this.$store)(e)
|
|
})
|
|
}).catch(e => {
|
|
this.signup.loading = false
|
|
|
|
this.ajaxErrorHandler(e, (error) => {
|
|
let path = error.path
|
|
|
|
if(this.signup.errors[path] !== undefined && this.signup.errors[path] !== undefined) {
|
|
this.signup.errors[path] = error.message
|
|
}
|
|
})
|
|
})
|
|
}
|
|
},
|
|
doLogin () {
|
|
this.clearSignupErrors()
|
|
|
|
if(!this.login.username.trim().length) {
|
|
this.login.errors.username = 'Username must not be blank'
|
|
return
|
|
}
|
|
|
|
this.login.loading = true
|
|
|
|
this.axios.post(`/api/v1/users/login`, {
|
|
username: this.login.username,
|
|
password: this.login.password
|
|
}).then(res => {
|
|
this.login.loading = false
|
|
this.$store.commit('setUsername', res.data.username)
|
|
this.$store.commit('setAdmin', res.data.admin)
|
|
this.closeAccountModal()
|
|
this.$socket.emit('accountEvent')
|
|
|
|
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.$store.commit('setDevMode', res.data.developerMode)
|
|
this.$store.commit('setTheme', res.data.theme)
|
|
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(e => {
|
|
this.login.loading = false
|
|
this.ajaxErrorHandler(e, (error) => {
|
|
let path = error.path
|
|
|
|
if(this.signup.errors[path] !== undefined && this.signup.errors[path] !== undefined) {
|
|
this.signup.errors[path] = error.message
|
|
}
|
|
})
|
|
})
|
|
},
|
|
doRecovery () {
|
|
this.clearRecoveryErrors()
|
|
|
|
if(!this.recovery.email.trim().length) {
|
|
this.recovery.errors.email = 'Email must not be blank'
|
|
return
|
|
}
|
|
|
|
this.recovery.loading = true
|
|
|
|
this.axios.post(`/api/v1/users/recovery/send`, {
|
|
email: this.recovery.email
|
|
}).then(res => {
|
|
this.recovery.loading = false
|
|
this.$store.commit('setUsername', res.data.username)
|
|
this.$store.commit('setAdmin', res.data.admin)
|
|
this.closeAccountModal()
|
|
|
|
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.$store.commit('setDevMode', res.data.developerMode)
|
|
this.$store.commit('setTheme', res.data.theme)
|
|
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(e => {
|
|
this.recovery.loading = false
|
|
this.ajaxErrorHandler(e, (error) => {
|
|
let path = error.path
|
|
|
|
if(this.recovery.errors[path] !== undefined && this.recovery.errors[path] !== undefined) {
|
|
this.recovery.errors[path] = error.message
|
|
}
|
|
})
|
|
})
|
|
}
|
|
},
|
|
mounted () {
|
|
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.$store.commit('setDevMode', res.data.developerMode)
|
|
this.$store.commit('setTheme', res.data.theme)
|
|
this.$store.commit('setTheme', res.data.theme)
|
|
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()
|
|
}
|
|
})
|
|
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.$store.commit('setAPIVersion', res.data.latestAPIVersion)
|
|
this.$store.commit('setLatestVersion', res.data.latestStableVersion)
|
|
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.$store.commit('setTheme', res.data.theme)
|
|
if(res.data.theme === "dark") {
|
|
this.darkTheme()
|
|
}
|
|
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()
|
|
}
|
|
})
|
|
this.axios.get(
|
|
'/api/v1/users/reward'
|
|
|
|
).then(res => {
|
|
this.$store.commit('setKoins', res.data.koins)
|
|
})
|
|
}).catch(err => {
|
|
this.showConn()
|
|
this.pollConn()
|
|
if(err.response.data.errors[0].name === 'noSettings') {
|
|
this.showConn()
|
|
this.pollConn()
|
|
} else {
|
|
this.showConn()
|
|
this.pollConn()
|
|
}
|
|
})
|
|
|
|
this.axios.get('/api/v1/forums/category')
|
|
.then(res => {
|
|
this.$store.commit('addCategories', res.data)
|
|
if(!this.$store.state.meta.title.length && this.$route.params.category) {
|
|
let selectedCategory = this.$route.params.category.toUpperCase()
|
|
let category = this.categories.find(c => c.value === selectedCategory)
|
|
|
|
this.$store.dispatch('setTitle', category.name)
|
|
}
|
|
})
|
|
this.pollConnAlt()
|
|
},
|
|
watch: {
|
|
$route () {
|
|
this.showMenu = false
|
|
},
|
|
'$store.state.ajaxErrorsModal': function(val) {
|
|
if(val) {
|
|
this.$refs.ajaxErrorsModalButton.focus()
|
|
}
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
<style lang='scss'>
|
|
@import url('https://fonts.googleapis.com/css?family=Lato:400,400i,500,500i,700');
|
|
@import './assets/scss/variables.scss';
|
|
@import './assets/sass/primary';
|
|
$primary: #0ba8e6 ;
|
|
$colors: (
|
|
"primary": #0ba8e6
|
|
);
|
|
html, body {
|
|
width: 100%;
|
|
height: 100%;
|
|
margin: 0;
|
|
padding: 0;
|
|
|
|
color: $color__text--primary;
|
|
@include text;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.route_container {
|
|
width: 90%;
|
|
max-width: 1250px;
|
|
margin: 0 auto;
|
|
margin-top: 2rem;
|
|
padding-bottom: 2rem;
|
|
}
|
|
|
|
.logo {
|
|
@include text($font--role-emphasis, 2rem, 600);
|
|
@include user-select(none);
|
|
cursor: pointer;
|
|
background: none;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
max-width: 20rem;
|
|
|
|
|
|
&:hover, &:visited, &:active {
|
|
outline: none;
|
|
color: $color__text--primary;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 870px) {
|
|
.route_container {
|
|
width: calc(100% - 2rem);
|
|
margin: 0 1rem;
|
|
margin-top: 0rem;
|
|
}
|
|
|
|
.logo {
|
|
position: relative;
|
|
z-index: 2;
|
|
max-width: calc(100vw - 7rem);
|
|
}
|
|
|
|
.header__menu_button {
|
|
display: inline-block;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.header__overlay--show {
|
|
pointer-events: all;
|
|
opacity: 1;
|
|
}
|
|
|
|
.header__group:first-child {
|
|
margin-left: 1rem;
|
|
}
|
|
|
|
.header__group:nth-child(2) {
|
|
position: fixed;
|
|
padding-top: 1.5rem;
|
|
width: 17rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
z-index: 2;
|
|
background: #fff;
|
|
top: 0;
|
|
left: calc(-100% - 2rem);
|
|
height: 100%;
|
|
box-shadow: none;
|
|
transition: left 0.4s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.4s ease-in;
|
|
|
|
> .button {
|
|
width: 100%;
|
|
border-radius: 0;
|
|
margin: 0;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
&::before {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 0.3rem;
|
|
content: '';
|
|
background: linear-gradient(to right, hsl(200, 98%, 43%), hsla(193, 98%, 48%, 1));
|
|
}
|
|
}
|
|
.header__group:nth-child(2).header__group--show {
|
|
left: 0;
|
|
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.4);
|
|
}
|
|
.search_box {
|
|
margin: 0;
|
|
display: inline-block;
|
|
}
|
|
}
|
|
</style>
|