Add jquery library, add modal component and style it. Add localization support

parent 9834b3ee
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
"name": "typos-react", "name": "typos-react",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"bootstrap": "^3.3.7", "bootstrap": "^3.3.7",
"jquery": "^3.3.1",
"react": "^16.4.1", "react": "^16.4.1",
"react-bootstrap": "^0.32.1", "react-bootstrap": "^0.32.1",
"react-dom": "^16.4.1", "react-dom": "^16.4.1",
"react-localization": "^1.0.10",
"react-scripts": "1.1.4" "react-scripts": "1.1.4"
}, },
"scripts": { "scripts": {
......
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Panel } from 'react-bootstrap' import $ from 'jquery';
import './App.css';
import TypoModal from '../Modal/'
import {i18n} from '../Localization'
class App extends Component { class App extends Component {
constructor(props, context) {
super(props, context);
this.state = {
correctionMode: false
}
this.minSelectionLength = 4;
this.maxSelectionLength = 50;
this.typo = "";
this.registerHandlers();
}
// Returns selected text or null if no
// text was selected
getSelectedText() {
return window.getSelection().toString();
}
// Register handlers for user input
// CTRL+Enter should open modal with typo correction
registerHandlers() {
$(document).keydown(event => {
if (event.ctrlKey && event.keyCode === 13) {
const selection = this.getSelectedText();
if (selection.length < this.minSelectionLength ||
selection.length > this.maxSelectionLength)
{
alert(i18n.formatString(i18n.errorSelectionLength,
this.minSelectionLength, this.maxSelectionLength));
return;
}
this.typo = selection;
// Ctrl-Enter pressed
this.setState({
correctionMode: true
});
}
});
}
render() { render() {
if (!this.state.correctionMode) return null;
return ( return (
<div className="es-typo-window"> <TypoModal text={this.typo} closeCallback={this.modalClosedCallback} show={this.state.correctionMode}/>
<Panel bsStyle="primary">
<Panel.Heading>Etersoft Typos</Panel.Heading>
<Panel.Body>You want to correct this typo: $s</Panel.Body>
<Panel.Footer>Panel footer!</Panel.Footer>
</Panel>
</div>
); );
} }
// This method is invoked when a modal has been closed
modalClosedCallback = () => {
this.setState({
correctionMode: false
})
}
} }
export default App; export default App;
import LocalizedStrings from 'react-localization'
export const i18n = new LocalizedStrings({
ru: {
modalTitle: "Система исправления опечаток Etersoft",
modalInfo: "Пожалуйста, введите исправленный вариант и комментарий (необязательно) " +
"для отправки отчёта об опечатке на сервер",
modalCorrectLabel: "Исправленный вариант",
modalCorrectHelp: "Модераторы проверят исправления и внесут поправки в текст",
modalTypoLabel: "Текст с ошибкой",
errorSelectionLength: "Опечатка должна быть длиной от {0} до {1} символов",
close: "Закрыть",
saveChanges: "Сохранить изменения"
},
en: {
}
})
\ No newline at end of file
.es-typo-text {
font-size: 140%;
color: #3278b5;
}
.es-typo-correct-fg {
margin-top: 20px;
}
.es-typo-text-fg {
margin-top: 30px;
}
\ No newline at end of file
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import App from './App'; import TypoModal from './Modal';
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<App />, div); ReactDOM.render(<TypoModal />, div);
ReactDOM.unmountComponentAtNode(div); ReactDOM.unmountComponentAtNode(div);
}); });
import React, { Component } from 'react';
import { Modal, Button, FormGroup, FormControl, ControlLabel, HelpBlock } from 'react-bootstrap'
import './Modal.css';
import {i18n} from '../Localization'
class TypoModal extends Component {
constructor(props, context) {
super(props, context);
this.state = {
show: this.props.show
}
this.text = props.text;
this.closeCallback = props.closeCallback;
}
handleShow = () => {
this.setState({ show: true })
}
handleClose = () => {
this.setState({ show: false })
this.closeCallback();
}
render() {
if (!this.state.show) return null;
return (
<Modal className="es-typo-window" show={this.state.show} onHide={this.handleClose}>
<Modal.Header closeButton><Modal.Title>{i18n.modalTitle}</Modal.Title></Modal.Header>
<Modal.Body>
<p>{i18n.modalInfo}</p>
<form>
<FormGroup className="es-typo-text-fg">
<ControlLabel>{i18n.modalTypoLabel}</ControlLabel>
<p className="es-typo-text">{this.text}</p>
</FormGroup>
<FormGroup className="es-typo-correct-fg">
<ControlLabel>{i18n.modalCorrectLabel}</ControlLabel>
<FormControl
type="text"
value={this.text} />
<HelpBlock>{i18n.modalCorrectHelp}</HelpBlock>
</FormGroup>
</form>
</Modal.Body>
<Modal.Footer>
<Button>{i18n.close}</Button>
<Button bsStyle="primary">{i18n.saveChanges}</Button>
</Modal.Footer>
</Modal>
);
}
}
export default TypoModal;
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css' import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/css/bootstrap-theme.css' import 'bootstrap/dist/css/bootstrap-theme.css';
import App from './App/'; import App from './App/';
import registerServiceWorker from './registerServiceWorker'; import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('typos-window')); const rootElement = document.createElement("div");
ReactDOM.render(<App />, rootElement);
registerServiceWorker(); registerServiceWorker();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment