Commit 2b5925b8 authored by Maxime Chaillet's avatar Maxime Chaillet

Merge branch 'issue157' into 'master'

Issue157

Closes #157

See merge request !136
parents 02467665 b040f58f
...@@ -3,7 +3,7 @@ import { Breadcrumb, Label } from 'react-bootstrap'; ...@@ -3,7 +3,7 @@ import { Breadcrumb, Label } from 'react-bootstrap';
export class BreadCrumbs extends React.Component { export class BreadCrumbs extends React.Component {
render() { render() {
var items = []; var items = [];
if (this.props.breadcrumbsList) { if (this.props.breadcrumbsList) {
if (this.props.breadcrumbsList.items) { if (this.props.breadcrumbsList.items) {
...@@ -12,18 +12,18 @@ export class BreadCrumbs extends React.Component { ...@@ -12,18 +12,18 @@ export class BreadCrumbs extends React.Component {
} }
/** breadCrumbsSize is used to mark as active the latest item in the list */ /** breadCrumbsSize is used to mark as active the latest item in the list */
var breadCrumbsSize = items.length; var breadCrumbsSize = items.length;
return (<Breadcrumb style={{ backgroundColor: '#bfbfbf', marginTop: -20, borderBotton: '1px solid #f2f2f2', fontSize: '14px' }}> return (<Breadcrumb style={{ backgroundColor: '#bfbfbf', marginTop: -20, borderBotton: '1px solid #f2f2f2', fontSize: '14px' }}>
{items.map(function (breadcrumb, i) { {items.map(function (breadcrumb, i) {
if (i === 0) { if (i === 0) {
return <Breadcrumb.Item style={{ marginLeft: '40px' }} href={breadcrumb.link}> {breadcrumb.name} </Breadcrumb.Item>; return <Breadcrumb.Item key={i} style={{ marginLeft: '40px' }} href={breadcrumb.link}> {breadcrumb.name} </Breadcrumb.Item>;
} }
if (breadCrumbsSize === (i + 1)) { if (breadCrumbsSize === (i + 1)) {
return <Breadcrumb.Item active href={breadcrumb.link}> return <Breadcrumb.Item key={i} active href={breadcrumb.link}>
<Label style={{ fontSize: '12px' }}>{breadcrumb.badge}</Label> {breadcrumb.name} </Breadcrumb.Item>; <Label style={{ fontSize: '12px' }}>{breadcrumb.badge}</Label> {breadcrumb.name} </Breadcrumb.Item>;
} }
return <Breadcrumb.Item href={breadcrumb.link}> {breadcrumb.name} </Breadcrumb.Item>; return <Breadcrumb.Item key={i} href={breadcrumb.link}> {breadcrumb.name} </Breadcrumb.Item>;
})} })}
</Breadcrumb>) </Breadcrumb>)
......
...@@ -54,7 +54,7 @@ class EventActionBar extends React.Component { ...@@ -54,7 +54,7 @@ class EventActionBar extends React.Component {
expanded={this.state.isNavbarExpanded} expanded={this.state.isNavbarExpanded}
onSelect={this.onSelectNavbar} onSelect={this.onSelectNavbar}
onToggle={this.onToggleNavbar} onToggle={this.onToggleNavbar}
style={{ background: 'none', border: 'none', webkitBoxShadow: 'none', boxShadow: 'none' }}> style={{ background: 'none', border: 'none', WebkitBoxShadow: 'none', boxShadow: 'none' }}>
<Navbar.Header> <Navbar.Header>
<Navbar.Toggle /> <Navbar.Toggle />
......
import React from 'react'; import React from 'react';
import { EDIT_EVENT_CONTEXT, ANNOTATION, NOTIFICATION, NEW_EVENT_CONTEXT, PLAINTEXT_CONTENT_FORMAT, LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT, HTML_CONTENT_FORMAT, LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT } from '../../constants/EventTypes'; import { EDIT_EVENT_CONTEXT, ANNOTATION, NOTIFICATION, NEW_EVENT_CONTEXT, PLAINTEXT_CONTENT_FORMAT, LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT, HTML_CONTENT_FORMAT, LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT } from '../../constants/EventTypes';
import { Label, FormControl, InputGroup } from 'react-bootstrap';
import EventContentDisplayer from './EventContentDisplayer'; import EventContentDisplayer from './EventContentDisplayer';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { getOriginalEvent, getPreviousVersionNumber, } from '../../helpers/EventHelpers'; import { getPreviousVersionNumber } from '../../helpers/EventHelpers';
import HTMLEditor from './HTMLEditor'; import HTMLEditor from './HTMLEditor';
/**
* React component which render the content panel of an event
*/
class EventContentPanel extends React.Component { class EventContentPanel extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
if (props.event) { this.eventId = props.event._id; }; //required for component will unmount in EDIT_EVENT_CONTEXT if (props.event) { this.eventId = props.event._id; }; //required for component will unmount in EDIT_EVENT_CONTEXT
} }
render() { render() {
let { event, context, getEditorHeight, investigationId, user, onEventModified } = this.props; let { event, context, investigationId, user, onEventModified } = this.props;
if (context === EDIT_EVENT_CONTEXT) { if (context === EDIT_EVENT_CONTEXT) {
if (event) { if (event) {
if (event.type === ANNOTATION) { if (event.type === ANNOTATION) {
...@@ -30,13 +31,15 @@ class EventContentPanel extends React.Component { ...@@ -30,13 +31,15 @@ class EventContentPanel extends React.Component {
} }
if (event.type === NOTIFICATION) { if (event.type === NOTIFICATION) {
return (<NotificationContent return (<EventContentDisplayer
onEventModified={onEventModified} content={getPreviousVersionNumber(event) === 0 ? [{ format: 'html', text: '<p> </p>' }] : event.content}
event={event} eventId={event._id}
investigationId={investigationId} investigationId={investigationId}
isEditionMode={true}
onEventModified={onEventModified}
storeToLocalStorage={this.storeToLocalStorage} storeToLocalStorage={this.storeToLocalStorage}
user={user} useRichTextEditor={true}
/>); user={user} />);
} }
} }
} else if (context === NEW_EVENT_CONTEXT) { } else if (context === NEW_EVENT_CONTEXT) {
...@@ -99,142 +102,4 @@ EventContentPanel.proptype = { ...@@ -99,142 +102,4 @@ EventContentPanel.proptype = {
investigationId: PropTypes.string, investigationId: PropTypes.string,
/* user who is using this component */ /* user who is using this component */
user: PropTypes.object, user: PropTypes.object,
} }
\ No newline at end of file
// /**
// * React component which represents the content of an annotation
// * @param {*} props the props passed to this component
// */
// class AnnotationContent extends React.Component {
// constructor(props) {
// super(props);
// // this.state = {
// // inputTitleValue: this.props.event.title || ''
// // };
// //this.onChangeInputValue = this.onChangeInputValue.bind(this);
// }
// // onChangeInputValue(e) {
// // this.setState({ inputTitleValue: e.target.value });
// // }
// render() {
// let { event, investigationId, storeToLocalStorage, user } = this.props;
// if (event.type && event.type === ANNOTATION) {
// return (
// <div>
// <EventContentDisplayer
// onEventModified={this.props.onEventModified}
// content={event.content}
// eventId={event._id}
// investigationId={investigationId}
// isEditionMode={true}
// storeToLocalStorage={storeToLocalStorage}
// useRichTextEditor={true}
// user={user}
// />
// {/* <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'
// ref={this.props.setTitleInput}
// />
// </InputGroup>
// </div> */}
// </div>
// );
// };
// }
// componentDidUpdate() {
// this.props.onEventModified();
// }
// }
// AnnotationContent.propTypes = {
// /* the callback function which activates the save button */
// onEventModified: PropTypes.func.isRequired,
// /* The event to be shown */
// event: PropTypes.object.isRequired,
// /* the investigationId */
// investigationId: PropTypes.string.isRequired,
// /* the callback function which adds a ref to this */
// setTitleInput: PropTypes.func.isRequired,
// /* the user */
// user: PropTypes.object.isRequired
// };
/**
* React component which represents the content of an notification
* @param {*} props the props passed to this component
*/
const NotificationContent = (props) => {
let { event, getEditorHeight, investigationId, user } = props;
let notificationMessage = getOriginalEvent(event);
if (event.type && event.type === NOTIFICATION) {
let editorContent;
if (getPreviousVersionNumber(event) === 0) {
let fakeContent = [{ format: 'html', text: '<p> </p>' }];
editorContent = (<EventContentDisplayer
onEventModified={props.onEventModified}
content={fakeContent}
eventId={event._id}
investigationId={investigationId}
isEditionMode={true}
storeToLocalStorage={props.storeToLocalStorage}
useRichTextEditor={true}
user={user}
/>);
} else {
editorContent = (<EventContentDisplayer
onEventModified={props.onEventModified}
content={event.content}
eventId={event._id}
investigationId={investigationId}
isEditionMode={true}
storeToLocalStorage={props.storeToLocalStorage}
useRichTextEditor={true}
user={user}
/>);
};
return (
<div>
<div style={{ marginLeft: '10px' }} >
<div id='divContainingHTMLNotificationInDocView'>
<EventContentDisplayer
content={notificationMessage.content}
eventId={event._id}
isEditionMode={false}
storeToLocalStorage={props.storeToLocalStorage}
useRichTextEditor={false}
/>
</div>
</div>
{editorContent}
</div>
);
};
};
NotificationContent.propTypes = {
/* the callback function which activates the save button */
onEventModified: PropTypes.func.isRequired,
/* The event to be shown */
event: PropTypes.object.isRequired,
/* the investigationId */
investigationId: PropTypes.string.isRequired,
/* the user */
user: PropTypes.object.isRequired
};
\ No newline at end of file
...@@ -36,19 +36,19 @@ class EventList extends React.Component { ...@@ -36,19 +36,19 @@ class EventList extends React.Component {
return ( return (
<div> <div>
<div class="sidenav"> <div className="sidenav">
<EventTimeLine events={this.props.events}></EventTimeLine> <EventTimeLine events={this.props.events}></EventTimeLine>
</div> </div>
<div class="main"> <div className="main">
<Table responsive style={{ fontSize: '12px' }} > <Table responsive style={{ fontSize: '12px' }} >
<tbody style={{ borderRight: '1px solid #F9F9F9' }}> <tbody style={{ borderRight: '1px solid #F9F9F9' }}>
{this.getItems().map((event, index) => { {this.getItems().map((event, index) => {
if (event.type === "date") { if (event.type === "date") {
return <tr><td style={{ borderTop: '1px solid #f2f2f2', textAlign: 'center', fontSize: '18px', fontWeight: 'bold' }} colSpan={3} ><a name={event.anchor}></a> {event.text}</td></tr>; return <tr key={index}><td style={{ borderTop: '1px solid #f2f2f2', textAlign: 'center', fontSize: '18px', fontWeight: 'bold' }} colSpan={3} ><a name={event.anchor}></a> {event.text}</td></tr>;
} }
return <tr> return <tr key={index}>
<td style={{ width: '16px', borderTop: '0' }}> <td style={{ width: '16px', borderTop: '0' }}>
<EventIcon event={event} /> <Glyphicon glyph='edit' onClick={() => { this.props.onEventClicked(event); }} /> <EventIcon event={event} /> <Glyphicon glyph='edit' onClick={() => { this.props.onEventClicked(event); }} />
</td> </td>
<td style={{ width: '16px', borderTop: '0', borderRight: '1px solid #f2f2f2' }}> <td style={{ width: '16px', borderTop: '0', borderRight: '1px solid #f2f2f2' }}>
<OverlayTrigger placement="right" overlay={<Tooltip id="tooltip"> <p> Events created on {Moment(getOriginalEvent(event).creationDate).format("MMMM Do YYYY, h:mm:ss a")} </p> </Tooltip>}> <OverlayTrigger placement="right" overlay={<Tooltip id="tooltip"> <p> Events created on {Moment(getOriginalEvent(event).creationDate).format("MMMM Do YYYY, h:mm:ss a")} </p> </Tooltip>}>
......
...@@ -5,7 +5,7 @@ import _ from 'lodash' ...@@ -5,7 +5,7 @@ import _ from 'lodash'
import Moment from 'moment' import Moment from 'moment'
import { getContent, convertImagesToThumbnails } from '../../../helpers/EventHelpers'; import { getContent, convertImagesToThumbnails } from '../../../helpers/EventHelpers';
import { getOriginalEvent } from '../../../helpers/EventHelpers' import { getOriginalEvent } from '../../../helpers/EventHelpers'
import { VerticalTimeline, VerticalTimelineElement } from 'react-vertical-timeline-component'; import { VerticalTimeline, VerticalTimelineElement } from 'react-vertical-timeline-component';
import 'react-vertical-timeline-component/style.min.css'; import 'react-vertical-timeline-component/style.min.css';
import { getEventIcon } from '../../../helpers/EventHelpers'; import { getEventIcon } from '../../../helpers/EventHelpers';
import CategoryIcon from './CategoryIcon.js'; import CategoryIcon from './CategoryIcon.js';
...@@ -14,101 +14,104 @@ require("./eventList.css"); ...@@ -14,101 +14,104 @@ require("./eventList.css");
/** /**
* The list of the all events * The list of the all events
*/ */
class EventTimeLine extends React.Component { class EventTimeLine extends React.Component {
/** Returns the list of days and statistics */ /** Returns the list of days and statistics */
getItems(){ getItems() {
var days = {}; var days = {};
for (var i = 0; i < this.props.events.length; i++){ for (var i = 0; i < this.props.events.length; i++) {
var date = Moment(getOriginalEvent(this.props.events[i]).creationDate).format("MMMM Do YYYY"); var date = Moment(getOriginalEvent(this.props.events[i]).creationDate).format("MMMM Do YYYY");
if (days[date] == null){ if (days[date] == null) {
days[date] = { days[date] = {
commandLine : 0, commandLine: 0,
info : 0, info: 0,
error : 0, error: 0,
comment : 0 comment: 0
}; };
} }
switch(this.props.events[i].category){ switch (this.props.events[i].category) {
case "commandLine": case "commandLine":
days[date].commandLine = days[date].commandLine + 1; days[date].commandLine = days[date].commandLine + 1;
break; break;
case "error": case "error":
days[date].error = days[date].error + 1; days[date].error = days[date].error + 1;
break; break;
case "info": case "info":
days[date].info = days[date].info + 1; days[date].info = days[date].info + 1;
break; break;
case "comment": case "comment":
days[date].comment = days[date].comment + 1; days[date].comment = days[date].comment + 1;
break; break;
} }
} }
return days; return days;
} }
getNode(category, items, key){ getNode(category, items, key) {
if (items[key][category] != 0){ if (items[key][category] != 0) {
return <td style={{width:'25px'}}> return <td style={{ width: '25px' }}>
{items[key][category]} {items[key][category]}
</td>; </td>;
} }
return <td style={{width:'25px'}}></td>; return <td style={{ width: '25px' }}></td>;
} }
getNodeIcon(category, items, key){ getNodeIcon(category, items, key) {
if (items[key][category] != 0){ if (items[key][category] != 0) {
return <td style={{width:'25px'}}> return <td style={{ width: '25px' }}>
<CategoryIcon category={category}> </CategoryIcon> <CategoryIcon category={category}> </CategoryIcon>
</td>; </td>;
} }
return <td style={{width:'25px'}}></td>; return <td style={{ width: '25px' }}></td>;
} }
render() { render() {
if (!this.props.events || this.props.events.length === 0) { if (!this.props.events || this.props.events.length === 0) {
return null; return null;
} }
var items = this.getItems(); var items = this.getItems();
return ( return (
<VerticalTimeline layout='one-column' className='vertical-time-line-custom-general' animate={false}> <VerticalTimeline layout='1-column' className='vertical-time-line-custom-general' animate={false}>
{ Object.keys(items).map((key, index) => { {Object.keys(items).map((key, index) => {
return <VerticalTimelineElement return <VerticalTimelineElement
className="vertical-timeline-element-custom" className="vertical-timeline-element-custom"
iconStyle={{ top:'15px',left:'15px',width:'10px', height:'10px', background: 'rgb(33, 150, 243)', color: '#ccc' }}> key={key}
<div> iconStyle={{ top: '15px', left: '15px', width: '10px', height: '10px', background: 'rgb(33, 150, 243)', color: '#ccc' }}>
<a href={'#' + key}> {key}</a> <div>
<table style={{fontSize:'14px'}}> <a href={'#' + key}> {key}</a>
<tr> <table style={{ fontSize: '14px' }}>
{this.getNode("commandLine", items, key)} <tbody>
{this.getNodeIcon("commandLine", items, key)} <tr>
{this.getNode("error", items, key)} {this.getNode("commandLine", items, key)}
{this.getNodeIcon("error", items, key)} {this.getNodeIcon("commandLine", items, key)}
{this.getNode("info", items, key)} {this.getNode("error", items, key)}
{this.getNodeIcon("info", items, key)} {this.getNodeIcon("error", items, key)}
{this.getNode("comment", items, key)} {this.getNode("info", items, key)}
{this.getNodeIcon("comment", items, key)} {this.getNodeIcon("info", items, key)}
</tr> {this.getNode("comment", items, key)}
</table> {this.getNodeIcon("comment", items, key)}
</div> </tr>
</VerticalTimelineElement>; </tbody>
</table>
})} </div>
</VerticalTimeline> </VerticalTimelineElement>;
})}
</VerticalTimeline>
) )
} }
} }
EventTimeLine.propTypes = { EventTimeLine.propTypes = {
/** the array of unsorted events as provided by the ICAT+ server */ /** the array of unsorted events as provided by the ICAT+ server */
events: PropTypes.array events: PropTypes.array
} }
export default EventTimeLine; export default EventTimeLine;
...@@ -17,6 +17,7 @@ class OverlayBox extends React.Component { ...@@ -17,6 +17,7 @@ class OverlayBox extends React.Component {
render() { render() {
return (<Modal return (<Modal
classNames={this.props.classNames} classNames={this.props.classNames}
onClose={() => null}
onEntered={this.onEntered} onEntered={this.onEntered}
onExited={this.onExited} onExited={this.onExited}
open={this.props.open} open={this.props.open}
......
...@@ -91,7 +91,7 @@ class LogbookContainer extends React.Component { ...@@ -91,7 +91,7 @@ class LogbookContainer extends React.Component {
view={this.state.view} view={this.state.view}
/> />
<OverlayBox open={this.state.isNewEventVisible === true || this.state.eventBeingEdited} classNames={{ overlay: 'newOrEditOverlayClass', modal: 'newOrEditModalClass' }}> <OverlayBox open={this.state.isNewEventVisible === true || (this.state.eventBeingEdited ? true : false)} classNames={{ overlay: 'newOrEditOverlayClass', modal: 'newOrEditModalClass' }}>
<div style={{ height: this.getPanelHeightInPercent(NEW_EVENT_CONTEXT), paddingBottom: this.state.eventBeingEdited ? '5px' : '0px' }}> <div style={{ height: this.getPanelHeightInPercent(NEW_EVENT_CONTEXT), paddingBottom: this.state.eventBeingEdited ? '5px' : '0px' }}>
{this.state.isNewEventVisible === true ? {this.state.isNewEventVisible === true ?
<NewOrEditEventPanel <NewOrEditEventPanel
...@@ -262,13 +262,13 @@ class LogbookContainer extends React.Component { ...@@ -262,13 +262,13 @@ class LogbookContainer extends React.Component {
/** /**
* Set the visibility of the edit event panel * Set the visibility of the edit event panel
* @param {string} visibility the requested visibility * @param {string} newVisibility the requested visibility
*/ */
setEditEventVisibility = (visibility) => { setEditEventVisibility = (newVisibility) => {
if (visibility) { if (newVisibility) {
if (visibility === EDIT_EVENT_VISIBLE) { if (newVisibility === EDIT_EVENT_VISIBLE) {
//this.setState({ isNewEventVisible: true }); //this.setState({ isNewEventVisible: true });
} else if (visibility === EDIT_EVENT_INVISIBLE) { } else if (newVisibility === EDIT_EVENT_INVISIBLE) {
this.setState({ eventBeingEdited: null }); this.setState({ eventBeingEdited: null });
} }
}; };
......
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