Commit bd943d2f authored by Alejandro De Maria Antolinos's avatar Alejandro De Maria Antolinos
Browse files

Merge branch 'issue_255' into 'master'

Issue 521

Closes #521

See merge request !540
parents ca438466 8b8890c6
Pipeline #52967 passed with stages
in 4 minutes and 39 seconds
......@@ -17,6 +17,7 @@ import SampleTrackingStatsPage from './containers/Stats/SampleTracking/SampleTra
import SearchPage from './containers/SearchPage';
import OpenDataPage from './containers/OpenData/OpenDataPage';
import ClosedDataPage from './containers/ClosedData/ClosedDataPage';
import InvestigationProposalPage from './containers/InvestigationProposalPage';
import DatasetsPage from './containers/DatasetsPage';
import TagPage from './containers/TagPage';
import EventsPage from './containers/EventsPage';
......@@ -189,6 +190,10 @@ function App() {
<Route path="/investigation/:investigationId/parcel/:parcelId">
<ParcelPage />
</Route>
<Route path="/investigation/:investigationId/proposal">
<InvestigationProposalPage />
</Route>
</LoadingBoundary>
</Route>
......
import React from 'react';
import { Glyphicon } from 'react-bootstrap';
import moment from 'moment';
import DOIBadge from '../doi/DOIBadge';
import ResponsiveTable from '../Table/ResponsiveTable';
import InvestigationWidget from './InvestigationWidget';
import {
beamlineFormatter,
startDateFormatter,
......@@ -220,7 +218,7 @@ function InvestigationTable(props) {
const totalSize = data && data.length > 0 ? data[0].meta?.page?.total : 0;
const user = useSelector((state) => state.user);
const { sessionId, isAdministrator } = user;
const { isAdministrator } = user;
function handleStartDateChange(date) {
setStartDate(date);
......@@ -255,38 +253,6 @@ function InvestigationTable(props) {
setPage(1);
}
const expandRow = {
showExpandColumn: true,
expandColumnPosition: 'right',
expandHeaderColumnRenderer: ({ isAnyExpands }) => {
if (isAnyExpands) {
return (
<span style={{ fontSize: 18 }}>
<Glyphicon glyph="zoom-out" />
</span>
);
}
return (
<span style={{ fontSize: 18 }}>
<Glyphicon glyph="zoom-in" />
</span>
);
},
expandColumnRenderer: ({ expanded }) => {
if (expanded) {
return <Glyphicon glyph="zoom-out" />;
}
return <Glyphicon glyph="zoom-in" />;
},
renderer: (investigation) => (
<InvestigationWidget
investigation={investigation}
sessionId={sessionId}
user={user}
/>
),
};
return (
<>
<div className={styles.wrapper}>
......@@ -327,7 +293,6 @@ function InvestigationTable(props) {
withUserPortalLink ||
(UI.userPortal.isLinkEnabled && isAdministrator),
})}
expandRow={expandRow}
handleTableChange={handleTableChange}
onSearch={onSearch}
delay={1250}
......
import React from 'react';
import { Panel, Tab, Tabs, Well } from 'react-bootstrap';
import SamplesTable from './SamplesTable';
import ParticipantsPanel from './ParticipantsPanel';
import LoadingBoundary from '../LoadingBoundary';
function InvestigationWidget(props) {
const { investigation, user } = props;
return (
<Panel>
<Panel.Body>
<h2>{investigation.title}</h2>
<Well>
<h4>Abstract</h4>
<p>{investigation.summary}</p>
</Well>
<Tabs id="tabs">
<Tab style={{ margin: 30 }} eventKey={1} title="Participants">
<LoadingBoundary message="Loading participants...">
<ParticipantsPanel
investigationId={investigation.id}
name={user.name}
/>
</LoadingBoundary>
</Tab>
<Tab style={{ margin: 30 }} eventKey={2} title="Samples">
<LoadingBoundary message="Loading samples">
<SamplesTable investigationId={investigation.id} />
</LoadingBoundary>
</Tab>
</Tabs>
</Panel.Body>
<Panel.Footer></Panel.Footer>
</Panel>
);
}
export default InvestigationWidget;
......@@ -131,7 +131,12 @@ function ParticipantsPanel(props) {
keyField="id"
data={investigationUsers}
columns={[
{ text: 'id', dataField: 'id', hidden: true, searchable: false },
{
text: 'id',
dataField: 'id',
hidden: true,
searchable: false,
},
{
text: 'Name',
dataField: 'fullName',
......
import React from 'react';
import { Well } from 'react-bootstrap';
import { INVESTIGATION_DATE_FORMAT } from '../../constants';
import DOIBadge from '../doi/DOIBadge';
import { dateFormatter } from './utils';
function ProposalPanel(props) {
const { investigation } = props;
return (
<>
<h4>{investigation.title} </h4>
<div>
<p className="text-secondary">
{dateFormatter(investigation.startDate, 'DD/MM/YYYY hh:mm', false)}
{investigation.endDate && (
<>
{' '}
-{' '}
{dateFormatter(
investigation.endDate,
'DD/MM/YYYY hh:mm',
false
)}{' '}
</>
)}{' '}
{investigation.instrument && (
<>- on beamline: {investigation.instrument.name} </>
)}
{investigation.releaseDate && (
<>
- release date:{' '}
{dateFormatter(
investigation.releaseDate,
INVESTIGATION_DATE_FORMAT,
false
)}
</>
)}
{investigation.doi && (
<>
{' '}
<DOIBadge doi={investigation.doi} />
</>
)}
</p>
</div>
<Well>
<h4>Abstract</h4>
<p>{investigation.summary}</p>
</Well>
</>
);
}
export default ProposalPanel;
import React from 'react';
import { Panel, Glyphicon } from 'react-bootstrap';
import LoadingBoundary from '../LoadingBoundary';
import SamplesTable from './SamplesTable';
function SamplesPanel(props) {
const { investigationId } = props;
return (
<Panel bsStyle="info">
<Panel.Heading>
<Panel.Title componentClass="h3">
{' '}
<Glyphicon glyph="th-list" /> Samples
</Panel.Title>
</Panel.Heading>
<Panel.Body>
<LoadingBoundary message="Loading samples">
<SamplesTable investigationId={investigationId} />
</LoadingBoundary>
</Panel.Body>
</Panel>
);
}
export default SamplesPanel;
import React from 'react';
import React, { useEffect, useRef } from 'react';
import { Badge, Glyphicon, Nav, NavItem } from 'react-bootstrap';
import { useSelector } from 'react-redux';
import { useSelector, useDispatch } from 'react-redux';
import { useParams } from 'react-router';
import { LinkContainer } from 'react-router-bootstrap';
import UI from '../../config/ui';
import { useResource } from 'rest-hooks';
import InvestigationResource from '../../resources/investigation';
import { setInvestigationBreadCrumbs } from '../../containers/investigation-breadcrumbs';
function TabContainerMenu(props) {
const { doi } = props;
const { isAnonymous } = useSelector((state) => state.user);
const datasetCount = useSelector((state) => state.datasets.data.length);
const { investigationId } = useParams();
const breadcrumbsList = useSelector((state) => state.breadcrumbsList);
const currentBreadcrumbsList = useRef(); // work around stale breadcrumbsList reference
currentBreadcrumbsList.current = breadcrumbsList;
const investigation = useResource(InvestigationResource.detailShape(), {
id: investigationId,
});
const dispatch = useDispatch();
useEffect(() => {
if (investigation) {
dispatch(
setInvestigationBreadCrumbs(
investigation,
currentBreadcrumbsList.current
)
);
}
}, [dispatch, investigation, currentBreadcrumbsList]); // eslint-disable-line react-hooks/exhaustive-deps
const routePrefix = `/investigation/${investigationId}`;
return (
<Nav bsStyle="tabs">
{UI.investigationContainer.isDatasetListVisible && (
<LinkContainer to={doi ? `/public/${doi}` : `${routePrefix}/datasets`}>
<NavItem eventKey="datasets" href="">
<Glyphicon glyph="list" />
<span style={{ marginLeft: 2 }}> Dataset List &nbsp;</span>
<Badge bsClass="ourBadges-m"> {datasetCount} </Badge>
</NavItem>
</LinkContainer>
)}
{!doi && (
<>
<LinkContainer to={`${routePrefix}/events`}>
<NavItem eventKey="events" href="">
<Glyphicon glyph="comment" />
<span style={{ marginLeft: 2 }}> Logbook </span>
<>
<Nav bsStyle="tabs">
{UI.investigationContainer.isDatasetListVisible && (
<LinkContainer
to={doi ? `/public/${doi}` : `${routePrefix}/datasets`}
>
<NavItem eventKey="datasets" href="">
<Glyphicon glyph="list" />
<span style={{ marginLeft: 2 }}> Dataset List &nbsp;</span>
<Badge bsClass="ourBadges-m"> {datasetCount} </Badge>
</NavItem>
</LinkContainer>
)}
{!doi && (
<>
<LinkContainer to={`${routePrefix}/events`}>
<NavItem eventKey="events" href="">
<Glyphicon glyph="comment" />
<span style={{ marginLeft: 2 }}> Logbook </span>
</NavItem>
</LinkContainer>
{UI.sampleTracking.enabled && !isAnonymous && (
<>
<LinkContainer to={`${routePrefix}/shipping`}>
<NavItem eventKey="shipping" href="">
<Glyphicon glyph="plane" />
<span style={{ marginLeft: 2 }}> Shipping </span>
</NavItem>
</LinkContainer>
</>
)}
</>
)}
</Nav>
{UI.sampleTracking.enabled && !isAnonymous && (
<>
<LinkContainer to={`${routePrefix}/shipping`}>
<NavItem eventKey="shipping" href="">
<Glyphicon glyph="plane" />
<span style={{ marginLeft: 2 }}> Shipping </span>
</NavItem>
</LinkContainer>
</>
)}
</>
)}
{!isAnonymous && (
<>
<LinkContainer to={`${routePrefix}/proposal`}>
<NavItem eventKey="summary" href="">
<Glyphicon glyph="cog" />
<span style={{ marginLeft: 2 }}> Proposal </span>
</NavItem>
</LinkContainer>
</>
)}
</Nav>
</>
);
}
......
import React, { useEffect, useRef } from 'react';
import React, { useEffect } from 'react';
import { Col, Grid, Row, Alert } from 'react-bootstrap';
import { useParams } from 'react-router';
import { useDispatch, useSelector } from 'react-redux';
......@@ -9,7 +9,6 @@ import PageNotFound from './PageNotFound';
import { fetchDatasetsByInvestigationId } from '../actions/datasets';
import { useResource } from 'rest-hooks';
import InvestigationResource from '../resources/investigation';
import { setInvestigationBreadCrumbs } from './investigation-breadcrumbs';
function DatasetsPage() {
const { investigationId } = useParams();
......@@ -19,32 +18,13 @@ function DatasetsPage() {
const sessionId = useSelector((state) => state.user.sessionId);
const datasets = useSelector((state) => state.datasets);
const breadcrumbsList = useSelector((state) => state.breadcrumbsList);
const currentBreadcrumbsList = useRef(); // work around stale breadcrumbsList reference
currentBreadcrumbsList.current = breadcrumbsList;
const dispatch = useDispatch();
/* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
dispatch(fetchDatasetsByInvestigationId(sessionId, investigationId));
if (investigation) {
dispatch(
setInvestigationBreadCrumbs(
investigation,
currentBreadcrumbsList.current
)
);
}
// `investigation` object can be duplicated in store, so we use `investigation.id` as effect dependency
}, [
dispatch,
investigationId,
sessionId,
investigation?.id,
currentBreadcrumbsList,
]);
}, [dispatch, investigationId, sessionId, investigation?.id]);
if (!investigation) {
return <PageNotFound />;
......
import React from 'react';
import { Col, Grid, Row } from 'react-bootstrap';
import { useParams } from 'react-router';
import { useSelector } from 'react-redux';
import TabContainerMenu from '../components/TabContainerMenu/TabContainerMenu';
import PageNotFound from './PageNotFound';
import { useResource } from 'rest-hooks';
import InvestigationResource from '../resources/investigation';
import ParticipantsPanel from '../components/Investigation/ParticipantsPanel';
import SamplesPanel from '../components/Investigation/SamplesPanel';
import ProposalPanel from '../components/Investigation/ProposalPanel';
function InvestigationProposalPage() {
const { investigationId } = useParams();
const user = useSelector((state) => state.user);
const investigation = useResource(InvestigationResource.detailShape(), {
id: investigationId,
});
if (!investigation) {
return <PageNotFound />;
}
return (
<Grid fluid>
<Row>
<Col sm={12}>
<TabContainerMenu />
<div style={{ margin: 20 }}>
<ProposalPanel investigation={investigation} />
</div>
<div style={{ margin: 20 }}>
<ParticipantsPanel
investigationId={investigationId}
name={user.name}
/>
</div>
<div style={{ margin: 20 }}>
<SamplesPanel investigationId={investigationId} />
</div>
</Col>
</Row>
</Grid>
);
}
export default InvestigationProposalPage;
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