Compare commits
10 Commits
5d19104445
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 658c0f6267 | |||
| 2e7451e906 | |||
| e8d1adae98 | |||
| 775d503627 | |||
| cccd5e7556 | |||
| 4774d6959c | |||
| f70de4f43d | |||
| 00a2c29a09 | |||
| 39a5e29781 | |||
| 966febc7b5 |
@ -58,10 +58,11 @@
|
|||||||
"webpack-dev-server": "^3.11.0"
|
"webpack-dev-server": "^3.11.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@popperjs/core": "^2.9.2",
|
||||||
|
"ace-builds": "^1.4.12",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"bootstrap": "^5.0.0-alpha1",
|
"bootstrap": "^5.0.0-alpha1",
|
||||||
"moment": "^2.27.0",
|
"moment": "^2.27.0",
|
||||||
"popper.js": "^1.16.1",
|
|
||||||
"query-string": "^6.13.1",
|
"query-string": "^6.13.1",
|
||||||
"uuid": "^8.2.0"
|
"uuid": "^8.2.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import http from './HttpAPI';
|
import http from './HttpAPI';
|
||||||
|
|
||||||
const ROOT_URL = 'http://api.auth.vigdorov.ru/users';
|
const ROOT_URL = 'https://api.auth.vigdorov.ru/users';
|
||||||
|
|
||||||
const profileServiceApi = {
|
const profileServiceApi = {
|
||||||
getSelfInfo: async () => {
|
getSelfInfo: async () => {
|
||||||
|
|||||||
@ -10,11 +10,11 @@ export const API_NAME_HEADER = 'api-name';
|
|||||||
|
|
||||||
export const API_OPTIONS = {
|
export const API_OPTIONS = {
|
||||||
[API_NAMES.PRODUCTION]: {
|
[API_NAMES.PRODUCTION]: {
|
||||||
url: 'http://api.storage.vigdorov.ru',
|
url: 'https://api.storage.vigdorov.ru',
|
||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
[API_NAMES.TESTING]: {
|
[API_NAMES.TESTING]: {
|
||||||
url: 'http://api.storage.vigdorov.ru',
|
url: 'https://api.storage.vigdorov.ru',
|
||||||
options: {
|
options: {
|
||||||
headers: {
|
headers: {
|
||||||
'Api-Name': 'store-service-test',
|
'Api-Name': 'store-service-test',
|
||||||
@ -22,7 +22,7 @@ export const API_OPTIONS = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
[API_NAMES.DEVELOP]: {
|
[API_NAMES.DEVELOP]: {
|
||||||
url: 'http://localhost:4001',
|
url: 'https://localhost:4001',
|
||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -34,7 +34,7 @@ export const ENDPOINTS = {
|
|||||||
HOOKS: '/hooks',
|
HOOKS: '/hooks',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AUTH_SERVICE = 'http://api.auth.vigdorov.ru';
|
export const AUTH_SERVICE = 'https://api.auth.vigdorov.ru';
|
||||||
|
|
||||||
export const AUTH_ENDPOINTS = {
|
export const AUTH_ENDPOINTS = {
|
||||||
AUTH: '/auth',
|
AUTH: '/auth',
|
||||||
|
|||||||
26
src/app.html
26
src/app.html
@ -32,6 +32,26 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- Шаблон для CodeEditor -->
|
||||||
|
<template id="code-editor">
|
||||||
|
<div class="CodeEditor">
|
||||||
|
<div class="CodeEditor__editor form-control"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Шаблон для FormCodeEditor -->
|
||||||
|
<template id="form-code-editor">
|
||||||
|
<div class="mb-3 FormCodeEditor">
|
||||||
|
<label class="form-label">
|
||||||
|
<span class="FormCodeEditor__label"></span>
|
||||||
|
<span class="FormCodeEditor__star text-danger"></span>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="FormCodeEditor__input" />
|
||||||
|
<div class="FormCodeEditor__editor"></div>
|
||||||
|
<div class="FormCodeEditor__errorText form-text invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- Шаблон карточек на главной-->
|
<!-- Шаблон карточек на главной-->
|
||||||
<template id="main-statistic">
|
<template id="main-statistic">
|
||||||
<div class="h-100">
|
<div class="h-100">
|
||||||
@ -81,10 +101,6 @@
|
|||||||
<div class="Login__title h3"></div>
|
<div class="Login__title h3"></div>
|
||||||
<form class="Login__form needs-validation" novalidate>
|
<form class="Login__form needs-validation" novalidate>
|
||||||
<div class="Login__inputContainer"></div>
|
<div class="Login__inputContainer"></div>
|
||||||
<div class="form-group form-check Login__check">
|
|
||||||
<input type="checkbox" class="form-check-input" id="check">
|
|
||||||
<label class="form-check-label" for="check">Оставаться в системе</label>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary Login__submit">Войти</button>
|
<button type="submit" class="btn btn-primary Login__submit">Войти</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -472,7 +488,7 @@
|
|||||||
|
|
||||||
<!-- Шаблон для Модального Сайдбара -->
|
<!-- Шаблон для Модального Сайдбара -->
|
||||||
<template id="modal-sidebar">
|
<template id="modal-sidebar">
|
||||||
<div class="ModalSidebar row justify-content-end m-0">
|
<div class="ModalSidebar row justify-content-end m-0 invisible">
|
||||||
<div class="ModalSidebar__window col-12 col-md-9 col-lg-8 col-xl-7 p-0">
|
<div class="ModalSidebar__window col-12 col-md-9 col-lg-8 col-xl-7 p-0">
|
||||||
<button class="ModalSidebar__close d-flex justify-center align-items-center" type="button">
|
<button class="ModalSidebar__close d-flex justify-center align-items-center" type="button">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import authServiceApi from './api/AuthServiceAPI';
|
|||||||
import userInfoService from './services/UserInfoService';
|
import userInfoService from './services/UserInfoService';
|
||||||
import {EVENTS, ROUTES} from './core/consts';
|
import {EVENTS, ROUTES} from './core/consts';
|
||||||
import UsersPage from './pages/users/components/page/Page';
|
import UsersPage from './pages/users/components/page/Page';
|
||||||
|
import {DocumentationPage} from './pages/documentation/components/page/Page';
|
||||||
|
|
||||||
const initAppComponents = () => {
|
const initAppComponents = () => {
|
||||||
const mainMenu = new MainMenu();
|
const mainMenu = new MainMenu();
|
||||||
@ -36,10 +37,11 @@ const initAppComponents = () => {
|
|||||||
routerPagesContainer.addRoutes([
|
routerPagesContainer.addRoutes([
|
||||||
{url: ROUTES.MAIN, pageComponent: MainPage},
|
{url: ROUTES.MAIN, pageComponent: MainPage},
|
||||||
{url: ROUTES.STORE, pageComponent: ApiPage},
|
{url: ROUTES.STORE, pageComponent: ApiPage},
|
||||||
{url: ROUTES.LOGS, pageComponent: LogsPage},
|
{url: ROUTES.LOGS, pageComponent: LogsPage, onlyAdmin: true},
|
||||||
{url: ROUTES.USERS, pageComponent: UsersPage},
|
{url: ROUTES.USERS, pageComponent: UsersPage},
|
||||||
{url: ROUTES.LOGIN, pageComponent: LoginPage},
|
{url: ROUTES.LOGIN, pageComponent: LoginPage},
|
||||||
{url: ROUTES.PROFILE, pageComponent: ProfilePage},
|
{url: ROUTES.PROFILE, pageComponent: ProfilePage},
|
||||||
|
{url: ROUTES.DOCUMENTATION, pageComponent: DocumentationPage},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
7
src/core/components/code-editor/CodeEditor.css
Normal file
7
src/core/components/code-editor/CodeEditor.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.CodeEditor__editor {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeEditor__editor_disabled {
|
||||||
|
background-color: #e9ecefa6;
|
||||||
|
}
|
||||||
45
src/core/components/code-editor/CodeEditor.js
Normal file
45
src/core/components/code-editor/CodeEditor.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import ace from 'ace-builds/src-noconflict/ace';
|
||||||
|
import theme from 'ace-builds/src-noconflict/theme-github';
|
||||||
|
import {Mode as JSONMode} from 'ace-builds/src-noconflict/mode-json';
|
||||||
|
import Component from '../component/Component';
|
||||||
|
import {CODE_EDITOR_MODE} from '../../consts';
|
||||||
|
import './CodeEditor.css';
|
||||||
|
|
||||||
|
const Modes = {
|
||||||
|
[CODE_EDITOR_MODE.JSON]: JSONMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class CodeEditor extends Component {
|
||||||
|
constructor ({
|
||||||
|
parentNode,
|
||||||
|
id,
|
||||||
|
mode,
|
||||||
|
rows = 5,
|
||||||
|
} = {}) {
|
||||||
|
super('#code-editor', parentNode);
|
||||||
|
|
||||||
|
this.editorContainer = this.mainNode.querySelector('.CodeEditor__editor');
|
||||||
|
this.editorContainer.setAttribute('id', id);
|
||||||
|
|
||||||
|
this.editorContainer.style.minHeight = `${Math.round(rows * 24.33)}px`;
|
||||||
|
|
||||||
|
this.editor = ace.edit(id);
|
||||||
|
this.editor.session.setMode(new Modes[mode]());
|
||||||
|
|
||||||
|
this.editor.setTheme(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue = (value) => {
|
||||||
|
this.editor.session.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue = () => {
|
||||||
|
return this.editor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
disabled = (value) => {
|
||||||
|
const method = value ? 'add' : 'remove';
|
||||||
|
this.editorContainer.classList[method]('CodeEditor__editor_disabled');
|
||||||
|
this.editor.setReadOnly(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/core/components/form-code-editor/FormCodeEditor.css
Normal file
13
src/core/components/form-code-editor/FormCodeEditor.css
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.FormCodeEditor {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FormCodeEditor__input {
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FormCodeEditor__input:invalid + .FormCodeEditor__editor {
|
||||||
|
border: 1px solid var(--bs-red);
|
||||||
|
border-radius: .25rem;
|
||||||
|
}
|
||||||
69
src/core/components/form-code-editor/FormCodeEditor.js
Normal file
69
src/core/components/form-code-editor/FormCodeEditor.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import Component from '../component/Component';
|
||||||
|
import {CodeEditor} from '../code-editor/CodeEditor';
|
||||||
|
import './FormCodeEditor.css';
|
||||||
|
import {EVENTS} from '../../consts';
|
||||||
|
|
||||||
|
export class FormCodeEditor extends Component {
|
||||||
|
constructor (parentNode, {
|
||||||
|
id,
|
||||||
|
mode,
|
||||||
|
label,
|
||||||
|
required = false,
|
||||||
|
initValue = '',
|
||||||
|
className = '',
|
||||||
|
rows,
|
||||||
|
} = {}) {
|
||||||
|
super('#form-code-editor', parentNode);
|
||||||
|
|
||||||
|
this.label = this.mainNode.querySelector('.form-label');
|
||||||
|
this.labelText = this.mainNode.querySelector('.FormCodeEditor__label');
|
||||||
|
this.star = this.mainNode.querySelector('.FormCodeEditor__star');
|
||||||
|
this.editorContainer = this.mainNode.querySelector('.FormCodeEditor__editor');
|
||||||
|
this.errorText = this.mainNode.querySelector('.FormCodeEditor__errorText');
|
||||||
|
this.input = this.mainNode.querySelector('.FormCodeEditor__input');
|
||||||
|
|
||||||
|
this.addEventListener(this.editorContainer, EVENTS.CLICK, this.clearError);
|
||||||
|
this.addEventListener(this.editorContainer, EVENTS.KEYDOWN, this.clearError);
|
||||||
|
|
||||||
|
this.labelText.textContent = label;
|
||||||
|
|
||||||
|
this.editor = this.createComponent(CodeEditor, {
|
||||||
|
parentNode: this.editorContainer,
|
||||||
|
id,
|
||||||
|
mode,
|
||||||
|
rows,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (className) {
|
||||||
|
this.editorContainer.classList.add(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (required) {
|
||||||
|
this.star.textContent = ' *';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setValue(initValue);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
disabled = (value) => {
|
||||||
|
this.editor.disabled(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue = () => {
|
||||||
|
return this.editor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue = (value) => {
|
||||||
|
this.editor.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
setError = (errorMessage) => {
|
||||||
|
this.errorText.textContent = errorMessage;
|
||||||
|
this.input.setCustomValidity(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearError = () => {
|
||||||
|
this.setError('');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -88,7 +88,7 @@ class FormControl extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearError = () => {
|
clearError = () => {
|
||||||
this.errorText.textContent = '';
|
this.setError('');
|
||||||
}
|
}
|
||||||
|
|
||||||
getInputTagName = (type) => {
|
getInputTagName = (type) => {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import routeService from '../../../services/RouteService';
|
|||||||
import './MainMenu.css';
|
import './MainMenu.css';
|
||||||
import {EVENTS, ROUTES, TAG_NAME} from '../../consts';
|
import {EVENTS, ROUTES, TAG_NAME} from '../../consts';
|
||||||
import tokenApi from '../../../api/TokenAPI';
|
import tokenApi from '../../../api/TokenAPI';
|
||||||
|
import userInfoService from '../../../services/UserInfoService';
|
||||||
|
|
||||||
const NAV_MENU = [
|
const NAV_MENU = [
|
||||||
{
|
{
|
||||||
@ -17,11 +18,16 @@ const NAV_MENU = [
|
|||||||
{
|
{
|
||||||
title: 'Журнал',
|
title: 'Журнал',
|
||||||
url: ROUTES.LOGS,
|
url: ROUTES.LOGS,
|
||||||
|
onlyAdmin: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Пользователи',
|
title: 'Пользователи',
|
||||||
url: ROUTES.USERS,
|
url: ROUTES.USERS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Документация',
|
||||||
|
url: ROUTES.DOCUMENTATION,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Личный кабинет',
|
title: 'Личный кабинет',
|
||||||
url: ROUTES.PROFILE,
|
url: ROUTES.PROFILE,
|
||||||
@ -72,7 +78,7 @@ class MainMenu extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render = () => {
|
render = () => {
|
||||||
this.menuItems = NAV_MENU.map(({url, title, className = ''}) => {
|
this.menuItems = NAV_MENU.map(({url, title, className = '', onlyAdmin}) => {
|
||||||
const li = this.createElement({
|
const li = this.createElement({
|
||||||
tagName: TAG_NAME.LI,
|
tagName: TAG_NAME.LI,
|
||||||
parentNode: this.buttonsContainer,
|
parentNode: this.buttonsContainer,
|
||||||
@ -95,7 +101,7 @@ class MainMenu extends Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return {url, link};
|
return {url, li, link, onlyAdmin};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +113,12 @@ class MainMenu extends Component {
|
|||||||
this.mainNode.remove();
|
this.mainNode.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
showMenu = () => {
|
showMenu = async () => {
|
||||||
|
const {is_admin} = await userInfoService.getUserInfo();
|
||||||
|
this.menuItems.forEach(({li, onlyAdmin}) => {
|
||||||
|
const isShow = !onlyAdmin || is_admin;
|
||||||
|
li.style.display = isShow ? 'list-item' : 'none';
|
||||||
|
});
|
||||||
document.body.prepend(this.mainNode);
|
document.body.prepend(this.mainNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const HIDE_SHADOW_CLASS = 'ModalSidebar__shadow_hide';
|
|||||||
const SHADOW_CLASS = 'ModalSidebar__shadow';
|
const SHADOW_CLASS = 'ModalSidebar__shadow';
|
||||||
const CROSS_BUTTON_CLASS = 'ModalSidebar__close';
|
const CROSS_BUTTON_CLASS = 'ModalSidebar__close';
|
||||||
const WINDOW_CLASS = 'ModalSidebar__window';
|
const WINDOW_CLASS = 'ModalSidebar__window';
|
||||||
|
const WINDOW_INIT_CLASS = 'invisible';
|
||||||
class ModalSidebar extends Component {
|
class ModalSidebar extends Component {
|
||||||
constructor ({
|
constructor ({
|
||||||
content,
|
content,
|
||||||
@ -56,6 +56,7 @@ class ModalSidebar extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
show = () => {
|
show = () => {
|
||||||
|
this.mainNode.classList.remove(WINDOW_INIT_CLASS);
|
||||||
this.mainNode.classList.add(SHOW_WINDOW_CLASS);
|
this.mainNode.classList.add(SHOW_WINDOW_CLASS);
|
||||||
this.shadow.classList.add(SHOW_SHADOW_CLASS);
|
this.shadow.classList.add(SHOW_SHADOW_CLASS);
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import routeService from '../../../services/RouteService';
|
|||||||
import NotFoundPage from '../../../pages/not-found/components/page/Page';
|
import NotFoundPage from '../../../pages/not-found/components/page/Page';
|
||||||
|
|
||||||
import {EVENTS, ROUTES} from '../../consts';
|
import {EVENTS, ROUTES} from '../../consts';
|
||||||
|
import userInfoService from '../../../services/UserInfoService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @interface Route
|
* @interface Route
|
||||||
@ -59,6 +60,14 @@ class RouterPagesContainer extends Component {
|
|||||||
this.currentPage = new PageComponent('#page', this.mainNode);
|
this.currentPage = new PageComponent('#page', this.mainNode);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.addSubscribe(userInfoService, EVENTS.CHANGE_USER_INFO, ({is_admin}) => {
|
||||||
|
const {url} = routeService.getUrlData();
|
||||||
|
const currentRoute = this.routes.find((route) => route.url === url);
|
||||||
|
if (currentRoute.onlyAdmin && !is_admin) {
|
||||||
|
routeService.goTo(ROUTES.MAIN);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -69,4 +69,9 @@ export const ROUTES = {
|
|||||||
USERS: '/users',
|
USERS: '/users',
|
||||||
LOGIN: '/login',
|
LOGIN: '/login',
|
||||||
PROFILE: '/profile',
|
PROFILE: '/profile',
|
||||||
|
DOCUMENTATION: '/documentation',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CODE_EDITOR_MODE = {
|
||||||
|
JSON: 'json',
|
||||||
};
|
};
|
||||||
|
|||||||
16
src/pages/documentation/components/page/Page.js
Normal file
16
src/pages/documentation/components/page/Page.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import Component from '../../../../core/components/component/Component';
|
||||||
|
import {TAG_NAME} from '../../../../core/consts';
|
||||||
|
|
||||||
|
export class DocumentationPage extends Component {
|
||||||
|
constructor (mainNodeSelector, parentNode) {
|
||||||
|
super(mainNodeSelector, parentNode);
|
||||||
|
|
||||||
|
this.createElement({
|
||||||
|
tagName: TAG_NAME.DIV,
|
||||||
|
parentNode: this.mainNode,
|
||||||
|
options: {
|
||||||
|
textContent: 'Документация',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,7 +11,6 @@ class LoginForm extends Component {
|
|||||||
this.form = this.mainNode.querySelector('.Login__form');
|
this.form = this.mainNode.querySelector('.Login__form');
|
||||||
this.inputContainer = this.mainNode.querySelector('.Login__inputContainer');
|
this.inputContainer = this.mainNode.querySelector('.Login__inputContainer');
|
||||||
this.submitButton = this.mainNode.querySelector('.Login__submit');
|
this.submitButton = this.mainNode.querySelector('.Login__submit');
|
||||||
this.checkboxSystem = this.mainNode.querySelector('.form-check-input');
|
|
||||||
this.logoImage = this.mainNode.querySelector('.Login__logo');
|
this.logoImage = this.mainNode.querySelector('.Login__logo');
|
||||||
this.logoImage.src = Image;
|
this.logoImage.src = Image;
|
||||||
|
|
||||||
@ -39,7 +38,6 @@ class LoginForm extends Component {
|
|||||||
this.loginControl.input,
|
this.loginControl.input,
|
||||||
this.passwordControl.input,
|
this.passwordControl.input,
|
||||||
this.submitButton,
|
this.submitButton,
|
||||||
this.checkboxSystem,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
elements.forEach((element) => {
|
elements.forEach((element) => {
|
||||||
@ -61,6 +59,11 @@ class LoginForm extends Component {
|
|||||||
return this.form.checkValidity();
|
return this.form.checkValidity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setError = (message) => {
|
||||||
|
this.loginControl.setError(message);
|
||||||
|
this.passwordControl.setError(message);
|
||||||
|
}
|
||||||
|
|
||||||
submit = (event) => {
|
submit = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (this.validateInputs()) {
|
if (this.validateInputs()) {
|
||||||
|
|||||||
@ -6,6 +6,11 @@ import routeService from '../../../../services/RouteService';
|
|||||||
import notify from '../../../../services/NotifyService';
|
import notify from '../../../../services/NotifyService';
|
||||||
import {ROUTES, EVENTS} from '../../../../core/consts';
|
import {ROUTES, EVENTS} from '../../../../core/consts';
|
||||||
|
|
||||||
|
const ERRORS = {
|
||||||
|
NOT_CORRECT: 'Неверный логин или пароль',
|
||||||
|
UNKNOWN_ERROR: 'Неизвестная ошибка',
|
||||||
|
};
|
||||||
|
|
||||||
class LoginPage extends Component {
|
class LoginPage extends Component {
|
||||||
constructor (mainNodeSelector, parentNode) {
|
constructor (mainNodeSelector, parentNode) {
|
||||||
super(mainNodeSelector, parentNode);
|
super(mainNodeSelector, parentNode);
|
||||||
@ -21,8 +26,12 @@ class LoginPage extends Component {
|
|||||||
routeService.goTo(ROUTES.MAIN);
|
routeService.goTo(ROUTES.MAIN);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
const message = e?.response?.data?.message || 'Неизвестная ошибка';
|
const message = e?.response?.data?.message || ERRORS.UNKNOWN_ERROR;
|
||||||
notify.warn(message);
|
if (message === ERRORS.NOT_CORRECT) {
|
||||||
|
this.form.setError(ERRORS.NOT_CORRECT);
|
||||||
|
} else {
|
||||||
|
notify.warn(message);
|
||||||
|
}
|
||||||
this.form.disabled(false);
|
this.form.disabled(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Component from '../../../../core/components/component/Component';
|
import Component from '../../../../core/components/component/Component';
|
||||||
import FormControl from '../../../../core/components/form-control/FormControl';
|
import FormControl from '../../../../core/components/form-control/FormControl';
|
||||||
import {FORM_TYPES, EVENTS} from '../../../../core/consts';
|
import {FORM_TYPES, EVENTS} from '../../../../core/consts';
|
||||||
import {INPUT_IDS, LABELS} from './consts';
|
import {INPUT_IDS, LABELS, ERRORS} from './consts';
|
||||||
import notify from '../../../../services/NotifyService';
|
import notify from '../../../../services/NotifyService';
|
||||||
import profileServiceApi from '../../../../api/ProfileServiceAPI';
|
import profileServiceApi from '../../../../api/ProfileServiceAPI';
|
||||||
|
|
||||||
@ -48,21 +48,22 @@ class ProfileContent extends Component {
|
|||||||
const newPasswordRepeat = this.newPasswordRepeat.getValue();
|
const newPasswordRepeat = this.newPasswordRepeat.getValue();
|
||||||
|
|
||||||
if (!oldPassword) {
|
if (!oldPassword) {
|
||||||
this.oldPassword.setError('Заполните старый пароль');
|
this.oldPassword.setError(ERRORS.TYPED_OLD_PASSWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newPassword) {
|
if (!newPassword) {
|
||||||
this.newPassword.setError('Заполните новый пароль');
|
this.newPassword.setError(ERRORS.TYPED_NEW_PASSWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isEqualPassword = newPassword === newPasswordRepeat;
|
const isEqualPassword = newPassword === newPasswordRepeat;
|
||||||
|
|
||||||
if (!isEqualPassword) {
|
if (!isEqualPassword) {
|
||||||
notify.warn('Пароли не совпадают');
|
this.newPassword.setError(ERRORS.PASSWORD_NOT_EQUAL);
|
||||||
|
this.newPasswordRepeat.setError(ERRORS.PASSWORD_NOT_EQUAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newPasswordRepeat) {
|
if (!newPasswordRepeat) {
|
||||||
this.newPasswordRepeat.setError('Повторите новый пароль');
|
this.newPasswordRepeat.setError(ERRORS.REPEAT_PASSWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.form.checkValidity() && isEqualPassword;
|
return this.form.checkValidity() && isEqualPassword;
|
||||||
@ -80,9 +81,16 @@ class ProfileContent extends Component {
|
|||||||
if (this.validateInputs()) {
|
if (this.validateInputs()) {
|
||||||
const oldPassword = this.oldPassword.getValue();
|
const oldPassword = this.oldPassword.getValue();
|
||||||
const newPassword = this.newPassword.getValue();
|
const newPassword = this.newPassword.getValue();
|
||||||
await profileServiceApi.changePassword(oldPassword, newPassword);
|
try {
|
||||||
|
await profileServiceApi.changePassword(oldPassword, newPassword);
|
||||||
|
} catch (e) {
|
||||||
|
if (e?.response?.data?.message === ERRORS.NOT_CORRECT_PASSWORD) {
|
||||||
|
this.oldPassword.setError(ERRORS.NOT_CORRECT_PASSWORD);
|
||||||
|
}
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
this.clearForm();
|
this.clearForm();
|
||||||
notify.success('Пароль успешно изменен');
|
notify.success(LABELS.SUCCESS_CHANGE_PASSWORD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,4 +11,13 @@ export const LABELS = {
|
|||||||
OLD_PASSWORD_PLACEHOLDER: 'Введите старый пароль',
|
OLD_PASSWORD_PLACEHOLDER: 'Введите старый пароль',
|
||||||
NEW_PASSWORD_PLACEHOLDER: 'Введите новый пароль',
|
NEW_PASSWORD_PLACEHOLDER: 'Введите новый пароль',
|
||||||
NEW_PASSWORD_REPEAT_PLACEHOLDER: 'Введите новый пароль еще раз',
|
NEW_PASSWORD_REPEAT_PLACEHOLDER: 'Введите новый пароль еще раз',
|
||||||
|
SUCCESS_CHANGE_PASSWORD: 'Пароль изменен',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ERRORS = {
|
||||||
|
TYPED_OLD_PASSWORD: 'Заполните старый пароль',
|
||||||
|
TYPED_NEW_PASSWORD: 'Заполните новый пароль',
|
||||||
|
PASSWORD_NOT_EQUAL: 'Пароли не совпадают',
|
||||||
|
REPEAT_PASSWORD: 'Повторите новый пароль',
|
||||||
|
NOT_CORRECT_PASSWORD: 'Неверный старый пароль',
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
.Api__value-input {
|
|
||||||
height: 200px;
|
|
||||||
}
|
|
||||||
.Api__view-controls {
|
.Api__view-controls {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
import Component from '../../../../core/components/component/Component';
|
import Component from '../../../../core/components/component/Component';
|
||||||
import ModalSidebar from '../../../../core/components/modal-sidebar/ModalSibebar';
|
import ModalSidebar from '../../../../core/components/modal-sidebar/ModalSibebar';
|
||||||
import FormControl from '../../../../core/components/form-control/FormControl';
|
import FormControl from '../../../../core/components/form-control/FormControl';
|
||||||
import {FORM_TYPES, EVENTS, MODES} from '../../../../core/consts';
|
import {EVENTS, MODES, CODE_EDITOR_MODE, FORM_TYPES} from '../../../../core/consts';
|
||||||
import './ApiTableViewForm.css';
|
import './ApiTableViewForm.css';
|
||||||
import storageApi from '../../api/StorageServiceAPI';
|
import storageApi from '../../api/StorageServiceAPI';
|
||||||
import routeService from '../../../../services/RouteService';
|
import routeService from '../../../../services/RouteService';
|
||||||
import {HooksComponent} from '../hooks-component/HooksComponent';
|
import {HooksComponent} from '../hooks-component/HooksComponent';
|
||||||
|
import {FormCodeEditor} from '../../../../core/components/form-code-editor/FormCodeEditor';
|
||||||
|
import userInfoService from '../../../../services/UserInfoService';
|
||||||
|
import usersServiceApi from '../../../users/api/UsersServiceAPI';
|
||||||
|
|
||||||
const TITLE_MODES = {
|
const TITLE_MODES = {
|
||||||
[MODES.Create]: 'Создание нового хранилища',
|
[MODES.Create]: 'Создание нового хранилища',
|
||||||
@ -30,37 +33,6 @@ class ApiTableViewForm extends Component {
|
|||||||
|
|
||||||
this.title.textContent = 'Информация о хранилище';
|
this.title.textContent = 'Информация о хранилище';
|
||||||
|
|
||||||
this.inputs = [
|
|
||||||
this.keyInput = this.createComponent(FormControl, this.form, {
|
|
||||||
id: 'api-key-input',
|
|
||||||
label: 'Название хранилища',
|
|
||||||
pattern: '^[a-zA-Z][a-zA-Z0-9_-]{3,}$',
|
|
||||||
required: true,
|
|
||||||
}),
|
|
||||||
this.serviceNameInput = this.createComponent(FormControl, this.form, {
|
|
||||||
id: 'api-service-name-input',
|
|
||||||
label: 'Название сервиса',
|
|
||||||
required: true,
|
|
||||||
}),
|
|
||||||
this.authorInput = this.createComponent(FormControl, this.form, {
|
|
||||||
id: 'api-author-input',
|
|
||||||
label: 'Автор хранилища',
|
|
||||||
required: true,
|
|
||||||
}),
|
|
||||||
this.descriptionInput = this.createComponent(FormControl, this.form, {
|
|
||||||
id: 'api-description-input',
|
|
||||||
label: 'Краткое описание',
|
|
||||||
required: true,
|
|
||||||
}),
|
|
||||||
this.valueInput = this.createComponent(FormControl, this.form, {
|
|
||||||
id: 'api-value-input',
|
|
||||||
type: FORM_TYPES.TEXTAREA,
|
|
||||||
className: 'Api__value-input',
|
|
||||||
label: 'Содержимое хранилища',
|
|
||||||
required: true,
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
this.buttons = [
|
this.buttons = [
|
||||||
{
|
{
|
||||||
button: this.createButton = this.mainNode.querySelector('.ApiViewForm__create'),
|
button: this.createButton = this.mainNode.querySelector('.ApiViewForm__create'),
|
||||||
@ -69,10 +41,12 @@ class ApiTableViewForm extends Component {
|
|||||||
{
|
{
|
||||||
button: this.saveButton = this.mainNode.querySelector('.ApiViewForm__save'),
|
button: this.saveButton = this.mainNode.querySelector('.ApiViewForm__save'),
|
||||||
modes: [MODES.Edit],
|
modes: [MODES.Edit],
|
||||||
|
onlyOwner: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
button: this.editButton = this.mainNode.querySelector('.ApiViewForm__edit'),
|
button: this.editButton = this.mainNode.querySelector('.ApiViewForm__edit'),
|
||||||
modes: [MODES.View],
|
modes: [MODES.View],
|
||||||
|
onlyOwner: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
button: this.cancelButton = this.mainNode.querySelector('.ApiViewForm__cancel'),
|
button: this.cancelButton = this.mainNode.querySelector('.ApiViewForm__cancel'),
|
||||||
@ -81,6 +55,7 @@ class ApiTableViewForm extends Component {
|
|||||||
{
|
{
|
||||||
button: this.deleteButton = this.mainNode.querySelector('.ApiViewForm__delete'),
|
button: this.deleteButton = this.mainNode.querySelector('.ApiViewForm__delete'),
|
||||||
modes: [MODES.View, MODES.Edit],
|
modes: [MODES.View, MODES.Edit],
|
||||||
|
onlyOwner: true,
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -96,31 +71,74 @@ class ApiTableViewForm extends Component {
|
|||||||
|
|
||||||
this.addEventListener(this.cancelButton, EVENTS.CLICK, this.handleCloseModal);
|
this.addEventListener(this.cancelButton, EVENTS.CLICK, this.handleCloseModal);
|
||||||
|
|
||||||
|
this.hooksContainer = this.createComponent(HooksComponent, this.mainNode);
|
||||||
|
this.form.insertAdjacentElement('afterend', this.hooksContainer.mainNode);
|
||||||
|
|
||||||
|
this.addSubscribe(routeService, EVENTS.ROUTE_SEARCH_CHANGE, this.setForm);
|
||||||
|
|
||||||
|
this.renderInputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderInputs = async () => {
|
||||||
|
const users = await usersServiceApi.request();
|
||||||
|
this.inputs = [
|
||||||
|
this.keyInput = this.createComponent(FormControl, this.form, {
|
||||||
|
id: 'api-key-input',
|
||||||
|
label: 'Название хранилища',
|
||||||
|
pattern: '^[a-zA-Z][a-zA-Z0-9_-]{3,}$',
|
||||||
|
required: true,
|
||||||
|
}),
|
||||||
|
this.serviceNameInput = this.createComponent(FormControl, this.form, {
|
||||||
|
id: 'api-service-name-input',
|
||||||
|
label: 'Название сервиса',
|
||||||
|
required: true,
|
||||||
|
}),
|
||||||
|
this.authorInput = this.createComponent(FormControl, this.form, {
|
||||||
|
id: 'api-author-input',
|
||||||
|
label: 'Автор хранилища',
|
||||||
|
type: FORM_TYPES.SELECT,
|
||||||
|
options: users.map((user) => ({
|
||||||
|
value: user.login,
|
||||||
|
text: user.login,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
this.descriptionInput = this.createComponent(FormControl, this.form, {
|
||||||
|
id: 'api-description-input',
|
||||||
|
label: 'Краткое описание',
|
||||||
|
required: true,
|
||||||
|
}),
|
||||||
|
this.valueInput = this.createComponent(FormCodeEditor, this.form, {
|
||||||
|
id: 'api-value-input',
|
||||||
|
className: 'Api__value-input',
|
||||||
|
label: 'Содержимое хранилища',
|
||||||
|
mode: CODE_EDITOR_MODE.JSON,
|
||||||
|
required: true,
|
||||||
|
}),
|
||||||
|
this.hideSelect = this.createComponent(FormControl, this.form, {
|
||||||
|
id: 'api-hide-select',
|
||||||
|
label: 'Видимость хранилища',
|
||||||
|
type: FORM_TYPES.SELECT,
|
||||||
|
options: [
|
||||||
|
{value: true, text: 'Скрыть'},
|
||||||
|
{value: false, text: 'Показать'},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
this.inputs.forEach((input) => {
|
this.inputs.forEach((input) => {
|
||||||
input.disabled(true);
|
input.disabled(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.hooksContainer = this.createComponent(HooksComponent, this.mainNode);
|
this.setForm();
|
||||||
this.form.insertAdjacentElement('afterend', this.hooksContainer.mainNode);
|
|
||||||
|
|
||||||
this.addSubscribe(routeService, EVENTS.ROUTE_SEARCH_CHANGE, ({query}) => {
|
|
||||||
const {mode, key} = query;
|
|
||||||
this.setForm(mode, key);
|
|
||||||
this.setVisibleHooks(mode);
|
|
||||||
});
|
|
||||||
|
|
||||||
const {query: {mode, key}} = routeService.getUrlData();
|
|
||||||
if (mode) {
|
|
||||||
this.setForm(mode, key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCloseModal = () => {
|
handleCloseModal = () => {
|
||||||
routeService.pushQuery({}, true);
|
routeService.pushQuery({}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisibleHooks = (mode) => {
|
setVisibleHooks = (mode, isAvailable) => {
|
||||||
const method = mode !== MODES.View ? 'add' : 'remove';
|
const isHide = mode !== MODES.View || !isAvailable;
|
||||||
|
const method = isHide ? 'add' : 'remove';
|
||||||
this.hooksContainer.mainNode.classList[method]('invisible');
|
this.hooksContainer.mainNode.classList[method]('invisible');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,17 +163,26 @@ class ApiTableViewForm extends Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
setInputDisabled = (mode) => {
|
setInputDisabled = (mode, isAdmin) => {
|
||||||
const disabled = !EDIT_MODES.includes(mode);
|
const disabled = !EDIT_MODES.includes(mode);
|
||||||
this.inputs.forEach((input) => {
|
this.inputs.forEach((input) => {
|
||||||
const disabledLogin = this.keyInput === input && mode === MODES.Edit;
|
if (input === this.keyInput) {
|
||||||
input.disabled(disabled ? disabled : disabledLogin);
|
const disabledKey = mode !== MODES.Create;
|
||||||
|
input.disabled(disabled ? disabled : disabledKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (input === this.authorInput) {
|
||||||
|
const disabledAuthor = mode !== MODES.Create || !isAdmin;
|
||||||
|
input.disabled(disabled ? disabled : disabledAuthor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input.disabled(disabled);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
showButtons = (mode) => {
|
showButtons = (mode, isAvailable) => {
|
||||||
this.buttons.forEach(({button, modes}) => {
|
this.buttons.forEach(({button, modes, onlyOwner}) => {
|
||||||
const isShow = modes.includes(mode);
|
const isShow = modes.includes(mode) && (onlyOwner ? isAvailable : true);
|
||||||
button.style.display = isShow ? 'inline-block' : 'none';
|
button.style.display = isShow ? 'inline-block' : 'none';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -201,6 +228,7 @@ class ApiTableViewForm extends Component {
|
|||||||
service_name: this.serviceNameInput.getValue(),
|
service_name: this.serviceNameInput.getValue(),
|
||||||
author: this.authorInput.getValue(),
|
author: this.authorInput.getValue(),
|
||||||
description: this.descriptionInput.getValue(),
|
description: this.descriptionInput.getValue(),
|
||||||
|
hide: this.hideSelect.getValue(),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.clearForm();
|
this.clearForm();
|
||||||
@ -216,6 +244,7 @@ class ApiTableViewForm extends Component {
|
|||||||
service_name: this.serviceNameInput.getValue(),
|
service_name: this.serviceNameInput.getValue(),
|
||||||
author: this.authorInput.getValue(),
|
author: this.authorInput.getValue(),
|
||||||
description: this.descriptionInput.getValue(),
|
description: this.descriptionInput.getValue(),
|
||||||
|
hide: this.hideSelect.getValue(),
|
||||||
});
|
});
|
||||||
this.clearForm();
|
this.clearForm();
|
||||||
routeService.pushQuery({}, true);
|
routeService.pushQuery({}, true);
|
||||||
@ -234,17 +263,22 @@ class ApiTableViewForm extends Component {
|
|||||||
this.keyInput.setValue(key);
|
this.keyInput.setValue(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
setForm = async (mode, storeKey) => {
|
setForm = async () => {
|
||||||
const {key, value, description, service_name, author} = await this.loadStore(storeKey);
|
const {query: {mode, key: storeKey}} = routeService.getUrlData();
|
||||||
|
const {key, value, description, service_name, author, hide} = await this.loadStore(storeKey);
|
||||||
|
const {login, is_admin} = await userInfoService.getUserInfo();
|
||||||
|
const isAvailableEdit = author === login || is_admin;
|
||||||
this.setSidebarTitle(mode, storeKey);
|
this.setSidebarTitle(mode, storeKey);
|
||||||
this.setKeyInput(mode, key);
|
this.setKeyInput(mode, key);
|
||||||
this.serviceNameInput.setValue(service_name);
|
this.serviceNameInput.setValue(service_name);
|
||||||
this.authorInput.setValue(author);
|
this.authorInput.setValue(author || login);
|
||||||
this.descriptionInput.setValue(description);
|
this.descriptionInput.setValue(description);
|
||||||
this.valueInput.setValue(this.stringifyValue(value));
|
this.valueInput.setValue(this.stringifyValue(value));
|
||||||
|
this.hideSelect.setValue(hide);
|
||||||
|
|
||||||
this.setInputDisabled(mode);
|
this.setInputDisabled(mode, is_admin);
|
||||||
this.showButtons(mode);
|
this.showButtons(mode, isAvailableEdit);
|
||||||
|
this.setVisibleHooks(mode, isAvailableEdit);
|
||||||
|
|
||||||
if (mode) {
|
if (mode) {
|
||||||
this.sidebar.show();
|
this.sidebar.show();
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import http from '../../../api/HttpAPI';
|
import http from '../../../api/HttpAPI';
|
||||||
|
|
||||||
const ROOT_URL = 'http://api.auth.vigdorov.ru/users';
|
const ROOT_URL = 'https://api.auth.vigdorov.ru/users';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Объект с полями для создания пользователя
|
* Объект с полями для создания пользователя
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class UsersPage extends Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.addSubscribe(userInfoService, EVENTS.CHANGE_USER_INFO, ({is_admin}) => {
|
this.addSubscribe(userInfoService, EVENTS.CHANGE_USER_INFO, ({is_admin}) => {
|
||||||
this.createUserButton.disabled = !is_admin;
|
this.setCreateUserButton(is_admin);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addEventListener(this.createUserButton, EVENTS.CLICK, () => {
|
this.addEventListener(this.createUserButton, EVENTS.CLICK, () => {
|
||||||
@ -61,9 +61,13 @@ class UsersPage extends Component {
|
|||||||
this.initPage();
|
this.initPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCreateUserButton = (isAdmin) => {
|
||||||
|
this.createUserButton.style.display = isAdmin ? 'inline-block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
initPage = async () => {
|
initPage = async () => {
|
||||||
const user = await userInfoService.getUserInfo();
|
const user = await userInfoService.getUserInfo();
|
||||||
this.createUserButton.disabled = !user.is_admin;
|
this.setCreateUserButton(user.is_admin);
|
||||||
this.userList = await usersServiceApi.request();
|
this.userList = await usersServiceApi.request();
|
||||||
this.renderTable();
|
this.renderTable();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,20 +85,20 @@ class UserViewForm extends Component {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
this.addEventListener(this.cancelButton, 'click', () => {
|
this.addEventListener(this.cancelButton, EVENTS.CLICK, () => {
|
||||||
routeService.pushQuery({}, true);
|
routeService.pushQuery({}, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addEventListener(this.editButton, 'click', () => {
|
this.addEventListener(this.editButton, EVENTS.CLICK, () => {
|
||||||
routeService.pushQuery({mode: MODES.Edit});
|
routeService.pushQuery({mode: MODES.Edit});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addEventListener(this.form, 'submit', (event) => {
|
this.addEventListener(this.form, EVENTS.SUBMIT, (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
this.addEventListener(this.createButton, 'click', this.createUser);
|
this.addEventListener(this.createButton, EVENTS.CLICK, this.createUser);
|
||||||
this.addEventListener(this.saveButton, 'click', this.saveUser);
|
this.addEventListener(this.saveButton, EVENTS.CLICK, this.saveUser);
|
||||||
this.addEventListener(this.deleteButton, 'click', this.deleteUser);
|
this.addEventListener(this.deleteButton, EVENTS.CLICK, this.deleteUser);
|
||||||
|
|
||||||
this.addSubscribe(routeService, EVENTS.ROUTE_SEARCH_CHANGE, ({query}) => {
|
this.addSubscribe(routeService, EVENTS.ROUTE_SEARCH_CHANGE, ({query}) => {
|
||||||
const {mode, login} = query;
|
const {mode, login} = query;
|
||||||
@ -128,7 +128,7 @@ class UserViewForm extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
validateInputs = () => {
|
validateInputs = (isEditMode) => {
|
||||||
this.form.classList.add('was-validated');
|
this.form.classList.add('was-validated');
|
||||||
const login = this.login.getValue();
|
const login = this.login.getValue();
|
||||||
|
|
||||||
@ -147,6 +147,10 @@ class UserViewForm extends Component {
|
|||||||
return '';
|
return '';
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
if (isEditMode) {
|
||||||
|
this.password.setError('');
|
||||||
|
}
|
||||||
|
|
||||||
this.login.setError(loginErrorMessage);
|
this.login.setError(loginErrorMessage);
|
||||||
|
|
||||||
return this.form.checkValidity();
|
return this.form.checkValidity();
|
||||||
@ -174,7 +178,7 @@ class UserViewForm extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveUser = () => {
|
saveUser = () => {
|
||||||
if (this.validateInputs()) {
|
if (this.validateInputs(true)) {
|
||||||
this.next(EVENTS.SAVE_USER, {
|
this.next(EVENTS.SAVE_USER, {
|
||||||
login: this.login.getValue(),
|
login: this.login.getValue(),
|
||||||
avatar: this.avatar.getValue(),
|
avatar: this.avatar.getValue(),
|
||||||
@ -214,6 +218,11 @@ class UserViewForm extends Component {
|
|||||||
const isShow = mode === MODES.Create;
|
const isShow = mode === MODES.Create;
|
||||||
this.password.setValue('');
|
this.password.setValue('');
|
||||||
this.password.mainNode.style.display = isShow ? 'block' : 'none';
|
this.password.mainNode.style.display = isShow ? 'block' : 'none';
|
||||||
|
if (isShow) {
|
||||||
|
this.login.mainNode.after(this.password.mainNode);
|
||||||
|
} else {
|
||||||
|
this.mainNode.appendChild(this.password.mainNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setLogin = (mode, login) => {
|
setLogin = (mode, login) => {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ class UserInfoService extends EmitService {
|
|||||||
this.userInfo = {
|
this.userInfo = {
|
||||||
login: NOT_USER,
|
login: NOT_USER,
|
||||||
avatar: DEFAULT_AVATAR,
|
avatar: DEFAULT_AVATAR,
|
||||||
|
is_admin: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user