Add option to unlock and relock perks in the tree
This commit is contained in:
parent
a38afc2d6a
commit
9f2b21574b
|
@ -4,6 +4,7 @@ from perks import views
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('trees', views.TreeView.as_view()),
|
path('trees', views.TreeView.as_view()),
|
||||||
path('trees/<int:tree_id>', views.PerkView.as_view()),
|
path('trees/<int:tree_id>', views.PerkView.as_view()),
|
||||||
path('users/<int:user_id>', views.UserView.as_view()),
|
path('user', views.UserView.as_view()),
|
||||||
|
# path('unlock/<int:perk_id>', views.UserView.as_view()),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
from os import environ
|
from os import environ
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework import authentication # , permissions
|
from rest_framework import permissions
|
||||||
|
|
||||||
from .parser import PerkParser
|
from .parser import PerkParser
|
||||||
from .models import Perk, Tree, User
|
from .models import Perk, Tree, User
|
||||||
|
@ -23,7 +23,6 @@ if not PERKS_DIR:
|
||||||
|
|
||||||
|
|
||||||
class TreeView(APIView):
|
class TreeView(APIView):
|
||||||
authentication_classes = (authentication.TokenAuthentication,)
|
|
||||||
# permission_classes = (permissions.IsAuthenticated,)
|
# permission_classes = (permissions.IsAuthenticated,)
|
||||||
|
|
||||||
def get(self, request, format=None):
|
def get(self, request, format=None):
|
||||||
|
@ -47,7 +46,6 @@ class TreeView(APIView):
|
||||||
|
|
||||||
|
|
||||||
class PerkView(APIView):
|
class PerkView(APIView):
|
||||||
authentication_classes = (authentication.TokenAuthentication,)
|
|
||||||
# permission_classes = (permissions.IsAuthenticated,)
|
# permission_classes = (permissions.IsAuthenticated,)
|
||||||
|
|
||||||
def get(self, request, tree_id, format=None):
|
def get(self, request, tree_id, format=None):
|
||||||
|
@ -85,11 +83,29 @@ class PerkView(APIView):
|
||||||
|
|
||||||
|
|
||||||
class UserView(APIView):
|
class UserView(APIView):
|
||||||
authentication_classes = (authentication.TokenAuthentication,)
|
permission_classes = (permissions.IsAuthenticated,)
|
||||||
|
|
||||||
def get(self, request, user_id):
|
def get(self, request):
|
||||||
user = User.objects.get(id=user_id)
|
user = User.objects.get(base_user__id=request.user.id)
|
||||||
serialized_user = UserSerializer(user).data
|
serialized_user = UserSerializer(user).data
|
||||||
|
|
||||||
return Response(serialized_user)
|
return Response(serialized_user)
|
||||||
|
|
||||||
|
def patch(self, request):
|
||||||
|
user = User.objects.get(base_user__id=request.user.id)
|
||||||
|
if 'perks' in request.data:
|
||||||
|
current_perks = [perk.id for perk in user.perks.all()]
|
||||||
|
new_perks = request.data['perks']
|
||||||
|
if len(current_perks) < len(new_perks):
|
||||||
|
for perk_id in new_perks:
|
||||||
|
perk = Perk.objects.get(id=perk_id)
|
||||||
|
user.perks.add(perk)
|
||||||
|
elif len(current_perks) > len(new_perks):
|
||||||
|
removed_perks = list(set(current_perks) ^ set(new_perks))
|
||||||
|
for perk_id in removed_perks:
|
||||||
|
perk = Perk.objects.get(id=perk_id)
|
||||||
|
user.perks.remove(perk)
|
||||||
|
|
||||||
|
serialized_user = UserSerializer(user).data
|
||||||
|
return Response(serialized_user)
|
||||||
|
|
||||||
|
|
|
@ -129,8 +129,6 @@ USE_TZ = True
|
||||||
STATIC_URL = '/django-static/'
|
STATIC_URL = '/django-static/'
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
|
||||||
'PAGE_SIZE': 10,
|
|
||||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||||
'rest_framework_simplejwt.authentication.JWTAuthentication',
|
'rest_framework_simplejwt.authentication.JWTAuthentication',
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,9 +25,9 @@ from rest_framework_simplejwt.views import (
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('api/', include([
|
path('api/', include([
|
||||||
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
|
path('token', TokenObtainPairView.as_view(), name='token_obtain_pair'),
|
||||||
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
path('token/refresh', TokenRefreshView.as_view(), name='token_refresh'),
|
||||||
path('token/verify/', TokenVerifyView.as_view(), name='token_verify'),
|
path('token/verify', TokenVerifyView.as_view(), name='token_verify'),
|
||||||
path('', include('perks.urls'))
|
path('', include('perks.urls'))
|
||||||
]))
|
]))
|
||||||
]
|
]
|
||||||
|
|
|
@ -8,10 +8,9 @@
|
||||||
import Axios from 'axios';
|
import Axios from 'axios';
|
||||||
|
|
||||||
const ENDPOINTS = {
|
const ENDPOINTS = {
|
||||||
LOGIN: '/token/',
|
LOGIN: '/token',
|
||||||
VERIFY: '/token/verify/',
|
VERIFY: '/token/verify',
|
||||||
REFRESH: '/token/refresh/',
|
REFRESH: '/token/refresh',
|
||||||
USER: '/user/',
|
|
||||||
};
|
};
|
||||||
const AUTH_HEADER = 'Authorization';
|
const AUTH_HEADER = 'Authorization';
|
||||||
|
|
||||||
|
@ -24,10 +23,6 @@ export default class AuthApi {
|
||||||
return Axios.post(ENDPOINTS.LOGIN, data);
|
return Axios.post(ENDPOINTS.LOGIN, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getUser() {
|
|
||||||
return Axios.get(ENDPOINTS.USER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static signup(data) {
|
static signup(data) {
|
||||||
return Axios.post(ENDPOINTS.USER, data);
|
return Axios.post(ENDPOINTS.USER, data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import Axios from 'axios';
|
||||||
|
|
||||||
const ENDPOINTS = {
|
const ENDPOINTS = {
|
||||||
TREES: '/trees',
|
TREES: '/trees',
|
||||||
|
PERKS: '/perks',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class AuthApi {
|
export default class AuthApi {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* user.api.js
|
||||||
|
* Copyright (C) 2019 pavle <pavle.portic@tilda.center>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the BSD-3-Clause license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Axios from 'axios';
|
||||||
|
|
||||||
|
const ENDPOINTS = {
|
||||||
|
USER: '/user',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class AuthApi {
|
||||||
|
static getUser() {
|
||||||
|
return Axios.get(ENDPOINTS.USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static updatePerks(data) {
|
||||||
|
return Axios.patch(ENDPOINTS.USER, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
<v-btn
|
<v-btn
|
||||||
flat
|
flat
|
||||||
v-for="item in toolbarItems"
|
v-for="item in toolbarItems[authStatus]"
|
||||||
:key="item.text"
|
:key="item.text"
|
||||||
:to="item.to"
|
:to="item.to"
|
||||||
>
|
>
|
||||||
|
@ -38,28 +38,25 @@ export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// toolbarItems: {
|
toolbarItems: {
|
||||||
// 'loggedIn': [
|
true: [
|
||||||
// { icon: 'fas fa-code-branch ', text: 'Perk trees', path: '/trees' },
|
{ icon: 'fas fa-upload', text: 'Upload perks', to: { name: 'upload-perks' } },
|
||||||
// { icon: 'account_circle', text: 'Admin panel', path: '/admin' },
|
{ icon: 'fas fa-code-branch', text: 'Perk trees', to: { name: 'trees' } },
|
||||||
// { icon: 'exit_to_app', text: 'Logout', path: '/logout' },
|
{ icon: 'fas fa-sign-out-alt', text: 'Logout', to: { name: 'logout' } },
|
||||||
// ],
|
],
|
||||||
// 'loggedOut': [{ icon: 'lock_open', text: 'Login', path: '/login' }],
|
false: [{ icon: 'fas fa-sign-in-alt', text: 'Login', to: { name: 'login' } }],
|
||||||
// },
|
},
|
||||||
toolbarItems: [
|
|
||||||
{ icon: 'fas fa-upload', text: 'Upload perks', to: { name: 'upload-perks' } },
|
|
||||||
{ icon: 'fas fa-code-branch', text: 'Perk trees', to: { name: 'trees' } },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['token']),
|
...mapGetters(['authStatus']),
|
||||||
authStatus() {
|
|
||||||
return this.token ? 'loggedIn' : 'loggedOut';
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
AuthController.refreshToken();
|
AuthController.refreshToken().catch(() => {
|
||||||
|
if (!this.$route.meta.guest) {
|
||||||
|
this.$router.push({ name: 'index' });
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,90 +1,90 @@
|
||||||
<template>
|
<template>
|
||||||
<v-layout>
|
<v-layout>
|
||||||
<v-flex md12 lg6 offset-lg3 >
|
<v-flex md12 lg6 offset-lg3 >
|
||||||
<v-card class="signup-form-card">
|
<v-card class="signup-form-card">
|
||||||
<h3>Sign up</h3>
|
<h3>Sign up</h3>
|
||||||
<form @submit="submit">
|
<form @submit="submit">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="username"
|
v-model="username"
|
||||||
name="username"
|
label="Username"
|
||||||
label="Username"
|
type="text"
|
||||||
type="text"
|
required>
|
||||||
v-validate="'required|max:255'"
|
</v-text-field>
|
||||||
data-vv-name="username"
|
<v-text-field
|
||||||
required>
|
v-model="email"
|
||||||
</v-text-field>
|
label="Email"
|
||||||
<v-text-field
|
type="email"
|
||||||
v-model="password"
|
required>
|
||||||
name="password"
|
</v-text-field>
|
||||||
label="Password"
|
<v-text-field
|
||||||
type="password"
|
v-model="password"
|
||||||
v-validate="'required|min:8|max:20'"
|
label="Password"
|
||||||
data-vv-name="password"
|
type="password"
|
||||||
required>
|
required>
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="passwordConfirm"
|
v-model="passwordConfirm"
|
||||||
name="passwordConfirm"
|
label="Confirm password"
|
||||||
label="Confirm password"
|
type="password"
|
||||||
type="password"
|
required>
|
||||||
v-validate="'required|min:8|max:20'"
|
</v-text-field>
|
||||||
data-vv-name="passwordConfirm"
|
<p v-for="(error, index) in signupErrors"
|
||||||
required>
|
:key="index"
|
||||||
</v-text-field>
|
class="signup-errors">
|
||||||
<p v-for="(error, index) in signupErrors"
|
{{ error }}
|
||||||
:key="index"
|
</p>
|
||||||
class="signup-errors">
|
|
||||||
{{ error }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<v-btn type="submit">Signup</v-btn>
|
<v-btn type="submit">Signup</v-btn>
|
||||||
</form>
|
</form>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AuthController from '../../controllers/auth.controller';
|
import AuthController from '../../controllers/auth.controller';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'signup',
|
name: 'signup',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
email: '',
|
||||||
passwordConfirm: '',
|
password: '',
|
||||||
signupErrors: [],
|
passwordConfirm: '',
|
||||||
};
|
signupErrors: [],
|
||||||
},
|
};
|
||||||
methods: {
|
},
|
||||||
submit(event) {
|
methods: {
|
||||||
event.preventDefault();
|
submit(event) {
|
||||||
if (this.password !== this.passwordConfirm) {
|
event.preventDefault();
|
||||||
this.signupErrors.push('Лозинке нису исте');
|
if (this.password !== this.passwordConfirm) {
|
||||||
return;
|
this.signupErrors.push('Passwords do not match');
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
username: this.username,
|
username: this.username,
|
||||||
password: this.password,
|
email: this.email,
|
||||||
};
|
password: this.password,
|
||||||
AuthController.register(data).then(() => {
|
};
|
||||||
this.$router.push({ name: 'index' });
|
AuthController.register(data).then(() => {
|
||||||
}).catch((error) => {
|
this.$router.push({ name: 'index' });
|
||||||
if (error.response.status === 401) {
|
}).catch((error) => {
|
||||||
this.signupErrors.push(error.response.data);
|
if (error.response) {
|
||||||
}
|
this.signupErrors.push(error.response.data);
|
||||||
});
|
}
|
||||||
},
|
});
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
.signup-form-card
|
.signup-form-card
|
||||||
padding 2rem
|
padding 2rem
|
||||||
|
|
||||||
.login-errors
|
.login-errors
|
||||||
color red
|
color red
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -15,16 +15,32 @@
|
||||||
<v-card-title
|
<v-card-title
|
||||||
class="headline grey darken-2"
|
class="headline grey darken-2"
|
||||||
primary-title
|
primary-title
|
||||||
>{{ perk }}</v-card-title>
|
>
|
||||||
<v-card-text>{{ effect }}</v-card-text>
|
{{ selectedPerk.name }}
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
{{ selectedPerk.level }}
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>{{ selectedPerk.effect }}</v-card-text>
|
||||||
<v-divider></v-divider>
|
<v-divider></v-divider>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn
|
<v-btn
|
||||||
color="primary"
|
color="error"
|
||||||
flat
|
flat
|
||||||
@click="dialog = false"
|
@click="dialog = false"
|
||||||
>Close</v-btn>
|
>Close</v-btn>
|
||||||
|
<v-btn
|
||||||
|
v-if="canUnlock"
|
||||||
|
color="primary"
|
||||||
|
flat
|
||||||
|
@click="unlock()"
|
||||||
|
>Unlock</v-btn>
|
||||||
|
<v-btn
|
||||||
|
v-else-if="canLock"
|
||||||
|
color="warning"
|
||||||
|
flat
|
||||||
|
@click="lock()"
|
||||||
|
>Lock</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
@ -36,7 +52,8 @@ import * as d3 from 'd3';
|
||||||
import Sankey from 'd3.chart.sankey';
|
import Sankey from 'd3.chart.sankey';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import PerksController from '../controllers/perks.controller';
|
import PerkController from '../controllers/perk.controller';
|
||||||
|
import UserController from '../controllers/user.controller';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'perks',
|
name: 'perks',
|
||||||
|
@ -45,8 +62,20 @@ export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
dialog: false,
|
dialog: false,
|
||||||
perk: '',
|
selectedPerk: {
|
||||||
effect: '',
|
id: null,
|
||||||
|
name: '',
|
||||||
|
effect: '',
|
||||||
|
level: null,
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
perks: [],
|
||||||
|
base_user: {},
|
||||||
|
},
|
||||||
|
graphData: {
|
||||||
|
nodes: [],
|
||||||
|
links: [],
|
||||||
|
},
|
||||||
colorScheme: [
|
colorScheme: [
|
||||||
'#458588',
|
'#458588',
|
||||||
'#d79921',
|
'#d79921',
|
||||||
|
@ -56,6 +85,30 @@ export default {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
canUnlock() {
|
||||||
|
const isLocked = _.indexOf(this.user.perks, this.selectedPerk.id);
|
||||||
|
if (isLocked !== -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requirements = _.filter(this.graphData.links, { target: this.selectedPerk });
|
||||||
|
const requirement_ids = _.map(requirements, 'source.id');
|
||||||
|
|
||||||
|
return requirement_ids.every((req) => this.user.perks.includes(req));
|
||||||
|
},
|
||||||
|
canLock() {
|
||||||
|
const dependencies = _.filter(this.graphData.links, { source: this.selectedPerk });
|
||||||
|
const dependency_ids = _.map(dependencies, 'target.id');
|
||||||
|
const isLocked = _.indexOf(this.user.perks, this.selectedPerk.id);
|
||||||
|
let hasUnlockedDependencies = false;
|
||||||
|
if (dependencies.length !== 0) {
|
||||||
|
hasUnlockedDependencies = dependency_ids.every((req) => this.user.perks.includes(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
return !hasUnlockedDependencies && isLocked !== -1;
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
renderGraph(graphData) {
|
renderGraph(graphData) {
|
||||||
const svg = d3.select('#perktree').append('svg');
|
const svg = d3.select('#perktree').append('svg');
|
||||||
|
@ -73,21 +126,58 @@ export default {
|
||||||
return this.colorScheme[node.type];
|
return this.colorScheme[node.type];
|
||||||
})
|
})
|
||||||
.on('node:click', (node) => {
|
.on('node:click', (node) => {
|
||||||
const clicked_node = _.find(nodes, (n) => {
|
const clickedNode = _.find(nodes, (n) => {
|
||||||
return n.name === node.name;
|
return n.name === node.name;
|
||||||
});
|
});
|
||||||
if (clicked_node.effect) {
|
if (clickedNode.effect) {
|
||||||
this.perk = clicked_node.name;
|
this.selectedPerk = clickedNode;
|
||||||
this.effect = clicked_node.effect;
|
|
||||||
this.dialog = true;
|
this.dialog = true;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.draw(graphData);
|
.draw(graphData);
|
||||||
},
|
},
|
||||||
|
unlock() {
|
||||||
|
if (this.canUnlock) {
|
||||||
|
const newPerks = _.clone(this.user.perks);
|
||||||
|
newPerks.push(this.selectedPerk.id);
|
||||||
|
UserController.updatePerks(newPerks).then((response) => {
|
||||||
|
this.user = response.data;
|
||||||
|
this.markUnlockedPerks();
|
||||||
|
this.dialog = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lock() {
|
||||||
|
if (this.canLock) {
|
||||||
|
const newPerks = _.difference(this.user.perks, [this.selectedPerk.id]);
|
||||||
|
UserController.updatePerks(newPerks).then((response) => {
|
||||||
|
this.user = response.data;
|
||||||
|
this.markUnlockedPerks();
|
||||||
|
this.dialog = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
markUnlockedPerks() {
|
||||||
|
for (let i = 0; i < this.graphData.nodes.length; i++) {
|
||||||
|
const perkId = this.graphData.nodes[i].id;
|
||||||
|
const el = this.$el.querySelector(`[data-node-id="${perkId}"] rect`);
|
||||||
|
|
||||||
|
if (_.indexOf(this.user.perks, perkId) !== -1) {
|
||||||
|
el.setAttribute('style', `stroke: #d65d0e !important; stroke-width: 3px; fill: ${el.style.fill};`);
|
||||||
|
} else {
|
||||||
|
el.setAttribute('style', `fill: ${el.style.fill};`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
PerksController.getPerks(this.$route.params.tree).then((response) => {
|
PerkController.getPerks(this.$route.params.tree).then((response) => {
|
||||||
this.renderGraph(response.data);
|
this.graphData = response.data;
|
||||||
|
this.renderGraph(this.graphData);
|
||||||
|
UserController.getUser().then((response) => {
|
||||||
|
this.user = response.data;
|
||||||
|
this.markUnlockedPerks();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<script>
|
<script>
|
||||||
// import * as _ from 'lodash';
|
// import * as _ from 'lodash';
|
||||||
|
|
||||||
import PerksController from '../controllers/perks.controller';
|
import PerkController from '../controllers/perk.controller';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'trees',
|
name: 'trees',
|
||||||
|
@ -37,7 +37,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
PerksController.getTrees().then((response) => {
|
PerkController.getTrees().then((response) => {
|
||||||
this.trees = response.data;
|
this.trees = response.data;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
<script>
|
<script>
|
||||||
import UploadButton from 'vuetify-upload-button';
|
import UploadButton from 'vuetify-upload-button';
|
||||||
|
|
||||||
import PerksController from '../controllers/perks.controller';
|
import PerkController from '../controllers/perk.controller';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'admin-panel',
|
name: 'admin-panel',
|
||||||
|
@ -71,7 +71,7 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
upload(file) {
|
upload(file) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
PerksController.uploadPerks(file).then(() => {
|
PerkController.uploadPerks(file).then(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.$router.push({ name: 'trees' });
|
this.$router.push({ name: 'trees' });
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<v-container>
|
||||||
|
<h1>Dashboard</h1>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import AuthController from '../controllers/auth.controller';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Index',
|
||||||
|
components: {
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
AuthController.getUser().then((response) => {
|
||||||
|
console.log(response.data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* perks.controller.js
|
* auth.controller.js
|
||||||
* Copyright (C) 2019 pavle <pavle.portic@tilda.center>
|
* Copyright (C) 2019 pavle <pavle.portic@tilda.center>
|
||||||
*
|
*
|
||||||
* Distributed under terms of the BSD-3-Clause license.
|
* Distributed under terms of the BSD-3-Clause license.
|
||||||
|
@ -40,7 +40,7 @@ export default class AuthController {
|
||||||
static setupToken() {
|
static setupToken() {
|
||||||
const access = this.getLocalStorageToken().access;
|
const access = this.getLocalStorageToken().access;
|
||||||
AuthApi.setAuthHeader(access);
|
AuthApi.setAuthHeader(access);
|
||||||
store.commit('setToken', access);
|
store.commit('login');
|
||||||
}
|
}
|
||||||
|
|
||||||
static login(data) {
|
static login(data) {
|
||||||
|
@ -56,7 +56,7 @@ export default class AuthController {
|
||||||
|
|
||||||
static logout() {
|
static logout() {
|
||||||
this.clearLocalStorageToken();
|
this.clearLocalStorageToken();
|
||||||
store.commit('clearToken');
|
store.commit('logout');
|
||||||
AuthApi.setAuthHeader('');
|
AuthApi.setAuthHeader('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* perks.controller.js
|
* perk.controller.js
|
||||||
* Copyright (C) 2019 pavle <pavle.portic@tilda.center>
|
* Copyright (C) 2019 pavle <pavle.portic@tilda.center>
|
||||||
*
|
*
|
||||||
* Distributed under terms of the BSD-3-Clause license.
|
* Distributed under terms of the BSD-3-Clause license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import PerkApi from '../apis/perk.api';
|
import PerkApi from '../apis/perk.api';
|
||||||
// import router from '../router';
|
|
||||||
|
|
||||||
export default class PerksController {
|
export default class PerkController {
|
||||||
static getTrees() {
|
static getTrees() {
|
||||||
return PerkApi.getTrees();
|
return PerkApi.getTrees();
|
||||||
}
|
}
|
||||||
|
@ -23,3 +22,4 @@ export default class PerksController {
|
||||||
return PerkApi.uploadPerks(data);
|
return PerkApi.uploadPerks(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* user.controller.js
|
||||||
|
* Copyright (C) 2019 pavle <pavle.portic@tilda.center>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the BSD-3-Clause license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import UserApi from '../apis/user.api';
|
||||||
|
|
||||||
|
export default class AuthController {
|
||||||
|
static getUser() {
|
||||||
|
return UserApi.getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
static updatePerks(perks) {
|
||||||
|
const data = {
|
||||||
|
perks,
|
||||||
|
};
|
||||||
|
|
||||||
|
return UserApi.updatePerks(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,14 +23,14 @@ const configureHttp = () => {
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
if (error.response && error.response.status === 401) {
|
if (error.response && error.response.status === 401) {
|
||||||
// AuthController.refreshToken().catch(() => {
|
AuthController.refreshToken().catch(() => {
|
||||||
// router.push({
|
router.push({
|
||||||
// name: 'logout',
|
name: 'logout',
|
||||||
// });
|
});
|
||||||
// });
|
|
||||||
router.push({
|
|
||||||
name: 'logout',
|
|
||||||
});
|
});
|
||||||
|
// router.push({
|
||||||
|
// name: 'logout',
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
|
|
@ -68,6 +68,11 @@ const router = new Router({
|
||||||
guest: true,
|
guest: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/user',
|
||||||
|
name: 'user',
|
||||||
|
component: () => import(/* webpackChunkName: "user" */ './components/user.component'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -78,7 +83,7 @@ router.isCurrentRoute = (routeName) => {
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
if (to.name === 'logout') {
|
if (to.name === 'logout') {
|
||||||
AuthController.logout();
|
AuthController.logout();
|
||||||
return next({ name: 'login' });
|
return next({ name: 'index' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!to.meta.guest && !AuthController.getAuthStatus()) {
|
if (!to.meta.guest && !AuthController.getAuthStatus()) {
|
||||||
|
|
|
@ -11,19 +11,19 @@ import Vuex from 'vuex';
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
token: null,
|
authStatus: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
token: (state) => state.token,
|
authStatus: (state) => state.authStatus,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setToken(token) {
|
login() {
|
||||||
state.token = token;
|
state.authStatus = true;
|
||||||
},
|
},
|
||||||
clearToken() {
|
logout() {
|
||||||
state.token = '';
|
state.authStatus = false;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Reference in New Issue