Commit c7cb910d authored by Alejandro De Maria Antolinos's avatar Alejandro De Maria Antolinos

Comming issue_93

parents 4af8c98e 8005c3eb
{
"name": "E-dataPortal",
"version": "0.1.0",
"private": true,
"dependencies": {
"@tinymce/tinymce-react": "^2.2.6",
"ajv": "^6.0.0",
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"bootstrap-auto-dismiss-alert": "^1.0.2",
"escape-string-regexp": "^1.0.5",
"formdata-polyfill": "^3.0.12",
"image-extensions": "^1.1.0",
"immutable": "^3.8.1",
"is-url": "^1.2.4",
"jquery": "^3.3.1",
"lodash": "^4.17.11",
"ls": "^0.2.1",
"moment": "^2.22.1",
"qhistory": "^1.0.0",
"rc-checkbox": "^2.1.5",
"react": "^16.3.2",
"react-bootstrap": "^0.32.1",
"react-bootstrap-button-loader": "^1.0.11",
"react-bootstrap-table": "^4.3.1",
"react-bootstrap-tooltip-button": "^1.0.6",
"react-combo-search": "git://github.com/Max-Z80/react-combo-search.git",
"react-dom": "^16.3.2",
"react-loader-advanced": "^1.7.1",
"react-moment": "^0.7.0",
"react-popup": "^0.9.3",
"react-redux": "^5.0.7",
"react-router": "^4.2.0",
"react-router-bootstrap": "^0.24.4",
"react-router-dom": "^4.2.2",
"react-scripts": "1.1.4",
"react-spinners": "^0.3.2",
"reactjs-popup": "^1.1.1",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-persist": "^5.9.1",
"redux-promise-middleware": "^5.1.1",
"redux-thunk": "^2.2.0",
"tinymce": "^4.8.2",
"treeview-react-bootstrap": "^0.4.6"
},
"peerDependencies": {},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "jest --watchAll",
"eject": "react-scripts eject"
},
"devDependencies": {
"enzyme": "^3.4.4",
"enzyme-adapter-react-16": "^1.2.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^23.5.0",
"react-doc-generator": "^1.2.5"
},
"jest": {
"moduleNameMapper": {
"\\.(css|less)$": "identity-obj-proxy"
"name": "E-dataPortal",
"version": "0.1.0",
"private": true,
"dependencies": {
"@tinymce/tinymce-react": "^2.2.6",
"ajv": "^6.0.0",
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"bootstrap-auto-dismiss-alert": "^1.0.2",
"escape-string-regexp": "^1.0.5",
"formdata-polyfill": "^3.0.12",
"image-extensions": "^1.1.0",
"immutable": "^3.8.1",
"is-url": "^1.2.4",
"jquery": "^3.3.1",
"lodash": "^4.17.11",
"ls": "^0.2.1",
"moment": "^2.22.1",
"qhistory": "^1.0.0",
"rc-checkbox": "^2.1.5",
"react": "^16.3.2",
"react-bootstrap": "^0.32.1",
"react-bootstrap-button-loader": "^1.0.11",
"react-bootstrap-table": "^4.3.1",
"react-bootstrap-tooltip-button": "^1.0.6",
"react-combo-search": "git://github.com/Max-Z80/react-combo-search.git",
"react-dom": "^16.3.2",
"react-loader-advanced": "^1.7.1",
"react-moment": "^0.7.0",
"react-popup": "^0.9.3",
"react-redux": "^5.0.7",
"react-router": "^4.2.0",
"react-router-bootstrap": "^0.24.4",
"react-router-dom": "^4.2.2",
"react-scripts": "1.1.4",
"react-spinners": "^0.3.2",
"reactjs-popup": "^1.1.1",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-persist": "^5.9.1",
"redux-promise-middleware": "^5.1.1",
"redux-thunk": "^2.2.0",
"tinymce": "^4.8.2",
"treeview-react-bootstrap": "^0.4.6"
},
"peerDependencies": {},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "jest --watchAll",
"eject": "react-scripts eject"
},
"devDependencies": {
"enzyme": "^3.4.4",
"enzyme-adapter-react-16": "^1.2.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^23.5.0",
"react-doc-generator": "^1.2.5"
},
"jest": {
"moduleNameMapper": {
"\\.(css|less)$": "identity-obj-proxy",
"\\.(gif)$": "<rootDir>/tests/fileMock.js"
}
}
}
}
\ No newline at end of file
......@@ -43,7 +43,7 @@ export function updateEvent(newEvent, sessionId, investigationId, onSuccess) {
console.log("the event was modified successfully on ICAT+ server.");
localStorage.removeItem('plainText');
localStorage.removeItem('HTMLText');
onSuccess();
onSuccess(response.data);
})
.catch(function (error) {
console.log(error);
......
......@@ -2,10 +2,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { getOriginalEvent, getEventIcon, getLastCommentContent, getEventCreationDate, getEventHistoryCreationDate, getContent } from '../../helpers/EventHelpers'
import EventContentDisplayer from './EventContentDisplayer';
import { ANNOTATION, NOTIFICATION, EDIT_MODE, LIST_VIEW, DOC_VIEW } from '../../constants/EventTypes';
import { ANNOTATION, NOTIFICATION, EDIT_MODE, DOC_VIEW } from '../../constants/EventTypes';
import { OverlayTrigger, Tooltip } from "react-bootstrap";
import { OverlayTrigger, Tooltip, Dropdown, MenuItem } from 'react-bootstrap';
require('./event.css');
/**
......@@ -13,6 +14,7 @@ import { OverlayTrigger, Tooltip } from "react-bootstrap";
*/
class BasicEvent extends React.Component {
render() {
function showContent() {
if (event.content && (getContent(event.content, 'plainText') !== null || getContent(event.content, 'html') !== null)) {
if (event.type === ANNOTATION) {
......@@ -26,7 +28,7 @@ class BasicEvent extends React.Component {
<Icon event={event} view={view} />
</div>
<p style={{ margin:'0px' , color: '#777777', fontStyle: 'italic' }}>This event has no content</p>
<p style={{ margin: '0px', color: '#777777', fontStyle: 'italic' }}>This event has no content</p>
</div>
)
}
......@@ -38,9 +40,12 @@ class BasicEvent extends React.Component {
return (
<div
id="contentDocList"
onClick={() => { toggleMode(EDIT_MODE) }}
onDoubleClick={() => { toggleMode(EDIT_MODE) }}
style={{ display: 'flex' }} >
<div style={{ flexGrow: '0' }}>
<div
id={(this.props.isSelected === true) ? "selectedEvent" : ""}
style={{ flexGrow: '0', flexShrink: '0' }}
>
<OverlayTrigger
placement="right"
overlay={
......@@ -49,9 +54,20 @@ class BasicEvent extends React.Component {
</Tooltip>
}>
<div>
<div style={{ paddingTop: paddingTopDate, paddingLeft: '10px', color: '#666666' }}>
<div style={{ paddingTop: paddingTopDate, paddingLeft: '10px', color: '#666666', display: 'inline' }}>
{getEventCreationDate(getOriginalEvent(event))}
</div>
<Dropdown id="dropdown-custom-1" >
<Dropdown.Toggle bsStyle="forEventDatesDropdown">
</Dropdown.Toggle >
<Dropdown.Menu className="super-colors">
<MenuItem eventKey="1" onClick={() => this.props.reverseEventsSortingByCreationDate(this.props.event._id)} >
Reverse sort and highlight this event.
</MenuItem>
</Dropdown.Menu>
</Dropdown>
</div>
</OverlayTrigger>
</div>
......@@ -66,6 +82,8 @@ class BasicEvent extends React.Component {
BasicEvent.propTypes = {
/* the event object as received from the ICAT+ server */
event: PropTypes.object.isRequired,
/** whether this event is selected or not */
isSelected: PropTypes.bool,
/* callback functon which trigger a change to another mode */
toggleMode: PropTypes.func.isRequired,
/** the user who is currently logged in */
......
......@@ -144,8 +144,9 @@ class DetailedEvent extends React.Component {
}
/** Callback executed when the event has been successfully updated on the server side*/
onSuccessfullyUpdated() {
this.props.reloadEvents();
onSuccessfullyUpdated(updatedEvent) {
this.props.toggleMode(READ_MODE); //this makes sure the mode is changed in case the event is updated.
this.props.onEventUpdated(updatedEvent)
}
/**
......@@ -232,8 +233,8 @@ DetailedEvent.propTypes = {
event: PropTypes.object.isRequired,
/** the investigationId which the events belong to. */
investigationId: PropTypes.string.isRequired,
/* callback function which triggers the reloading of the event list*/
reloadEvents: PropTypes.func.isRequired,
/**Callback function triggered when the user updated an existing event */
onEventUpdated: PropTypes.func,
/* Callback function used to change from one mode to the other READ_MODE vs EDIT_MODE*/
toggleMode: PropTypes.func.isRequired,
/** the user who is currently logged in */
......
import React from 'react';
import { LIST_VIEW, DOC_VIEW, READ_MODE, EDIT_MODE, ANNOTATION, NOTIFICATION } from '../../constants/EventTypes';
import { READ_MODE, EDIT_MODE, ANNOTATION, NOTIFICATION } from '../../constants/EventTypes';
import BasicEvent from './BasicEvent';
import DetailedEvent from './DetailedEvent';
import PropTypes from 'prop-types'
/**
* An event of the logbook
*/
......@@ -18,21 +17,24 @@ class Event extends React.Component {
this.toggleMode = this.toggleMode.bind(this);
}
render() {
let { event, investigationId, reloadEvents, user, view } = this.props;
let { investigationId, user, view, event, onEventUpdated } = this.props;
if (event.type && (event.type === ANNOTATION || event.type === NOTIFICATION)) {
if (view) {
if (this.state.mode === READ_MODE) {
return <BasicEvent
event={event}
isSelected={this.props.isSelected}
toggleMode={this.toggleMode}
user={user}
reverseEventsSortingByCreationDate={this.props.reverseEventsSortingByCreationDate}
view={view}
/>
} else if (this.state.mode === EDIT_MODE)
return <DetailedEvent
event={event}
investigationId={investigationId}
reloadEvents={reloadEvents}
onEventUpdated={onEventUpdated}
toggleMode={this.toggleMode}
user={user}
/>
......@@ -54,6 +56,7 @@ class Event extends React.Component {
this.setState({ mode: mode })
}
}
}
export default Event;
......@@ -62,18 +65,16 @@ export default Event;
Event.propTypes = {
/** the event object as received from the ICAT+ server */
event: PropTypes.object.isRequired,
/** the investigationId */
investigationId: PropTypes.string,
/* Callback function which reloads the event list*/
reloadEvents: PropTypes.func.isRequired,
/* whether this event is selected or not*/
isSelected: PropTypes.bool,
/* Callback function triggered when the user updated an event */
onEventUpdated: PropTypes.func,
/* callback function which reverse how events are sorted */
reverseEventsSortingByCreationDate: PropTypes.func,
/** the user who is currently logged in */
user: PropTypes.object.isRequired,
/* the view the event is in */
view: PropTypes.string
}
/**
* Default values for this component
*/
Event.defaultProps = {
view: DOC_VIEW
};
......@@ -3,7 +3,9 @@ import { Well, Button, ButtonToolbar, Glyphicon, Tooltip, OverlayTrigger, Grid,
import { getPDF } from '../../api/icat/icatPlus'
import { ComboSearch } from 'react-combo-search'
import PropTypes from 'prop-types';
import { LIST_VIEW, DOC_VIEW, NEW_EVENT_VISIBLE } from '../../constants/EventTypes';
import { DOC_VIEW, LIST_VIEW, NEW_EVENT_VISIBLE, SORT_EVENTS_FROM_YOUNGEST, SORT_EVENTS_FROM_OLDEST } from '../../constants/EventTypes';
import { GUI_CONFIG } from '../../config/gui.config';
// styles
require('./react-datetime.css');
......@@ -17,16 +19,25 @@ class EventActionBar extends React.Component {
constructor(props) {
super(props);
this.onSearch = this.onSearch.bind(this);
this.sortByDate = this.sortByDate.bind(this);
}
render() {
const { investigationId,
isShowingNewEvent,
numberOfMatchingEventsFound,
reloadEvents,
sessionId,
setNewEventVisibility,
setView } = this.props;
setView,
sortingFilter } = this.props;
function getCurrentlyPressedSortButton() {
if (sortingFilter && sortingFilter.createdAt) {
return sortingFilter.createdAt
}
}
let defaultSortingOrder = (GUI_CONFIG().DEFAULT_SORTING_FILTER) ? GUI_CONFIG().DEFAULT_SORTING_FILTER.createdAt : 1;
return (
<Grid fluid={true} style={{ marginTop: '10px' }}>
......@@ -55,15 +66,61 @@ class EventActionBar extends React.Component {
</Tooltip>
}>
<ButtonToolbar style={{ display: 'inline-block' }}>
<ToggleButtonGroup type="radio" name="view" defaultValue={1}>
<ToggleButton value={1} onClick={() => setView(LIST_VIEW)}><Glyphicon glyph="list" /> List</ToggleButton>
<ToggleButton value={2} onClick={() => setView(DOC_VIEW)}><Glyphicon glyph="list-alt" /> Doc </ToggleButton>
<ToggleButtonGroup
defaultValue={1}
name="view"
type="radio"
value={this.props.view}
>
<ToggleButton bsSize="small" value={LIST_VIEW} onClick={() => setView(LIST_VIEW)}><Glyphicon glyph="list" /> List</ToggleButton>
<ToggleButton bsSize="small" value={DOC_VIEW} onClick={() => setView(DOC_VIEW)}><Glyphicon glyph="list-alt" /> Doc </ToggleButton>
</ToggleButtonGroup>
</ButtonToolbar>
</OverlayTrigger>
</Col>
<Col xs={2}>
<ButtonToolbar style={{ display: 'inline-block' }}>
<ToggleButtonGroup
defaultValue={defaultSortingOrder}
name="sort"
type="radio"
value={getCurrentlyPressedSortButton()}
>
<ToggleButton
bsSize="small"
onClick={() => this.sortByDate(SORT_EVENTS_FROM_YOUNGEST)}
value={SORT_EVENTS_FROM_YOUNGEST}
>
<OverlayTrigger placement="right"
overlay={
<Tooltip id="tooltip3">
<p> Sort events chronologically from youngest to oldest </p>
</Tooltip>
}>
<Glyphicon glyph="sort-by-attributes-alt" />
</OverlayTrigger>
</ToggleButton>
<ToggleButton
bsSize="small"
onClick={() => this.sortByDate(SORT_EVENTS_FROM_OLDEST)}
value={SORT_EVENTS_FROM_OLDEST}
>
<OverlayTrigger placement="right"
overlay={
<Tooltip id="tooltip3">
<p> Sort events chronologically from oldest to youngest </p>
</Tooltip>
}>
<Glyphicon glyph="sort-by-attributes" />
</OverlayTrigger>
<Col xs={8} xsPush={0}>
</ToggleButton>
</ToggleButtonGroup>
</ButtonToolbar>
</Col>
<Col xs={6} xsPush={0}>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<div style={{ flexGrow: '0', minWidth: '55px', maxWidth: '90px' }} >
<p style={{ marginTop: '4px' }}> Search: </p>
......@@ -88,6 +145,13 @@ class EventActionBar extends React.Component {
onSearch(data) {
return this.props.searchEvents(data);
}
sortByDate(sortingOrder) {
if (sortingOrder && this.props.sortingFilter.createdAt !== sortingOrder) {
//this.setState({ sortingOrder: sortingOrder })
this.props.reverseEventsSortingByCreationDate();
}
}
}
/**
......@@ -138,14 +202,18 @@ EventActionBar.propTypes = {
isShowingNewEvent: PropTypes.bool,
/** the number of events found */
numberOfMatchingEventsFound: PropTypes.number,
/** callback function which reverse the sorting of events by date */
reverseEventsSortingByCreationDate: PropTypes.func.isRequired,
/** Callback function which reloads the events based on search criteria*/
searchEvents: PropTypes.func,
/* the sessionId*/
sessionId: PropTypes.string.isRequired,
/** Callback function triggered when the user clicks on the new event button */
setNewEventVisibility: PropTypes.func,
/** The current session Id */
sessionId: PropTypes.string.isRequired,
/** the callback function executed when the user clicks the view buttons */
setView: PropTypes.func,
/** the filter used to sort event */
sortingFilter: PropTypes.object.isRequired
}
export default EventActionBar;
\ No newline at end of file
//react
import React from 'react';
import { getFileByEventIdHTTPRequest } from '../../api/icat/icatPlus'
import { connect } from 'react-redux';
/**
* Handles how a event which category is File is viewed
*/
class EventFileViewer extends React.Component {
render() {
if (this.props.event.contentType.search("image") !== -1) {
return (
<div>
<a href={getFileByEventIdHTTPRequest(this.props.event.investigationId, this.props.event._id, this.props.user.sessionId)} target='_blank'> <img width={100} src={getFileByEventIdHTTPRequest(this.props.event.investigationId, this.props.event._id, this.props.user.sessionId)} alt={this.props.event.filename} /> </a> <span> {this.props.event.text} </span>
</div>)
}
if (this.props.event.contentType.search("pdf") !== -1) {
return (
<div>
<a href={getFileByEventIdHTTPRequest(this.props.event.investigationId, this.props.event._id, this.props.user.sessionId)} target='_blank'> <img width={100} src="/pdfLogo.png" alt={this.props.event.filename} /> </a> <span> {this.props.event.text} </span>
</div>)
}
}
}
function mapStateToProps(state) {
return {
user: state.user,
};
}
export default connect(
mapStateToProps,
)(EventFileViewer);
\ No newline at end of file
import React from 'react'
import PropTypes from 'prop-types'
import { Panel, Row, Col } from 'react-bootstrap'
import { getOriginalEvent, getContent, getEventIcon, getEventCreationDate, getTag, EXPANDED_VIEW_MODE, getFirstLettersofContent } from '../../helpers/EventHelpers'
import {ANNOTATION, NOTIFICATION} from '../../constants/EventTypes'
/**
* This class represents a collapsed event header
*/
export class EventHeaderCollapsed extends React.Component {
render() {
let event = this.props.event
let originalEvent = getOriginalEvent(event);
let typeSpecificColumn;
let typeSpecificColumn2;
if (!event.type) {
typeSpecificColumn = <AnnotationSpecificColumn event={event} toggleMode={this.props.toggleMode} />
} else if (event.type === ANNOTATION) {
typeSpecificColumn = <AnnotationSpecificColumn event={event} toggleMode={this.props.toggleMode} />
typeSpecificColumn2 = <AnnotationSpecificColumn2 event={event} />
} else if (event.type === NOTIFICATION) {
typeSpecificColumn = <NotificationSpecificColumn event={event} toggleMode={this.props.toggleMode} />
typeSpecificColumn2 = '';
}
return (<Panel.Heading bsClass='collapsedEventPanel' >
<Row >
<Col xs={1}>
<div style={{ position: 'absolute', right: '30px' }} > {getEventCreationDate(originalEvent)} </div>
</Col>
<Col xs={1}>
{getEventIcon(originalEvent.category)}
</Col>
{typeSpecificColumn}
{typeSpecificColumn2}
<Col xs={2}>
{getTag(event)}
</Col>
</Row>
</Panel.Heading>
)
}
}
const AnnotationSpecificColumn = (props) => {
return (
<Col xs={2}>
<span style={{ cursor: 'pointer', color: '#007bff' }} onClick={() => { props.toggleMode(EXPANDED_VIEW_MODE) }}> {props.event.title || "User comment"} </span>
</Col>
)
}
export const AnnotationSpecificColumn2 = (props) => {
let nbCharacterToDisplay = 100;
let firstLettersOfContent = '';
if (props.event) {
firstLettersOfContent = getFirstLettersofContent(props.event.content, nbCharacterToDisplay);
} else {
firstLettersOfContent = '';
}
return (
<Col xs={6}>
<div id='firstLettersOfContent'
style={{
background: 'linear-gradient(to right, #999999, #ffffff)', webkitBackgroundClip: 'text', webkitTextFillColor: 'transparent'
}}>
{firstLettersOfContent}
</div>
</Col>
)
}
const NotificationSpecificColumn = (props) => {
let originalEvent = getOriginalEvent(props.event);
let plainText = getContent(originalEvent.content, 'plainText');
if (!plainText) {
//this event has no plain text (should not happen)
plainText = 'No content'
}
return (
<Col xs={8}>
<span style={{ cursor: 'pointer', color: '#007bff' }} onClick={() => { props.toggleMode(EXPANDED_VIEW_MODE) }}> {plainText} </span>
</Col>
)
}
EventHeaderCollapsed.propTypes = {
/* the event*/
event: PropTypes.object.isRequired
}
import { LIST_VIEW, DOC_VIEW } from '../../constants/EventTypes';
import { DOC_VIEW } from '../../constants/EventTypes';
import React from 'react'
import ReactDOM from 'react-dom'
import { Grid, Row, Col, OverlayTrigger, Tooltip } from 'react-bootstrap'
import { Grid, Row, OverlayTrigger, Tooltip } from 'react-bootstrap'
import PropTypes from 'prop-types'
import _ from 'lodash'
import Moment from 'moment'
import EventActionBar from './EventActionBar'
import { getOriginalEvent } from '../../helpers/EventHelpers'
import Event from './Event';
......@@ -26,12 +25,11 @@ class EventList extends React.Component {
this.state = {
verticalBarLength: '0px',
isShowingNewEvent: false,
events: this.props.events, // the displayed (ie filtered) event list. The original list is in this.props.eventList
}
this.adjustVerticalBarLength = this.adjustVerticalBarLength.bind(this);
this.handlePageChanged = this.handlePageChanged.bind(this);
// this.onEventUpdated = this.onEventUpdated.bind(this);
}
/**
......@@ -45,10 +43,6 @@ class EventList extends React.Component {
this.adjustVerticalBarLength();
}
handlePageChanged(event) {
this.setState({ activePage: Number(event.currentTarget.id) });
}
render() {
const { investigationId, user, view, events, reloadEvents } = this.props;
......@@ -71,7 +65,9 @@ class EventList extends React.Component {
<Event
event={event}
investigationId={investigationId}
reloadEvents={reloadEvents}
isSelected={event._id && event._id === this.props.selectedEventId}
onEventUpdated={this.props.onEventUpdated}
reverseEventsSortingByCreationDate={this.props.reverseEventsSortingByCreationDate}
user={user}
view={view}
/>
......@@ -98,7 +94,7 @@ class EventList extends React.Component {
width: '2px',
background: '#CCCCCC',
zIndex: '1',
marginLeft: '100px',
marginLeft: '120px',
}} />
</Row>
{eventsAndDates}
......@@ -121,23 +117,25 @@ class EventList extends React.Component {
}
}
}
const TimeAxisMarks = (props) => {
let userView = props.userView; // the view the user has chossen 'doc' or 'monitoring'
let userView = props.userView; // the view the user has choosen 'doc' or 'monitoring'
if (userView == DOC_VIEW) {
/* to be removed */
return (<div style={{ marginTop: '10px', marginBottom: '10px' }}>
<OverlayTrigger placement="right" overlay={<Tooltip id="tooltip"> <p> Events created on {props.value} </p> </Tooltip>}>
<span style={{ color: '#777777', marginLeft: '0px', fontStyle: 'italic', fontSize: '16px' }}> {Moment(props.value).format("MMM D")} </span>
<span style={{ color: '#999999', marginLeft: '10px', fontStyle: 'italic', fontSize: '16px' }}> <strong> {Moment(props.value).format("MMM D")} </strong> </span>
</OverlayTrigger>
</div>)
} else {
// used in 'monitoring view'
return (<div style={{ marginTop: '10px', marginBottom: '10px' }}>
<OverlayTrigger placement="right" overlay={<Tooltip id="tooltip"> <p> Events created on {props.value} </p> </Tooltip>}>
<span style={{ color: '#777777', marginLeft: '0px', fontStyle: 'italic', fontSize: '16px' }}> {Moment(props.value).format("MMM D")} </span>
<span style={{ color: '#999999', marginLeft: '0px', fontStyle: 'italic', fontSize: '16px' }}> <strong> {Moment(props.value).format("MMM D")} </strong> </span>
</OverlayTrigger>
</div>
)
......@@ -149,13 +147,16 @@ EventList.propTypes = {
events: PropTypes.array,
/** the investigationId the provided events belong to. */
investigationId: PropTypes.string.isRequired,
/* Callback function triggered when the user updated an event */