Commit 9da58bfd authored by Maxime Chaillet's avatar Maxime Chaillet

revisit the layout of a new event. remove title. move tags below the editor....

revisit the layout of a new event. remove title. move tags below the editor. Make the modal webresponsive.
parent ed468033
......@@ -8,11 +8,11 @@ import PropTypes from 'prop-types'
class EventFooter extends React.Component {
render() {
return (
<div style={{ position: 'relative', height:'37px' }}>
<div style={{ position: 'relative', height: '37px' }}>
&nbsp;
<div className="noUnderlinedLink" style={{ position: 'absolute', right: '10px', top: '5px' }}>
<ButtonToolbar>
<ButtonGroup>
<ButtonGroup style={{ height: '30px' }}>
{this.props.isSaveButtonEnabled === true ?
<OverlayTrigger
placement="left"
......
......@@ -2,7 +2,7 @@
//React components
import React from 'react'
import PropTypes from 'prop-types';
import { Grid, Row, Col, FormControl, Panel, Collapse, Label, InputGroup } from "react-bootstrap"
import { Grid, Row, Col, FormControl, Panel, Collapse, Label, InputGroup, Glyphicon } from "react-bootstrap"
import TagContainer from '../../containers/TagContainer'
......@@ -10,7 +10,6 @@ import HTMLEditor from './HTMLEditor'
import EventHeader from './EventHeader'
import EventFooter from './EventFooter'
import { NEW_EVENT_INVISIBLE, ANNOTATION, NEW_EVENT_CONTEXT, EVENT_CATEGORY_COMMENT } from '../../constants/EventTypes';
import OverlayBox from './OverlayBox';
/* the possible status of the component */
const IDLE_STATUS = "idle";
......@@ -28,7 +27,7 @@ class NewEvent extends React.Component {
}
render() {
const { investigationId, isVisible, user, onNewEventUploaded } = this.props;
const { investigationId, user, onNewEventUploaded } = this.props;
if (this.state.status === UPLOADED_STATUS) {
this.setState({ status: IDLE_STATUS });
......@@ -36,69 +35,54 @@ class NewEvent extends React.Component {
return null;
} else {
return (
<Panel bsStyle='primary' style={{ marginBottom: '0px' }}>
<EventHeader context={NEW_EVENT_CONTEXT} />
<div>
<div style={{ padding: '1px' }}>
<HTMLEditor
user={user}
investigationId={investigationId}
isEditionMode={true}
canEnableSaveButton={this.canEnableSaveButton} />
</div>
{/* <div style={{ paddingTop: '8px'}}>
<InputGroup>
<InputGroup.Addon style={{ backgroundColor: 'transparent', border: 'none' }}> <Label> Title </Label> </InputGroup.Addon>
<FormControl
type="text"
value={this.state.inputTitleValue}
onChange={this.onChangeInputValue}
placeholder="Optional title here"
inputRef={(FormControl) => this.inputTitle = FormControl} />
</InputGroup>
</div> */}
<div>
<Label style={{ margin: '6px 6px 6px 12px', paddingRight: '2px' }}> Tags </Label>
<a href={"/investigation/" + this.props.investigationId + "/events/tagManager"} target="_blank" style={{ fontSize: '12px' }}> <Glyphicon glyph='cog' /> </a>
{/* <InputGroup.Addon style={{ backgroundColor: 'transparent', border: 'none' }}> <Label> Tags </Label> </InputGroup.Addon> */}
{/* <div style={{ paddingTop: '5px', marginRight: '10px' }}> */}
<TagContainer
canEnableSaveButton={this.canEnableSaveButton}
context={NEW_EVENT_CONTEXT}
investigationId={this.props.investigationId}
setTagContainer={this.setTagContainer}
/>
{/* </div> */}
</div>
</div>
<EventFooter
isSaveButtonEnabled={this.state.hasText}
onCancelButtonClicked={this.onCancelNewEventClicked}
onSaveButtonClicked={this.createEvent} />
</Panel>
<OverlayBox open={isVisible} classNames={{ overlay: 'newEventOverlayClass', modal: 'newEventModalClass' }}>
<Panel bsStyle='primary' >
<EventHeader context={NEW_EVENT_CONTEXT} />
< div id="newEventBox" style={{ display: 'flex' }} >
{/* the left panel */}
< div style={{ flexGrow: '0', maxWidth: '155px' }}>
<div style={{ paddingLeft: '5px' }} >
<div style={{ height: '50px' }} />
<a href={"/investigation/" + this.props.investigationId + "/events/tagManager"} target="_blank" style={{ float: 'right', paddingRight: '10px' }}> manage </a>
<Label> Tags </Label>
<div style={{ paddingTop: '5px', marginRight: '10px' }}>
<TagContainer
canEnableSaveButton={this.canEnableSaveButton}
context={NEW_EVENT_CONTEXT}
investigationId={this.props.investigationId}
setTagContainer={this.setTagContainer}
/>
</div>
</div>
</div >
<div
style={{ flexGrow: '1' }}>
<div>
<HTMLEditor
user={user}
investigationId={investigationId}
isEditionMode={true}
canEnableSaveButton={this.canEnableSaveButton} />
<div style={{ paddingTop: '8px' }}>
<InputGroup>
<InputGroup.Addon style={{ backgroundColor: 'transparent', border: 'none' }}> <Label> Title </Label> </InputGroup.Addon>
<FormControl
type="text"
value={this.state.inputTitleValue}
onChange={this.onChangeInputValue}
placeholder="Optional title here"
inputRef={(FormControl) => this.inputTitle = FormControl} />
</InputGroup>
</div>
</div>
<EventFooter
isSaveButtonEnabled={this.state.hasText}
onCancelButtonClicked={this.onCancelNewEventClicked}
onSaveButtonClicked={this.createEvent} />
</div>
</div >
</Panel>
</OverlayBox>
)
}
}
......@@ -148,7 +132,7 @@ class NewEvent extends React.Component {
],
creationDate: Date(),
investigationId: investigationId,
title: this.inputTitle.value,
title: '', //this.inputTitle.value,
tag: currentTagIds,
type: ANNOTATION,
username: this.props.user.username,
......@@ -166,8 +150,6 @@ class NewEvent extends React.Component {
NewEvent.propTypes = {
/** the investigationId indicating what investigation the new event will belong to*/
investigationId: PropTypes.string.isRequired,
/** whether this component is visible (ie panel is expanded) or not */
isVisible: PropTypes.bool.isRequired,
/** Callback function to reload events from the server */
reloadEvents: PropTypes.func,
// /** the callback function to change the visibility of this component */
......
......@@ -2,6 +2,7 @@ import React from 'react';
import Modal from 'react-responsive-modal';
import PropTypes from 'prop-types';
import Loading from '../Loading';
import logo from '../../images/loader.gif';
/**
* React component used to render a box overlayed on top of the page
......@@ -18,17 +19,28 @@ class OverlayBox extends React.Component {
return (<Modal
classNames={this.props.classNames}
onEntered={this.onEntered}
onExited={this.onExited}
open={this.props.open}
blockScroll={false}
showCloseIcon={false}
focusTrapped={false}
center={true}
>
{this.state.isChildComponentVisible === true ? this.props.children : <Loading />}
{this.state.isChildComponentVisible === true ? this.props.children : <img src={logo} style={{ position: 'absolute', left: '50%', marginLeft: '-25px', top: '50%', marginTop: '-25px', height: '50px', width: '50px' }} />}
</Modal>);
}
/** Callback triggered when the overlay box is opened. */
onEntered = () => {
/** this is a trick to circonvent a bug with tinymce in modals. the modal needs to be displayed first and tinymce shwn afterwards otherwise a bug occurs in tinymce. */
let timer = setTimeout(() => { this.setState({ isChildComponentVisible: true }) }, 500);
/** this is a trick to circumvent a bug with tinymce in modals. the modal needs to be displayed first and tinymce shwn afterwards otherwise a bug occurs in tinymce. */
let timer = setTimeout(() => { this.setState({ isChildComponentVisible: true }) }, 100);
}
/**
* Callback triggered when the modal is close. This happends when props.open becomes false
*/
onExited = () => {
this.setState({ isChildComponentVisible: false })
}
}
......
......@@ -38,13 +38,20 @@ class TagList extends React.Component {
...provided,
maxWidth: 140,
minWidth: 100,
minHeight: 32,
minHeight: 25,
}),
container: (provided) => ({
...provided,
marginTop: '5px'
}),
valueContainer: (provided) => ({
...provided,
paddingTop: '0px',
paddingBottom: '0px',
})
};
let selectedTags = this.props.selectedTags ?
......@@ -55,17 +62,17 @@ class TagList extends React.Component {
: null;
return (
<div>
<div style={{ display: 'inline-block' }}>
<div style={{ display: 'inline-block', paddingRight: '10px', paddingTop:'5px' }}>
<CreatableSelect
isClearable={false}
noOptionsMessage={() => 'No existing tag'}
onChange={this.onChange}
styles={customStyles}
options={availableTagsForSelect}
isSearchable={true} />
</div>
{selectedTags}
<CreatableSelect
isClearable={false}
noOptionsMessage={() => 'No existing tag'}
onChange={this.onChange}
styles={customStyles}
options={availableTagsForSelect}
isSearchable={true} />
</div>
);
......
......@@ -10,9 +10,7 @@ class TagViewer extends React.Component {
let { context, tag } = this.props;
if (context === DETAILED_EVENT_CONTEXT) {
return (<div style={{
marginRight: '4px',
}}>
return (<div style={{ display: 'inline-block', marginRight: '4px' }}>
<Label
style={{
backgroundColor: tag.color,
......@@ -77,7 +75,7 @@ class TagViewer extends React.Component {
</Label>
</Col>
<Col xs={12} sm={6} style={{alignItems: 'stretch', }}>
<Col xs={12} sm={6} style={{ alignItems: 'stretch', }}>
{tag.description ? <span> {tag.description} </span> : <span style={{ color: 'gray', fontStyle: 'italic' }}> No description yet</span>}
</Col>
......
......@@ -267,6 +267,7 @@ div.collapsedEventPanel-heading:hover {
}
/* Logbook menu related */
.logbookNavItem>a {
padding-top: 8px!important;
padding-bottom: 5px!important;
......@@ -275,45 +276,48 @@ div.collapsedEventPanel-heading:hover {
}
@media (max-width: 400px) {
.comboSearchContainer{
display: inline-block;
}
.comboSearchContainer {
display: inline-block;
}
}
@media (min-width: 401px) {
.comboSearchContainer{
display: inline-block;
width:400px;
}
.comboSearchContainer {
display: inline-block;
width: 400px;
}
}
/* END Logbook menu related */
.newEventOverlayClass {
background-color: transparent;
top: unset;
bottom: 80px;
height: 500px;
width: 850px;
left:unset;
}
.newEventModalClass {
max-width: unset;
margin: unset;
}
.myOverlayClass2 {
background-color: transparent;
top: unset;
bottom: 570px;
height: 500px;
width: 850px;
left:unset;
}
.myModalClass2 {
max-width: unset;
margin: unset;
@media (min-width: 1000px) {
.newEventOverlayClass {
background-color: transparent;
top: unset;
bottom: 60px;
height: 428px;
width: 850px;
left: unset;
padding-right: 0px;
/* overflow-y: hidden; */
}
.newEventModalClass {
max-width: unset;
margin: unset;
width: 100%;
height: 100%;
padding: unset;
}
.myOverlayClass2 {
background-color: transparent;
top: unset;
bottom: 570px;
height: 500px;
width: 850px;
left: unset;
}
.myModalClass2 {
max-width: unset;
margin: unset;
}
}
\ No newline at end of file
import React from 'react';
import './Loading.css';
import logo from '../images/loader.gif';
import logo from '../images/loader.gif';
class Loading extends React.Component {
render() {
render() {
let message = "Loading...";
if (this.props.message){
if (this.props.message) {
message = this.props.message;
}
return <div style={{width:300, height:300, marginTop:100}} className="center-div">
<div style={{ height:150}}><img style={{marginTop:100,height:50,width:50}} alt="" src={logo} /></div>
<div style={{ height:100}}><span style={{marginTop:200}}>{message}</span></div>
</div>;
}
return <div style={{ width: 300, height: 300, marginTop: 100 }} className="center-div">
<div style={{ height: 150 }}><img style={{ marginTop: 100, height: 50, width: 50 }} alt="" src={logo} /></div>
<div style={{ height: 100 }}><span style={{ marginTop: 200 }}>{message}</span></div>
</ div>;
}
}
export default Loading;
......@@ -23,7 +23,7 @@ class GeneralConfig {
this.statusbar = false;
this.branding = false; // hides powered by tinymce
this.paste_data_images = true;
this.autoresize_min_height = 400; //in px
this.autoresize_min_height = 250; //in px
this.autoresize_max_height = GUI_CONFIG().NEW_EVENT_MAX_HEIGHT; //in px
this.content_css = '/tinymce/customStyles.css';
this.formats = {
......
......@@ -15,6 +15,7 @@ import Loading from '../../components/Loading.js';
import UserMessage from '../../components/UserMessage.js';
import { getSelectionFiltersBySearchCriteria, getSelectionFiltersForMongoQuery } from './SelectionFilterHelper.js';
import { clearAvailableTagAction } from '../../actions/logbook.js';
import OverlayBox from '../../components/Event/OverlayBox.js';
/**
* This class represents the event container component. It's role is to retrieve events from the server asynchronuously.
......@@ -73,7 +74,7 @@ class EventContainer extends React.Component {
<UserMessage type={ERROR_MESSAGE_TYPE} message={this.state.errorMessage} />
<EventActionBar
availableTags = {this.props.availableTags}
availableTags={this.props.availableTags}
investigationId={investigationId}
isNewEventVisible={this.state.isNewEventVisible}
numberOfMatchingEventsFound={this.state.foundEventCount}
......@@ -87,14 +88,15 @@ class EventContainer extends React.Component {
view={this.state.view}
/>
<NewEvent
createEvent={this.createEvent}
isVisible={this.state.isNewEventVisible}
investigationId={investigationId}
onNewEventUploaded={this.onNewEventUploaded}
setNewEventVisibility={this.setNewEventVisibility}
user={user}
/>
<OverlayBox open={this.state.isNewEventVisible} classNames={{ overlay: 'newEventOverlayClass', modal: 'newEventModalClass' }}>
<NewEvent
createEvent={this.createEvent}
investigationId={investigationId}
onNewEventUploaded={this.onNewEventUploaded}
setNewEventVisibility={this.setNewEventVisibility}
user={user}
/>
</OverlayBox>
{(!isDataFetched(this)) ?
<Loading message='Loading logbook'></Loading>
......
......@@ -63,8 +63,7 @@ class TagContainer extends React.Component {
}
if (this.state.context === DETAILED_EVENT_CONTEXT || this.state.context === NEW_EVENT_CONTEXT) {
return (<div>
{userMessage}
return (
<TagList
availableTags={this.props.availableTags}
addTagToSelection={this.addTagToSelection}
......@@ -74,7 +73,7 @@ class TagContainer extends React.Component {
removeTagFromSelection={this.removeTagFromSelection}
selectedTags={this.state.selectedTags}
/>
</div>);
);
}
// no event is provided.
......
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