It fixes #187

parent f6c183f4
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, DOC_VIEW, BASIC_EVENT_CONTEXT } from '../../constants/EventTypes';
import { OverlayTrigger, Tooltip, Dropdown, MenuItem, Button } from 'react-bootstrap';
import TagContainer from '../../containers/TagContainer';
require('./event.css');
/**
* A basic event of the logbook
*/
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) {
return (<AnnotationContent event={event} view={view} />);
} else if (event.type === NOTIFICATION) {
return (<NotificationContent event={event} />);
};
} else {
return (<div>
<div style={{ flexGrow: '1', marginLeft: '10px', paddingTop: '4px', paddingBottom: '4px' }} >
<Icon event={event} view={view} />
</div>
<p style={{ margin: '0px', color: '#777777', fontStyle: 'italic' }}>This event has no content</p>
</div>
);
};
};
let { event, toggleMode, view, investigationId } = this.props;
let paddingTopDate = (event.type === ANNOTATION) ? '6px' : '0px';
return (
<div
id='contentDocList'
style={{ display: 'flex' }} >
<Button onClick={() => { this.props.onEventClicked(event); }} />
<div
id={(this.props.isSelected === true) ? 'selectedEvent' : ''}
style={{ flexGrow: '0', flexShrink: '0' }}
>
<OverlayTrigger
placement='right'
overlay={
<Tooltip id='tooltip'>
<p> Event created on {getEventHistoryCreationDate(getOriginalEvent(event))} </p>
</Tooltip>
}>
<div>
<div style={{ paddingTop: paddingTopDate, paddingLeft: '10px', color: '#666666', display: 'inline' }}>
{getEventCreationDate(getOriginalEvent(event))}
</div>
<Dropdown id='dropdown-custom-1' >
<Dropdown.Toggle bsStyle='link' style={{
paddingRight: '2px',
paddingLeft: '4px',
paddingTop: '0px',
paddingBottom: '0px',
backgroundColor: 'transparent',
marginRight: '10px',
color: '#888888'
}}>
</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>
<div style={{ flexGrow: '1', marginLeft: '30px' }}>
{showContent()}
</div>
{/* <div style={{ flexGrow: '1', flexShrink: '0', flexBasis: '100px' }}>
<div style={{ textAlign: 'right' }}>
<TagContainer context={BASIC_EVENT_CONTEXT} investigationId={investigationId} event={event} />
</div>
</div> */}
</div >
);
};
}
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 */
user: PropTypes.object.isRequired,
/* the current view */
view: PropTypes.string.isRequired,
};
const AnnotationContent = (props) => {
let { event, view } = props;
return (
<div style={{ flexGrow: '1', marginLeft: '10px', paddingTop: '4px', paddingBottom: '4px' }} >
<Icon event={event} view={view} />
<EventContentDisplayer
content={event.content}
useRichTextEditor={false}
isEditionMode={false}
/>
</div>
);
};
const NotificationContent = (props) => {
let { event } = props;
let notificationMessage = getOriginalEvent(event);
let renderedCommentContent;
let lastCommentContent = getLastCommentContent(event);
if (lastCommentContent) {
renderedCommentContent = () => (
<div style={{ clear: 'left', marginLeft: '30px', paddingTop: '8px', paddingBottom: '8px' }}>
{/* <div className='pull-left' style={{ paddingRight: '8px' }}>
{getEventIcon('comment', '20')}
</div> */}
<EventContentDisplayer
content={lastCommentContent}
useRichTextEditor={false}
isEditionMode={false}
/>
</div>);
} else { renderedCommentContent = () => null; };
return (
<div style={{ flexGrow: '1', marginLeft: '10px' }} >
<div className='pull-left' style={{ paddingRight: '8px' }}>
{getEventIcon(event.category, '20')}
</div>
<div id='divContainingHTMLNotificationInDocView'>
<EventContentDisplayer
content={notificationMessage.content}
useRichTextEditor={false}
isEditionMode={false}
/>
</div>
{renderedCommentContent()}
</div>);
};
const Icon = (props) => {
let { event, view } = props;
if (view && view === DOC_VIEW) {
return null;
};
return (<div className='pull-left' style={{ paddingRight: '8px' }}>
{getEventIcon(event.category, '20')}
</div>
);
};
export default BasicEvent;
\ No newline at end of file
import React from 'react';
import { READ_MODE, EDIT_MODE, ANNOTATION, NOTIFICATION } from '../../constants/EventTypes';
import BasicEvent from './BasicEvent';
import EditEvent from './EditEvent';
import PropTypes from 'prop-types'
/**
* An event of the logbook
*/
class Event extends React.Component {
constructor(props) {
super(props)
this.state = {
mode: READ_MODE
}
this.toggleMode = this.toggleMode.bind(this);
}
render() {
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}
investigationId={investigationId}
isSelected={this.props.isSelected}
onEventClicked={this.props.onEventClicked}
toggleMode={this.toggleMode}
user={user}
reverseEventsSortingByCreationDate={this.props.reverseEventsSortingByCreationDate}
view={view}
/>
} else if (this.state.mode === EDIT_MODE){}
// return <DetailedEvent
// event={event}
// investigationId={investigationId}
// onEventUpdated={onEventUpdated}
// toggleMode={this.toggleMode}
// user={user}
// updateEvent={this.props.updateEvent}
// />
} else {
console.log("[ERROR] the view is not set. This should not happen.");
return null;
}
}
console.log("[ERROR] event type is unknown or not defined for eventId " + event._id);
return null
}
/**
* Toggle the mode of the event: READ or EDIT
* @param {string} mode the requested new mode of the event
*/
toggleMode(mode) {
if (mode && this.state.mode !== mode) {
this.setState({ mode: mode })
}
}
}
export default Event;
Event.propTypes = {
/** the event object as received from the ICAT+ server */
event: PropTypes.object.isRequired,
/** the investigationId */
investigationId: PropTypes.string,
/* 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
}
......@@ -13,6 +13,7 @@ import { LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_
*/
class EventContentDisplayer extends React.Component {
render() {
let { isEditionMode, user, content, useRichTextEditor, investigationId, onEventModified, storeToLocalStorage } = this.props;
if (content && content instanceof Array && content.length !== 0) {
if (useRichTextEditor !== null && useRichTextEditor !== undefined) {
......@@ -28,8 +29,8 @@ class EventContentDisplayer extends React.Component {
text={HTMLText}
user={user}
/>)
} else if (useRichTextEditor === false) {
return (<div dangerouslySetInnerHTML={{ __html: HTMLText }} />)
} else if (useRichTextEditor === false) {
return (<div style='background-color:red' dangerouslySetInnerHTML={{ __html: HTMLText }} />)
}
}
}
......
......@@ -45,24 +45,39 @@ class EventList extends React.Component {
if (date !== lastDate) {
lastDate = date;
items.push({ text: date, type: "date", anchor: date });
}
}
items.push(eventsCopy[i]);
}
/** Add shadow to events that are before a date */
for (let i = 0; i < items.length; i++) {
if (items[i].type === "date"){
if (items[i - 1]){
items[i - 1].shadowBottomBorder = true;
}
}
}
/** Add shadow to the last one */
if (items.length > 0){
items[items.length -1].shadowBottomBorder = true;
}
return this.collapse(items);
}
render() {
if (!this.props.events || this.props.events.length === 0) {
return null;
}
return <Table responsive style={{ fontSize: '12px' }} >
return <Table responsive style={{ fontSize: '12px' }} style={{borderCollapse: 'collapse'}}>
<tbody>
{this.getItems().map((event, index) => {
if (event.type === "date") {
return <tr key={index}><td style={{ borderTop: '1px solid #f2f2f2', textAlign: 'center', fontSize: '18px', fontWeight: 'bold' }} colSpan={5} ><a name={event.anchor}></a> {event.text}</td></tr>;
return <tr key={index} style={{backgroundColor : '#F0F0F6', color : "gray", height:'50px'}} ><td style={{ textAlign: 'center', fontSize: '18px', fontWeight: 'bold' }} colSpan={6} ><a name={event.anchor}></a> {event.text}<br /></td></tr>;
}
return <Event key={index} availableTags={this.props.availableTags} event={event} logbookContext={this.props.logbookContext} onEventClicked={this.props.onEventClicked} ></Event>
return <Event key={index} availableTags={this.props.availableTags} event={event} logbookContext={this.props.logbookContext} onEventClicked={this.props.onEventClicked} ></Event>
})}
</tbody>
</Table>
......@@ -96,32 +111,57 @@ export class Event extends React.Component {
}
render() {
let events = [this.props.event];
if (this.props.event.events && !this.state.collapsed) {
events = events.concat(this.props.event.events);
};
/** Will print bottom shadow when it is the last event */
var getShadow = (event) => {
if (event.shadowBottomBorder){
return '0px 0 15px -15px rgba(100,100,100, 0.8)';
}
return ' 0px 0px 9px 0px white, 0 9px 0px 0px white, 0 -9px 0px 0px white, 0px 0 15px -4px rgba(100,100,100, 0.8), 0px 0 15px -4px rgba(100,100,100, 0.8)';
}
var getButtonIcon = (event) => {
if (this.props.logbookContext.isReleased === true){
return <Glyphicon glyph='eye-open' />;
}
else{
if ( getPreviousVersionNumber(event) === 0){
return <div><Glyphicon glyph='comment' style={{width:'30px'}} />Comment</div>;
}
return <span><Glyphicon glyph='edit' style={{width:'30px'}}/> Edit</span>;
}
}
return events.map((event, index) => {
return <tr key={index} id='contentDocList'>
<td style={{ width: '16px', borderTop: '0' }}>
return <tr key={index} id='contentDocList' style={{backgroundColor : '#F0F0F6'}}>
<td style={{ width: '16px', border: '0' }}>
<EventIcon event={event} />
</td>
<td style={{ width: '16px', borderTop: '0', borderRight: '1px solid #f2f2f2' }}>
<td style={{ width: '16px', border: '0', borderRight: '0px solid #F0F0F6' }}>
<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>}>
<span style={{ cursor: 'pointer', color: '#999999', margin: '0px' }}>{Moment(getOriginalEvent(event).creationDate).format("HH:mm:ss")} </span>
<span style={{ cursor: 'pointer', color: 'black', margin: '0px' }}>{Moment(getOriginalEvent(event).creationDate).format("HH:mm:ss")} </span>
</OverlayTrigger>
</td>
<td style={{ border: 0 }}>
<LazyContentEvent event={event} />
{event.events && this.state.collapsed ? <Label style={{ color: "blue", backgroundColor: "white", cursor: "pointer" }} onClick={this.handleClick} >.... {event.events.length} command lines more</Label> : null}
<td style={{ width: '16px', border : 0}}>
</td>
<td className="eventActionBox" style={{ paddingBottom: 0, border : 0, backgroundColor: 'white', boxShadow:getShadow(event)}}>
<div style={{marginLeft: '20px', backgroundColor: 'white'}}>
<LazyContentEvent event={event} />
{event.events && this.state.collapsed ? <Label style={{ color: "blue", backgroundColor: "#F8F8F8", cursor: "pointer" }} onClick={this.handleClick} >.... {event.events.length} command lines more</Label> : null}
</div>
</td>
<td style={{ width: '200px', border: 0 }}>
<TagListInLine tags={getTags(event, this.props.availableTags)} />
</td>
<td style={{ width: '50px', border: 0 }}>
<Button bsStyle="link" bsSize="small" style={{ padding: '0px' }} onClick={() => this.props.onEventClicked(event)}>
<Glyphicon glyph={this.props.logbookContext.isReleased === true ? 'eye-open' : getPreviousVersionNumber(event) === 0 ? 'plus' : 'edit'} style={{ width: '40px', position: 'static' }} />
<Button bsStyle="default" bsSize="small" style={{ width: '100px', position: 'static', padding: '0px' }} onClick={() => this.props.onEventClicked(event)}>
{getButtonIcon(event)}
</Button>
</td>
</tr>;
......@@ -168,10 +208,10 @@ class LazyContentEvent extends React.Component {
/** For performance only events with images are lazy loaded */
if (content.indexOf("img") !== -1) {
return <LazyLoad once>
<div dangerouslySetInnerHTML={{ __html: content }} />
<div dangerouslySetInnerHTML={{ __html: content }} />
</LazyLoad>;
}
return <div dangerouslySetInnerHTML={{ __html: content }} />;
return <div dangerouslySetInnerHTML={{ __html: content }} />;
} else {
return <div style={{ fontStyle: 'italic', color: '#888888' }}> There is no content </div>
}
......
......@@ -81,16 +81,11 @@
width : 250px;
}
.eventActionBox{
clear: right;
float: right;
padding-top: 2px;
padding-right: 3px;
padding-bottom: 0px;
padding-left: 3px;
border-radius: 5px
.eventActionBox{
}
.eventActionBox:hover{
cursor: 'pointer';
}
......@@ -83,7 +83,7 @@ class InvestigationContainer extends Component {
}
}
fetchData(sessionId) {
fetchData(sessionId) {
if (this.props.doi != null) {
if (sessionId) {
this.props.fetchDatasetsByDOI(sessionId, this.props.doi);
......@@ -121,7 +121,7 @@ class InvestigationContainer extends Component {
this.props.history.push(addressBar);
}
render() {
render() {
/** Array with ID for the rows that will be expanded by default */
let expanded = [];
/** Search proposal */
......
......@@ -79,7 +79,7 @@ export class LogbookContainer extends React.Component {
const selectionFilter = getSelectionFiltersForMongoQuery(this.state.userSearchCriteria, this.state.sortingFilter, this.state.view);
if (this.isAppProperlyConfigured()) {
return (
<div style={{ marginBottom: '40px' }}>
......
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