problems ack dialog: submit on enter and show error for empty message

This commit is contained in:
Alexander Zobnin
2018-12-27 13:57:08 +03:00
parent ad0f2c809c
commit 9e40959ef6
4 changed files with 65 additions and 11 deletions

View File

@@ -40,6 +40,7 @@
"babel-preset-env": "^1.7.0", "babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1", "babel-preset-react": "^6.24.1",
"benchmark": "^2.1.4", "benchmark": "^2.1.4",
"classnames": "^2.2.6",
"clean-webpack-plugin": "^0.1.19", "clean-webpack-plugin": "^0.1.19",
"codecov": "^3.1.0", "codecov": "^3.1.0",
"copy-webpack-plugin": "^4.5.4", "copy-webpack-plugin": "^4.5.4",

View File

@@ -1,5 +1,9 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import classNames from 'classnames';
const KEYBOARD_ENTER_KEY = 13;
const KEYBOARD_ESCAPE_KEY = 27;
interface ModalProps { interface ModalProps {
isOpen?: boolean; isOpen?: boolean;
@@ -10,6 +14,8 @@ interface ModalProps {
interface ModalState { interface ModalState {
value: string; value: string;
error: boolean;
message: string;
} }
export interface AckProblemData { export interface AckProblemData {
@@ -23,23 +29,43 @@ export class Modal extends PureComponent<ModalProps, ModalState> {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { value: '' }; this.state = {
value: '',
error: false,
message: '',
};
this.modalContainer = document.body; this.modalContainer = document.body;
} }
handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ value: event.target.value }); this.setState({ value: event.target.value, error: false });
}
handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.which === KEYBOARD_ENTER_KEY || event.key === 'Enter') {
this.submit();
} else if (event.which === KEYBOARD_ESCAPE_KEY || event.key === 'Escape') {
this.dismiss();
}
}
handleBackdropClick = () => {
this.dismiss();
} }
dismiss = () => { dismiss = () => {
console.log('dismiss'); this.setState({ value: '', error: false, message: '' });
this.setState({ value: '' });
this.props.onClose(); this.props.onClose();
} }
submit = () => { submit = () => {
console.log('submit', this.state.value); if (!this.state.value) {
return this.setState({
error: true,
message: 'Enter message text'
});
}
this.props.onSubmit({ this.props.onSubmit({
message: this.state.value message: this.state.value
}).then(() => { }).then(() => {
@@ -52,8 +78,10 @@ export class Modal extends PureComponent<ModalProps, ModalState> {
return null; return null;
} }
const inputClass = classNames('gf-form-input', { 'zbx-ack-error': this.state.error });
const modalNode = ( const modalNode = (
<div className="modal modal--narrow" key="modal"> <div className="modal modal--narrow zbx-ack-modal" key="modal">
<div className="modal-body"> <div className="modal-body">
<div className="modal-header"> <div className="modal-header">
<h2 className="modal-header-title"> <h2 className="modal-header-title">
@@ -66,10 +94,9 @@ export class Modal extends PureComponent<ModalProps, ModalState> {
</a> </a>
</div> </div>
<div className="modal-content"> <div className="modal-content">
{/* Message */}
<div className="gf-form"> <div className="gf-form">
<label className="gf-form-hint"> <label className="gf-form-hint">
<input className="gf-form-input" <input className={inputClass}
type="text" type="text"
name="message" name="message"
placeholder="Message" placeholder="Message"
@@ -77,10 +104,17 @@ export class Modal extends PureComponent<ModalProps, ModalState> {
autoComplete="off" autoComplete="off"
autoFocus={true} autoFocus={true}
value={this.state.value} value={this.state.value}
onChange={this.handleChange}> onChange={this.handleChange}
onKeyUp={this.handleKeyUp}>
</input> </input>
<small className="gf-form-hint-text muted">Press Enter to submit</small>
{this.state.error &&
<small className="gf-form-hint-text muted ack-error-message">{this.state.message}</small>
}
</label> </label>
</div> </div>
<div className="gf-form">
</div>
<div className="gf-form-button-row text-center"> <div className="gf-form-button-row text-center">
<button className="btn btn-success" onClick={this.submit}>Acknowledge</button> <button className="btn btn-success" onClick={this.submit}>Acknowledge</button>
@@ -93,7 +127,7 @@ export class Modal extends PureComponent<ModalProps, ModalState> {
const modalNodeWithBackdrop = [ const modalNodeWithBackdrop = [
modalNode, modalNode,
<div className="modal-backdrop in" key="modal-backdrop"></div> <div className="modal-backdrop in" key="modal-backdrop" onClick={this.handleBackdropClick}></div>
]; ];
const modal = this.props.withBackdrop ? modalNodeWithBackdrop : modalNode; const modal = this.props.withBackdrop ? modalNodeWithBackdrop : modalNode;

View File

@@ -510,6 +510,25 @@
} }
} }
.zbx-ack-modal {
.gf-form-input.zbx-ack-error {
border-color: $btn-danger-bg;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px $btn-danger-bg;
}
.gf-form .gf-form-hint {
.gf-form-hint-text {
display: inherit;
float: right;
&.ack-error-message {
float: left;
color: $error-text-color;
}
}
}
}
@keyframes slide-down { @keyframes slide-down {
0% { 0% {
opacity: 0; opacity: 0;

View File

@@ -1821,7 +1821,7 @@ class-utils@^0.3.5:
isobject "^3.0.0" isobject "^3.0.0"
static-extend "^0.1.1" static-extend "^0.1.1"
classnames@^2.2.5: classnames@^2.2.5, classnames@^2.2.6:
version "2.2.6" version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==