HM-134. Добавлен редактор кода Ace и внедрен для работы с хранилищами (#66)
This commit is contained in:
20
src/app.html
20
src/app.html
@ -32,6 +32,26 @@
|
||||
</nav>
|
||||
</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">
|
||||
<div class="h-100">
|
||||
|
||||
@ -15,6 +15,7 @@ import authServiceApi from './api/AuthServiceAPI';
|
||||
import userInfoService from './services/UserInfoService';
|
||||
import {EVENTS, ROUTES} from './core/consts';
|
||||
import UsersPage from './pages/users/components/page/Page';
|
||||
import {DocumentationPage} from './pages/documentation/components/page/Page';
|
||||
|
||||
const initAppComponents = () => {
|
||||
const mainMenu = new MainMenu();
|
||||
@ -40,6 +41,7 @@ const initAppComponents = () => {
|
||||
{url: ROUTES.USERS, pageComponent: UsersPage},
|
||||
{url: ROUTES.LOGIN, pageComponent: LoginPage},
|
||||
{url: ROUTES.PROFILE, pageComponent: ProfilePage},
|
||||
{url: ROUTES.DOCUMENTATION, pageComponent: DocumentationPage},
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
3
src/core/components/code-editor/CodeEditor.css
Normal file
3
src/core/components/code-editor/CodeEditor.css
Normal file
@ -0,0 +1,3 @@
|
||||
.CodeEditor__editor {
|
||||
width: 100%;
|
||||
}
|
||||
43
src/core/components/code-editor/CodeEditor.js
Normal file
43
src/core/components/code-editor/CodeEditor.js
Normal file
@ -0,0 +1,43 @@
|
||||
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.setValue(value);
|
||||
}
|
||||
|
||||
getValue = () => {
|
||||
return this.editor.getValue();
|
||||
}
|
||||
|
||||
disabled = (value) => {
|
||||
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 = () => {
|
||||
this.errorText.textContent = '';
|
||||
this.setError('');
|
||||
}
|
||||
|
||||
getInputTagName = (type) => {
|
||||
|
||||
@ -22,6 +22,10 @@ const NAV_MENU = [
|
||||
title: 'Пользователи',
|
||||
url: ROUTES.USERS,
|
||||
},
|
||||
{
|
||||
title: 'Документация',
|
||||
url: ROUTES.DOCUMENTATION,
|
||||
},
|
||||
{
|
||||
title: 'Личный кабинет',
|
||||
url: ROUTES.PROFILE,
|
||||
|
||||
@ -69,4 +69,9 @@ export const ROUTES = {
|
||||
USERS: '/users',
|
||||
LOGIN: '/login',
|
||||
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: 'Документация',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,3 @@
|
||||
.Api__value-input {
|
||||
height: 200px;
|
||||
}
|
||||
.Api__view-controls {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import Component from '../../../../core/components/component/Component';
|
||||
import ModalSidebar from '../../../../core/components/modal-sidebar/ModalSibebar';
|
||||
import FormControl from '../../../../core/components/form-control/FormControl';
|
||||
import {FORM_TYPES, EVENTS, MODES} from '../../../../core/consts';
|
||||
import {EVENTS, MODES, CODE_EDITOR_MODE} from '../../../../core/consts';
|
||||
import './ApiTableViewForm.css';
|
||||
import storageApi from '../../api/StorageServiceAPI';
|
||||
import routeService from '../../../../services/RouteService';
|
||||
import {HooksComponent} from '../hooks-component/HooksComponent';
|
||||
import {FormCodeEditor} from '../../../../core/components/form-code-editor/FormCodeEditor';
|
||||
|
||||
const TITLE_MODES = {
|
||||
[MODES.Create]: 'Создание нового хранилища',
|
||||
@ -52,11 +53,11 @@ class ApiTableViewForm extends Component {
|
||||
label: 'Краткое описание',
|
||||
required: true,
|
||||
}),
|
||||
this.valueInput = this.createComponent(FormControl, this.form, {
|
||||
this.valueInput = this.createComponent(FormCodeEditor, this.form, {
|
||||
id: 'api-value-input',
|
||||
type: FORM_TYPES.TEXTAREA,
|
||||
className: 'Api__value-input',
|
||||
label: 'Содержимое хранилища',
|
||||
mode: CODE_EDITOR_MODE.JSON,
|
||||
required: true,
|
||||
}),
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user