Refactored user store & moved popup logic from App to store
Cleaned up bits of all the components that use these stores. User store now focuses around keeping track of the authorization token and the response from /login. When a sucessfull login request is made we save our new token and username & admin data to the with login(). Since cookies aren't implemented yet we keep track of the auth_token to make authroized requests back to the api later. The username and admin data from within the body of the token is saved and only cleared on logout(). Since we haven't implemented cookies we persist storage with localStorage. Whenever we successfully decode and save a token body we also save the token to localStorage. This is later used by initFromLocalStorage() to hydrate the store on first page load. Popup module is for opening and closing the popup, and now moved away from a inline plugin in App entry. Now handles loading from & updating query parameters type=movie | show. The route listens checks if open every navigation and closes popup if it is.
This commit is contained in:
@@ -3,26 +3,31 @@
|
||||
<section class="not-found">
|
||||
<h1 class="not-found__title">Page Not Found</h1>
|
||||
</section>
|
||||
<seasoned-button class="button" @click="goBack">go back to previous page</seasoned-button>
|
||||
<seasoned-button class="button" @click="goBack"
|
||||
>go back to previous page</seasoned-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import store from '@/store'
|
||||
import SeasonedButton from '@/components/ui/SeasonedButton'
|
||||
import { mapActions, mapGetters } from "vuex";
|
||||
import SeasonedButton from "@/components/ui/SeasonedButton";
|
||||
|
||||
export default {
|
||||
components: { SeasonedButton },
|
||||
computed: {
|
||||
...mapGetters("popup", ["isOpen"])
|
||||
},
|
||||
methods: {
|
||||
...mapActions("popup", ["close"]),
|
||||
goBack() {
|
||||
this.$router.go(-1)
|
||||
this.$router.go(-1);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.$popup.isOpen == true)
|
||||
this.$popup.close()
|
||||
if (this.isOpen) this.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -47,7 +52,7 @@ export default {
|
||||
.not-found {
|
||||
display: flex;
|
||||
height: calc(100vh - var(--header-size));
|
||||
background: url('~assets/pulp-fiction.jpg') no-repeat 50% 50%;
|
||||
background: url("~assets/pulp-fiction.jpg") no-repeat 50% 50%;
|
||||
background-size: cover;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -1,64 +1,58 @@
|
||||
<template>
|
||||
<div class="movie-popup" @click="$popup.close()">
|
||||
<div v-if="isOpen" class="movie-popup" @click="close">
|
||||
<div class="movie-popup__box" @click.stop>
|
||||
<movie :id="id" :type="type"></movie>
|
||||
<button class="movie-popup__close" @click="$popup.close()"></button>
|
||||
<button class="movie-popup__close" @click="close"></button>
|
||||
</div>
|
||||
<i class="loader"></i>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from "vuex";
|
||||
import Movie from "./Movie";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
id: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
components: { Movie },
|
||||
computed: {
|
||||
...mapGetters("popup", ["isOpen", "id", "type"])
|
||||
},
|
||||
watch: {
|
||||
isOpen(value) {
|
||||
value
|
||||
? document.getElementsByTagName("body")[0].classList.add("no-scroll")
|
||||
: document
|
||||
.getElementsByTagName("body")[0]
|
||||
.classList.remove("no-scroll");
|
||||
}
|
||||
},
|
||||
components: { Movie },
|
||||
methods: {
|
||||
...mapActions("popup", ["close", "open"]),
|
||||
checkEventForEscapeKey(event) {
|
||||
if (event.keyCode == 27) {
|
||||
this.$popup.close();
|
||||
}
|
||||
},
|
||||
updateQueryParams(id = false) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.has("movie")) {
|
||||
params.delete("movie");
|
||||
}
|
||||
|
||||
if (id) {
|
||||
params.append("movie", id);
|
||||
}
|
||||
|
||||
window.history.replaceState(
|
||||
{},
|
||||
"search",
|
||||
`${window.location.protocol}//${window.location.hostname}${
|
||||
window.location.port ? `:${window.location.port}` : ""
|
||||
}${window.location.pathname}${
|
||||
params.toString().length ? `?${params}` : ""
|
||||
}`
|
||||
);
|
||||
if (event.keyCode == 27) this.close();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.updateQueryParams(this.id);
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
let id = null;
|
||||
let type = null;
|
||||
|
||||
if (params.has("movie")) {
|
||||
id = Number(params.get("movie"));
|
||||
type = "movie";
|
||||
} else if (params.has("show")) {
|
||||
id = Number(params.get("show"));
|
||||
type = "show";
|
||||
}
|
||||
|
||||
if (id && type) {
|
||||
this.open({ id, type });
|
||||
}
|
||||
|
||||
window.addEventListener("keyup", this.checkEventForEscapeKey);
|
||||
document.getElementsByTagName("body")[0].classList.add("no-scroll");
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.updateQueryParams();
|
||||
window.removeEventListener("keyup", this.checkEventForEscapeKey);
|
||||
document.getElementsByTagName("body")[0].classList.remove("no-scroll");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<img
|
||||
class="movie-item__img"
|
||||
ref="poster-image"
|
||||
@click="openMoviePopup(movie.id, movie.type)"
|
||||
@click="openMoviePopup"
|
||||
:alt="posterAltText"
|
||||
:data-src="poster"
|
||||
src="~assets/placeholder.png"
|
||||
@@ -27,6 +27,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from "vuex";
|
||||
import img from "../directives/v-image";
|
||||
|
||||
export default {
|
||||
@@ -101,8 +102,12 @@ export default {
|
||||
imageObserver.observe(poster);
|
||||
},
|
||||
methods: {
|
||||
openMoviePopup(id, type) {
|
||||
this.$popup.open(id, type);
|
||||
...mapActions("popup", ["open"]),
|
||||
openMoviePopup() {
|
||||
this.open({
|
||||
id: this.movie.id,
|
||||
type: this.movie.type
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<section class="profile">
|
||||
<div class="profile__content" v-if="userLoggedIn">
|
||||
<div class="profile__content" v-if="loggedIn">
|
||||
<header class="profile__header">
|
||||
<h2 class="profile__title">{{ emoji }} Welcome {{ username }}</h2>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
showActivity ? "hide activity" : "show activity"
|
||||
}}</seasoned-button>
|
||||
|
||||
<seasoned-button @click="logOut">Log out</seasoned-button>
|
||||
<seasoned-button @click="_logout">Log out</seasoned-button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<results-list v-if="results" :results="results" />
|
||||
</div>
|
||||
|
||||
<section class="not-found" v-if="!userLoggedIn">
|
||||
<section class="not-found" v-if="!loggedIn">
|
||||
<div class="not-found__content">
|
||||
<h2 class="not-found__title">Authentication Request Failed</h2>
|
||||
<router-link :to="{ name: 'signin' }" exact title="Sign in here">
|
||||
@@ -36,21 +36,19 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import storage from "@/storage";
|
||||
import store from "@/store";
|
||||
import { mapGetters, mapActions } from "vuex";
|
||||
import ListHeader from "@/components/ListHeader";
|
||||
import ResultsList from "@/components/ResultsList";
|
||||
import Settings from "@/components/Settings";
|
||||
import Activity from "@/components/ActivityPage";
|
||||
import SeasonedButton from "@/components/ui/SeasonedButton";
|
||||
|
||||
import { getEmoji, getUserRequests } from "@/api";
|
||||
import { getEmoji, getUserRequests, getSettings } from "@/api";
|
||||
|
||||
export default {
|
||||
components: { ListHeader, ResultsList, Settings, Activity, SeasonedButton },
|
||||
data() {
|
||||
return {
|
||||
userLoggedIn: "",
|
||||
emoji: "",
|
||||
results: undefined,
|
||||
totalResults: undefined,
|
||||
@@ -59,16 +57,17 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters("user", ["loggedIn", "username", "settings"]),
|
||||
resultCount() {
|
||||
if (this.results === undefined) return;
|
||||
|
||||
const loadedResults = this.results.length;
|
||||
const totalResults = this.totalResults < 10000 ? this.totalResults : "∞";
|
||||
return `${loadedResults} of ${totalResults} results`;
|
||||
},
|
||||
username: () => store.getters["userModule/username"]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions("user", ["logout", "updateSettings"]),
|
||||
toggleSettings() {
|
||||
this.showSettings = this.showSettings ? false : true;
|
||||
|
||||
@@ -98,16 +97,20 @@ export default {
|
||||
this.showActivity = this.showActivity == true ? false : true;
|
||||
this.updateQueryParams("activity", this.showActivity);
|
||||
},
|
||||
logOut() {
|
||||
this.$router.push("logout");
|
||||
_logout() {
|
||||
this.logout();
|
||||
this.$router.push("home");
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!localStorage.getItem("token")) {
|
||||
this.userLoggedIn = false;
|
||||
} else {
|
||||
this.userLoggedIn = true;
|
||||
if (!this.settings) {
|
||||
getSettings().then(resp => {
|
||||
const { settings } = resp;
|
||||
if (settings) updateSettings(settings);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.loggedIn) {
|
||||
this.showSettings = window.location.toString().includes("settings=true");
|
||||
this.showActivity = window.location.toString().includes("activity=true");
|
||||
|
||||
|
||||
@@ -1,47 +1,77 @@
|
||||
<template>
|
||||
<section class="profile">
|
||||
<div class="profile__content" v-if="userLoggedIn">
|
||||
<section class='settings'>
|
||||
<h3 class='settings__header'>Plex account</h3>
|
||||
<div class="profile__content" v-if="loggedIn">
|
||||
<section class="settings">
|
||||
<h3 class="settings__header">Plex account</h3>
|
||||
|
||||
<div v-if="!hasPlexUser">
|
||||
<span class="settings__info">Sign in to your plex account to get information about recently added movies and to see your watch history</span>
|
||||
<div v-if="!plexId">
|
||||
<span class="settings__info"
|
||||
>Sign in to your plex account to get information about recently
|
||||
added movies and to see your watch history</span
|
||||
>
|
||||
|
||||
<form class="form">
|
||||
<seasoned-input placeholder="plex username" icon="Email" :value.sync="plexUsername"/>
|
||||
<seasoned-input placeholder="plex password" icon="Keyhole" type="password"
|
||||
:value.sync="plexPassword" @submit="authenticatePlex" />
|
||||
<seasoned-input
|
||||
placeholder="plex username"
|
||||
icon="Email"
|
||||
:value.sync="plexUsername"
|
||||
/>
|
||||
<seasoned-input
|
||||
placeholder="plex password"
|
||||
icon="Keyhole"
|
||||
type="password"
|
||||
:value.sync="plexPassword"
|
||||
@submit="authenticatePlex"
|
||||
/>
|
||||
|
||||
<seasoned-button @click="authenticatePlex">link plex account</seasoned-button>
|
||||
<seasoned-button @click="authenticatePlex"
|
||||
>link plex account</seasoned-button
|
||||
>
|
||||
</form>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span class="settings__info">Awesome, your account is already authenticated with plex! Enjoy viewing your seasoned search history, plex watch history and real-time torrent download progress.</span>
|
||||
<seasoned-button @click="unauthenticatePlex">un-link plex account</seasoned-button>
|
||||
<span class="settings__info"
|
||||
>Awesome, your account is already authenticated with plex! Enjoy
|
||||
viewing your seasoned search history, plex watch history and
|
||||
real-time torrent download progress.</span
|
||||
>
|
||||
<seasoned-button @click="unauthenticatePlex"
|
||||
>un-link plex account</seasoned-button
|
||||
>
|
||||
</div>
|
||||
<seasoned-messages :messages.sync="messages" />
|
||||
|
||||
<hr class='setting__divider'>
|
||||
<hr class="setting__divider" />
|
||||
|
||||
<h3 class='settings__header'>Change password</h3>
|
||||
<h3 class="settings__header">Change password</h3>
|
||||
<form class="form">
|
||||
<seasoned-input placeholder="new password" icon="Keyhole" type="password"
|
||||
:value.sync="newPassword" />
|
||||
<seasoned-input
|
||||
placeholder="new password"
|
||||
icon="Keyhole"
|
||||
type="password"
|
||||
:value.sync="newPassword"
|
||||
/>
|
||||
|
||||
<seasoned-input placeholder="repeat new password" icon="Keyhole" type="password"
|
||||
:value.sync="newPasswordRepeat" />
|
||||
<seasoned-input
|
||||
placeholder="repeat new password"
|
||||
icon="Keyhole"
|
||||
type="password"
|
||||
:value.sync="newPasswordRepeat"
|
||||
/>
|
||||
|
||||
<seasoned-button @click="changePassword">change password</seasoned-button>
|
||||
<seasoned-button @click="changePassword"
|
||||
>change password</seasoned-button
|
||||
>
|
||||
</form>
|
||||
|
||||
<hr class='setting__divider'>
|
||||
<hr class="setting__divider" />
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="not-found" v-else>
|
||||
<div class="not-found__content">
|
||||
<h2 class="not-found__title">Authentication Request Failed</h2>
|
||||
<router-link :to="{name: 'signin'}" exact title="Sign in here">
|
||||
<router-link :to="{ name: 'signin' }" exact title="Sign in here">
|
||||
<button class="not-found__button button">Sign In</button>
|
||||
</router-link>
|
||||
</div>
|
||||
@@ -50,82 +80,68 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import store from '@/store'
|
||||
import storage from '@/storage'
|
||||
import SeasonedInput from '@/components/ui/SeasonedInput'
|
||||
import SeasonedButton from '@/components/ui/SeasonedButton'
|
||||
import SeasonedMessages from '@/components/ui/SeasonedMessages'
|
||||
import { mapGetters, mapState, mapActions } from "vuex";
|
||||
import storage from "@/storage";
|
||||
import SeasonedInput from "@/components/ui/SeasonedInput";
|
||||
import SeasonedButton from "@/components/ui/SeasonedButton";
|
||||
import SeasonedMessages from "@/components/ui/SeasonedMessages";
|
||||
|
||||
import { getSettings, updateSettings, linkPlexAccount, unlinkPlexAccount } from '@/api'
|
||||
import { linkPlexAccount, unlinkPlexAccount, getSettings } from "@/api";
|
||||
|
||||
export default {
|
||||
components: { SeasonedInput, SeasonedButton, SeasonedMessages },
|
||||
data(){
|
||||
return{
|
||||
userLoggedIn: '',
|
||||
data() {
|
||||
return {
|
||||
messages: [],
|
||||
plexUsername: null,
|
||||
plexPassword: null,
|
||||
newPassword: null,
|
||||
newPasswordRepeat: null,
|
||||
emoji: null
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasPlexUser: function() {
|
||||
return this.settings && this.settings['plex_userid']
|
||||
},
|
||||
settings: {
|
||||
get: () => {
|
||||
return store.getters['userModule/settings']
|
||||
},
|
||||
set: function(newSettings) {
|
||||
store.dispatch('userModule/setSettings', newSettings)
|
||||
}
|
||||
}
|
||||
...mapGetters("user", ["loggedIn", "plexId", "settings"])
|
||||
},
|
||||
methods: {
|
||||
setValue(l, t) {
|
||||
this[l] = t
|
||||
},
|
||||
...mapActions("user", ["login", "updateSettings"]),
|
||||
changePassword() {
|
||||
return
|
||||
return;
|
||||
},
|
||||
created() {
|
||||
if (!this.settings) {
|
||||
console.log("settings does not exists.", this.settings);
|
||||
getSettings().then(resp => {
|
||||
const { settings } = resp;
|
||||
if (settings) updateSettings(settings);
|
||||
});
|
||||
}
|
||||
},
|
||||
async authenticatePlex() {
|
||||
let username = this.plexUsername
|
||||
let password = this.plexPassword
|
||||
let username = this.plexUsername;
|
||||
let password = this.plexPassword;
|
||||
|
||||
const response = await linkPlexAccount(username, password)
|
||||
const { success, message } = await linkPlexAccount(username, password);
|
||||
|
||||
this.messages.push({
|
||||
type: response.success ? 'success' : 'error',
|
||||
title: response.success ? 'Authenticated with plex' : 'Something went wrong',
|
||||
message: response.message
|
||||
})
|
||||
|
||||
if (response.success)
|
||||
getSettings().then(settings => this.settings = settings)
|
||||
type: success ? "success" : "error",
|
||||
title: success ? "Authenticated with plex" : "Something went wrong",
|
||||
message: message
|
||||
});
|
||||
},
|
||||
async unauthenticatePlex() {
|
||||
const response = await unlinkPlexAccount()
|
||||
const response = await unlinkPlexAccount();
|
||||
|
||||
this.messages.push({
|
||||
type: response.success ? 'success' : 'error',
|
||||
title: response.success ? 'Unlinked plex account ' : 'Something went wrong',
|
||||
type: response.success ? "success" : "error",
|
||||
title: response.success
|
||||
? "Unlinked plex account "
|
||||
: "Something went wrong",
|
||||
message: response.message
|
||||
})
|
||||
|
||||
if (response.success)
|
||||
getSettings().then(settings => this.settings = settings)
|
||||
}
|
||||
},
|
||||
created(){
|
||||
const token = localStorage.getItem('token') || false;
|
||||
if (token){
|
||||
this.userLoggedIn = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -133,7 +149,7 @@ export default {
|
||||
@import "./src/scss/media-queries";
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
// DUPLICATE CODE
|
||||
@@ -142,22 +158,22 @@ a {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
&__group{
|
||||
justify-content: unset;
|
||||
&__input-icon {
|
||||
margin-top: 8px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
}
|
||||
&-input {
|
||||
padding: 10px 5px 10px 45px;
|
||||
height: 40px;
|
||||
font-size: 17px;
|
||||
width: 75%;
|
||||
@include desktop-min {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
||||
&__group {
|
||||
justify-content: unset;
|
||||
&__input-icon {
|
||||
margin-top: 8px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
}
|
||||
&-input {
|
||||
padding: 10px 5px 10px 45px;
|
||||
height: 40px;
|
||||
font-size: 17px;
|
||||
width: 75%;
|
||||
@include desktop-min {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.settings {
|
||||
@@ -167,32 +183,32 @@ a {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
&__header {
|
||||
margin: 0;
|
||||
line-height: 16px;
|
||||
color: $text-color;
|
||||
font-weight: 300;
|
||||
margin-bottom: 20px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
&__info {
|
||||
display: block;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
hr {
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-bottom: 1px solid $text-color-50;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 70px;
|
||||
margin-left: 20px;
|
||||
width: 96%;
|
||||
text-align: left;
|
||||
}
|
||||
span {
|
||||
font-weight: 200;
|
||||
size: 16px;
|
||||
}
|
||||
&__header {
|
||||
margin: 0;
|
||||
line-height: 16px;
|
||||
color: $text-color;
|
||||
font-weight: 300;
|
||||
margin-bottom: 20px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
&__info {
|
||||
display: block;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
hr {
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-bottom: 1px solid $text-color-50;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 70px;
|
||||
margin-left: 20px;
|
||||
width: 96%;
|
||||
text-align: left;
|
||||
}
|
||||
span {
|
||||
font-weight: 200;
|
||||
size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,88 +2,94 @@
|
||||
<section>
|
||||
<h1>Sign in</h1>
|
||||
|
||||
<seasoned-input placeholder="username"
|
||||
icon="Email"
|
||||
type="email"
|
||||
@enter="submit"
|
||||
:value.sync="username" />
|
||||
<seasoned-input placeholder="password" icon="Keyhole" type="password" :value.sync="password" @enter="submit"/>
|
||||
<seasoned-input
|
||||
placeholder="username"
|
||||
icon="Email"
|
||||
type="email"
|
||||
@enter="submit"
|
||||
:value.sync="username"
|
||||
/>
|
||||
<seasoned-input
|
||||
placeholder="password"
|
||||
icon="Keyhole"
|
||||
type="password"
|
||||
:value.sync="password"
|
||||
@enter="submit"
|
||||
/>
|
||||
|
||||
<seasoned-button @click="submit">sign in</seasoned-button>
|
||||
<router-link class="link" to="/register">Don't have a user? Register here</router-link>
|
||||
<router-link class="link" to="/register"
|
||||
>Don't have a user? Register here</router-link
|
||||
>
|
||||
|
||||
<seasoned-messages :messages.sync="messages"></seasoned-messages>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
import { login } from '@/api'
|
||||
import storage from '../storage'
|
||||
import SeasonedInput from '@/components/ui/SeasonedInput'
|
||||
import SeasonedButton from '@/components/ui/SeasonedButton'
|
||||
import SeasonedMessages from '@/components/ui/SeasonedMessages'
|
||||
import { parseJwt } from '@/utils'
|
||||
import { mapActions } from "vuex";
|
||||
import { login } from "@/api";
|
||||
import storage from "../storage";
|
||||
import SeasonedInput from "@/components/ui/SeasonedInput";
|
||||
import SeasonedButton from "@/components/ui/SeasonedButton";
|
||||
import SeasonedMessages from "@/components/ui/SeasonedMessages";
|
||||
|
||||
export default {
|
||||
components: { SeasonedInput, SeasonedButton, SeasonedMessages },
|
||||
data(){
|
||||
return{
|
||||
data() {
|
||||
return {
|
||||
messages: [],
|
||||
username: null,
|
||||
password: null
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
setValue(l, t) {
|
||||
this[l] = t
|
||||
},
|
||||
...mapActions("user", ["login"]),
|
||||
submit() {
|
||||
this.messages = [];
|
||||
let username = this.username;
|
||||
let password = this.password;
|
||||
let { username, password } = this;
|
||||
|
||||
if (username == null || username.length == 0) {
|
||||
this.messages.push({ type: 'error', title: 'Missing username' })
|
||||
return
|
||||
if (!username || username.length == 0) {
|
||||
this.messages.push({ type: "error", title: "Missing username" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (password == null || password.length == 0) {
|
||||
this.messages.push({ type: 'error', title: 'Missing password' })
|
||||
return
|
||||
if (!password || password.length == 0) {
|
||||
this.messages.push({ type: "error", title: "Missing password" });
|
||||
return;
|
||||
}
|
||||
|
||||
this.signin(username, password)
|
||||
this.signin(username, password);
|
||||
},
|
||||
signin(username, password) {
|
||||
login(username, password, true)
|
||||
.then(data => {
|
||||
if (data.success){
|
||||
const jwtData = parseJwt(data.token)
|
||||
localStorage.setItem('token', data.token);
|
||||
localStorage.setItem('username', jwtData['username']);
|
||||
localStorage.setItem('admin', jwtData['admin'] || false);
|
||||
|
||||
eventHub.$emit('setUserStatus');
|
||||
this.$router.push({ name: 'profile' })
|
||||
if (data.success && this.login(data.token)) {
|
||||
this.$router.push({ name: "profile" });
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.status === 401) {
|
||||
this.messages.push({ type: 'error', title: 'Access denied', message: 'Incorrect username or password' })
|
||||
}
|
||||
else {
|
||||
this.messages.push({ type: 'error', title: 'Unexpected error', message: error.message })
|
||||
this.messages.push({
|
||||
type: "error",
|
||||
title: "Access denied",
|
||||
message: "Incorrect username or password"
|
||||
});
|
||||
} else {
|
||||
this.messages.push({
|
||||
type: "error",
|
||||
title: "Unexpected error",
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
created(){
|
||||
document.title = 'Sign in' + storage.pageTitlePostfix;
|
||||
created() {
|
||||
document.title = "Sign in" + storage.pageTitlePostfix;
|
||||
storage.backTitle = document.title;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user