HM-105. Подтянуть загрузку данных пользователя. (#47)

This commit is contained in:
Nikolay
2020-08-02 12:18:54 +03:00
committed by GitHub
parent 93171aca68
commit 3a8bf0632b
8 changed files with 134 additions and 34 deletions

View File

@ -1,5 +1,6 @@
import LocalStorageAPI from './LocalStorageAPI';
import {LOCAL_STORAGE_TYPE} from './consts';
import userInfoService from '../services/UserInfoService';
const API_NAME = 'storageServiceUITokenApi';
@ -27,6 +28,7 @@ class TokenApi {
saveTokenPair = (tokens) => {
this.localApi.createOrUpdate(tokens.refresh_token);
this.sessionApi.createOrUpdate(tokens.access_token);
userInfoService.setUserLogin();
}
/**

View File

@ -13,19 +13,23 @@
<template id="main-menu">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid d-flex">
<div class="Logo__box d-flex align-items-center">
<img src="./img/logo.svg" alt="logo" class="Logo mr-2">
<div class="MainMenu__logoBox d-flex align-items-center">
<img src="./img/logo.svg" alt="logo" class="MainMenu__logo mr-2">
<a class="h3 text-light navbar-brand text-wrap m-0">Storage Service</a>
</div>
<button class="navbar-toggler ml-auto" type="button" data-toggle="collapse" data-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<button class="navbar-toggler ml-auto" type="button" data-toggle="collapse"
data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse ml-5" id="navbarNavDropdown">
<ul class="navbar-nav"></ul>
<ul class="navbar-nav mr-auto"></ul>
<div>
<div class="MainMenu__avatar"></div>
</div>
<button type="button"
class="btn btn-outline-dark MainMenu__exitButton">Выйти</button>
</div>
<div class="Avatar"></div>
<button type="submit" class="btn btn-outline-dark text-light ml-1">Выйти</button>
</nav>
</template>
@ -405,4 +409,4 @@
</body>
</html>
</html>

View File

@ -11,10 +11,15 @@ import RouterPagesContainer from './components/router-pages-container/index';
import LogsPage from './components/logs-page/index';
import LoginPage from './components/login-page';
import authServiceApi from './api/AuthServiceAPI';
import userInfoService from './services/UserInfoService';
import {EVENTS} from './consts';
const initAppComponents = () => {
const mainMenu = new MainMenu();
mainMenu.render();
userInfoService.subscribe(EVENTS.CHANGE_USER_INFO, ({avatar}) => {
mainMenu.setAvatar(avatar);
});
const routerPagesContainer = new RouterPagesContainer(mainMenu);

View File

@ -1,40 +1,52 @@
.Logo {
.MainMenu__logo {
width: 50px;
margin: 0 20px;
}
.Logo__box {
.MainMenu__logoBox {
width: 170px;
cursor: pointer;
}
.Buttons__container {
margin: 0 20px;
display: flex;
justify-content: center;
}
.NavButton {
margin: 5px 10px;
}
.nav-item {
cursor: pointer;
}
@media (max-width: 900px){
.Buttons__container {
flex-direction: column;
align-items: center;
justify-content: center;
}
}
.Avatar {
.MainMenu__avatar {
border-radius: 50%;
background-image: url('https://d5qmjlya0ygtg.cloudfront.net/569/c5295/f9ad/47c8/96a0/66a65609b38d/original/331698.jpg');
background-repeat: no-repeat;
background-position: center;
background-origin: border-box;
width: 50px;
height: 50px;
background-size: cover;
cursor: pointer;
}
.MainMenu__exitButton {
cursor: pointer;
color: hsla(0, 0%, 100%, 0.5);
}
.MainMenu__exitButton:hover {
color: #fff;
}
.MainMenu__profileButton {
display: none;
}
@media (max-width: 991px) {
.MainMenu__profileButton {
display: block;
}
.MainMenu__exitButton {
padding-left: 0;
margin-left: 0;
}
.MainMenu__avatar {
display: none;
}
}

View File

@ -4,19 +4,25 @@ import routeService from '../../services/RouteService';
import './MainMenu.css';
import {createElement} from '../../utils/elementUtils';
import {EVENTS} from '../../consts';
import tokenApi from '../../api/TokenAPI';
export const NAV_MENU = [
{
title: 'Главная',
url: '/'
url: '/',
},
{
title: 'Список хранилищ',
url: '/api'
url: '/api',
},
{
title: 'Журнал',
url: '/logs'
url: '/logs',
},
{
title: 'Личный кабинет',
url: '/profile',
className: 'MainMenu__profileButton'
},
];
@ -27,12 +33,20 @@ class MainMenu extends Component {
super('#main-menu', document.body);
this.buttonsContainer = this.mainNode.querySelector('.navbar-nav');
this.logoBox = this.mainNode.querySelector('.Logo__box');
this.logoBox = this.mainNode.querySelector('.MainMenu__logoBox');
this.avatar = this.mainNode.querySelector('.MainMenu__avatar');
this.exitButton = this.mainNode.querySelector('.MainMenu__exitButton');
this.addEventListener(this.exitButton, 'click', this.exitApp);
this.addEventListener(this.logoBox, 'click', () => {
routeService.goTo('/');
});
this.addEventListener(this.avatar, 'click', () => {
routeService.goTo('/profile');
});
this.addSubscribe(routeService, EVENTS.ROUTE_CHANGE, (route) => {
this.menuItems.forEach(({url, link}) => {
if (route.url === url) {
@ -44,13 +58,22 @@ class MainMenu extends Component {
});
}
exitApp = () => {
tokenApi.clearTokents();
location.reload();
}
setAvatar = (url) => {
this.avatar.style.backgroundImage = `url('${url}')`;
}
render = () => {
this.menuItems = NAV_MENU.map(({url, title}) => {
this.menuItems = NAV_MENU.map(({url, title, className = ''}) => {
const li = createElement({
tagName: 'li',
parentNode: this.buttonsContainer,
options: {
className: 'nav-item',
className: `nav-item ${className}`,
},
});
const link = createElement({

View File

@ -35,6 +35,7 @@ export const EVENTS = {
ROUTE_SEARCH_CHANGE: 'routeSearchChange',
ROW_CLICK: 'rowClick',
ROW_DOUBLE_CLICK: 'rowDoubleClick',
CHANGE_USER_INFO: 'changeUserInfo',
};
export const FORM_TYPES = {

View File

@ -0,0 +1,26 @@
import usersServiceApi from '../api/UsersServiceAPI';
import tokenApi from '../api/TokenAPI';
import {parseJwt} from '../utils/jwtDecode';
import {EVENTS} from '../consts';
import EmitService from './EmitService';
class UserInfoService extends EmitService {
constructor () {
super();
this.userInfo = {
login: 'not_user',
avatar: 'https://d5qmjlya0ygtg.cloudfront.net/569/c5295/f9ad/47c8/96a0/66a65609b38d/original/331698.jpg',
};
}
setUserLogin = async () => {
const {login} = parseJwt(tokenApi.getAccessToken());
this.userInfo = await usersServiceApi.find(login);
this.next(EVENTS.CHANGE_USER_INFO, {...this.userInfo});
}
}
const userInfoService = new UserInfoService();
export default userInfoService;

27
src/utils/jwtDecode.js Normal file
View File

@ -0,0 +1,27 @@
/**
* Функция для декодирования юникод текста
*/
export const base64DecodeUnicode = (string) => {
return decodeURIComponent(
Array.prototype.map
.call(atob(string), (c) => {
return `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`;
})
.join('')
);
};
/**
* Функция декодирования jwt токена для получения времени смерти
* accessToken'a
*/
export const parseJwt = (token) => {
return JSON.parse(
base64DecodeUnicode(
token
.split('.')[1]
.replace(/-/g, '+')
.replace(/_/g, '/')
)
);
};