Commit 208cc9b7 authored by Axel Bocciarelli's avatar Axel Bocciarelli

Fix selection and mint pages

parent 5c2d2c5d
Pipeline #33789 passed with stage
in 2 minutes and 51 seconds
......@@ -157,8 +157,13 @@ function App() {
</LoadingBoundary>
</Route>
<Route exact path="/selection" component={SelectionPage} />
<Route exact path="/selection/mint" component={MintSelectionPage} />
<Route exact path="/selection">
<SelectionPage />
</Route>
<Route exact path="/selection/mint">
<MintSelectionPage />
</Route>
{user.isAdministrator && (
<Route exact path="/manager/stats">
......
import {
ADD_DATASET_BY_ID,
ADD_INVESTIGATION_BY_ID,
REMOVE_DATASET_BY_ID,
REMOVE_INVESTIGATION_BY_ID,
} from '../constants/actionTypes';
export function addInvestigationById(investigationId) {
return function (dispatch) {
dispatch({
type: ADD_INVESTIGATION_BY_ID,
payload: investigationId,
});
};
}
export function removeInvestigationById(investigationId) {
return function (dispatch) {
dispatch({
type: REMOVE_INVESTIGATION_BY_ID,
payload: investigationId,
});
};
}
export function removeDatasetById(datasetId) {
return function (dispatch) {
dispatch({
......
......@@ -214,7 +214,7 @@ class DatasetTable extends React.Component {
const selectRow = {
mode: 'checkbox',
clickToSelect: false,
selected: this.props.selection.datasetIds,
selected: this.props.selectedDatasetIds,
onSelectAll: this.handleOnSelectAll,
onSelect: this.handleOnSelect,
classes: 'selection-row',
......@@ -233,11 +233,7 @@ class DatasetTable extends React.Component {
<Glyphicon glyph={expanded ? 'zoom-out' : 'zoom-in'} />
),
renderer: (dataset) => (
<DatasetWidget
dataset={dataset}
sessionId={this.props.sessionId}
selection={this.props.selection}
/>
<DatasetWidget dataset={dataset} sessionId={this.props.sessionId} />
),
};
......
......@@ -72,6 +72,20 @@ function Menu() {
<NavItem eventKey="my">My Data</NavItem>
</LinkContainer>
{UI.menu.isMySelectionVisible && selection.datasetIds.length > 0 && (
<LinkContainer to="/selection">
<NavItem eventKey="selection">
My Selection
<span
className="badge"
style={{ marginLeft: 10, padding: '2px 7px' }}
>
{selection.datasetIds.length}
</span>
</NavItem>
</LinkContainer>
)}
{UI.menu.isOpenDataVisible && (
<LinkContainer to="/public">
<NavItem eventKey="open" href="/public">
......@@ -88,17 +102,6 @@ function Menu() {
</LinkContainer>
)}
{UI.menu.isMySelectionVisible && selection.datasetIds.length > 0 && (
<LinkContainer to="/selection">
<NavItem eventKey="selection">
My Selection
<span className="badge" style={{ marginLeft: 10 }}>
{selection.datasetIds.length}
</span>
</NavItem>
</LinkContainer>
)}
{UI.sampleTracking.enabled && !isAnonymous && (
<NavDropdown
eventKey={3}
......
......@@ -35,11 +35,8 @@ class DOIForm extends React.Component {
this.authorCount = 0;
}
/**
* Add an author to the table
*/
addAuthor(investigationUser) {
const authors = this.state.authors;
const authors = [...this.state.authors];
if (!investigationUser.fullName) {
authors.push({
name: this.name.value,
......@@ -135,20 +132,22 @@ class DOIForm extends React.Component {
renderButton() {
return (
<SplitButton
id="add-author"
bsStyle="default"
title="Add author"
style={{ width: 100 }}
onClick={this.addAuthor}
>
{this.props.investigationUsers.map(function (user) {
{this.props.investigationUsers.map((user) => {
const bsStyleRole =
user.role === USER_ROLES.PrincipalInvestigator
? 'primary'
: 'default';
return (
<MenuItem
style={{ width: 350 }}
key={`${user.fullName} ${user.investigationId} ${user.role}`}
eventKey={user}
style={{ width: 350 }}
onSelect={this.addAuthor}
>
<span style={{ marginLeft: 10 }}>{user.fullName} </span>
......@@ -161,7 +160,6 @@ class DOIForm extends React.Component {
</MenuItem>
);
}, this)}
<MenuItem divider />
</SplitButton>
);
}
......@@ -201,7 +199,7 @@ class DOIForm extends React.Component {
</Panel.Heading>
<Panel.Body>
<Form inline>
<Form inline componentClass="div">
<FormGroup controlId="formInlineName">
<ControlLabel>Name</ControlLabel>{' '}
<FormControl
......
......@@ -33,8 +33,6 @@ export const SET_LOGBOOK_CONTEXT = 'SET_LOGBOOK_CONTEXT';
/** selection */
export const ADD_DATASET_BY_ID = 'ADD_DATASET_BY_ID';
export const REMOVE_DATASET_BY_ID = 'REMOVE_DATASET_BY_ID';
export const ADD_INVESTIGATION_BY_ID = 'ADD_INVESTIGATION_BY_ID';
export const REMOVE_INVESTIGATION_BY_ID = 'REMOVE_INVESTIGATION_BY_ID';
/** breadcrumbs */
export const SET_BREADCRUMBS = 'SET_BREADCRUMBS';
......
import axios from 'axios';
import { uniq } from 'lodash-es';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import React, { useEffect, useState } from 'react';
import { Col, Grid, Panel, Row } from 'react-bootstrap';
import BootstrapTable2 from 'react-bootstrap-table-next';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { doSignIn } from '../../actions/login';
import { addDatasetById, removeDatasetById } from '../../actions/selection';
import { useDispatch, useSelector } from 'react-redux';
import {
getDatasetsById,
getUsersByInvestigationIds,
} from '../../api/icat-plus/catalogue';
import DOIForm from '../../components/doi/DOIForm';
import Loader from '../../components/Loader';
import { PERSPECTIVE } from '../../constants';
class MintSelectionPage extends Component {
constructor(props) {
super(props);
this.state = {
investigationId: this.props.match.params.id,
username: this.props.user.username,
sessionId: this.props.user.sessionId,
datasets: [],
filtered: [],
fetching: false,
fetched: false,
datasetIds: this.props.selection.datasetIds,
investigationUsers: [],
};
}
/*
groupBy = function (xs, key) {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
parametersToDatasetObject = function (parametersGroupedByInvestigationId) {
let datasets = {};
for (var datasetId in parametersGroupedByInvestigationId) {
for (var index in parametersGroupedByInvestigationId[datasetId]) {
var param = parametersGroupedByInvestigationId[datasetId][index];
var key = param[5];
var value = param[6];
if (datasets[datasetId] == null) {
datasets[datasetId] = {};
}
datasets[datasetId][key] = value;
datasets[datasetId]["id"] = param[0];
datasets[datasetId]["name"] = param[1];
datasets[datasetId]["startDate"] = param[2];
datasets[datasetId]["endDate"] = param[3];
datasets[datasetId]["investigationName"] = param[4];
datasets[datasetId]["location"] = param[8];
datasets[datasetId]["investigationId"] = param[9];
}
}
var array = [];
for (var ds in datasets) {
array.push(datasets[ds]);
}
return array;
};
*/
onLogbookButtonClicked() {
this.setState({
perspective: PERSPECTIVE.Events,
});
}
import { setBreadCrumbs } from '../../actions/breadcrumbs';
function MintSelectionPage() {
const sessionId = useSelector((state) => state.user.sessionId);
const datasetIds = useSelector((state) => state.selection.datasetIds);
const dispatch = useDispatch();
const [state, setState] = useState({
datasets: [],
users: [],
isFetching: false,
});
const { datasets, users, isFetching: fetching } = state;
useEffect(() => {
dispatch(
setBreadCrumbs([
{ name: 'My Selection', link: '/selection' },
{ name: 'Mint DOI' },
])
);
componentDidMount() {
this.retrieveSelectedDatasetsFromDatabase();
}
async function fetchDatasetsAndUsers() {
const datasets = await axios.get(getDatasetsById(sessionId, datasetIds));
getUsers(investigationIds) {
this.setState({
fetching: true,
});
const investigationIds = datasets.data.map((d) => d.investigation.id);
const users = await axios.get(
getUsersByInvestigationIds(sessionId, [...new Set(investigationIds)])
);
axios
.get(getUsersByInvestigationIds(this.state.sessionId, investigationIds))
.then((res) => {
const investigationUsers = res.data;
this.setState({
investigationUsers,
fetching: false,
fetched: true,
});
})
.catch((error) => {
console.log(error);
});
}
retrieveSelectedDatasetsFromDatabase() {
/*if (!this.state.fetching) {
this.setState({
fetching: true
});
}*/
if (this.props.selection.datasetIds.length > 0) {
axios
.get(
getDatasetsById(this.state.sessionId, this.props.selection.datasetIds)
)
.then((res) => {
try {
const datasets = res.data;
this.setState({
datasets,
filtered: datasets,
fetching: false,
fetched: true,
});
this.getUsers(uniq(datasets.map((o) => o.investigation.id)));
} catch (error) {
console.log(error);
}
})
.catch((error) => {
console.log(error);
});
} else {
this.setState({
datasets: [],
filtered: [],
fetching: false,
setState({
datasets: datasets.data,
users: users.data,
isFetching: false,
});
}
}
render() {
/*if (this.props.selection.datasetIds.length !== this.state.datasets.length) {
this.retrieveSelectedDatasetsFromDatabase();
}*/
if (datasetIds.length > 0) {
setState({ datasets: [], users: [], isFetching: true });
fetchDatasetsAndUsers();
}
}, [datasetIds, dispatch, sessionId]);
return (
<Grid fluid style={{ margin: 60 }}>
<Row className="show-grid">
<Col xs={8}>
return (
<div className="app__inner">
<Grid fluid>
<Row>
<Col md={7}>
<Panel bsStyle="primary">
<Panel.Heading>
<strong>Please fill in this form</strong>
</Panel.Heading>
<Panel.Body>
{this.state.fetching ? (
{fetching ? (
<Loader message="Loading authors..." inPanel />
) : (
<DOIForm
investigationUsers={this.state.investigationUsers}
sessionId={this.props.user.sessionId}
datasets={this.state.datasets}
sessionId={sessionId}
datasets={datasets}
investigationUsers={users}
/>
)}
</Panel.Body>
</Panel>
</Col>
<Col xs={4}>
<Panel bsStyle="primary">
<Col md={5}>
<Panel bsStyle="info">
<Panel.Heading>
<strong>Dataset List</strong>
</Panel.Heading>
<Panel.Body>
<BootstrapTable2
keyField="id"
data={this.state.datasets}
columns={[
{ dataField: 'id', text: '', hidden: true },
{ dataField: 'name', text: 'Name' },
{ dataField: 'investigationName', text: 'Proposal' },
{ dataField: 'definition', text: 'Technique' },
]}
pageOptions={{
paginationSize: 10,
sizePerPage: 25,
showTotal: true,
hidePageListOnlyOnePage: true,
}}
striped
condensed
noDataIndication="This is no data to display"
/>
{fetching ? (
<Loader message="Loading datasets..." inPanel />
) : (
<BootstrapTable2
keyField="id"
data={datasets}
columns={[
{ dataField: 'id', text: '', hidden: true },
{ dataField: 'name', text: 'Name' },
{
dataField: 'investigation.name',
text: 'Proposal',
headerStyle: () => ({ width: 120 }),
},
]}
pageOptions={{
paginationSize: 10,
sizePerPage: 25,
showTotal: true,
hidePageListOnlyOnePage: true,
}}
striped
condensed
noDataIndication="This is no data to display"
/>
)}
</Panel.Body>
</Panel>
</Col>
</Row>
</Grid>
);
}
</div>
);
}
function mapStateToProps(state) {
return {
user: state.user,
events: state.events,
selection: state.selection,
};
}
function mapDispatchToProps(dispatch) {
return {
removeDatasetById: bindActionCreators(removeDatasetById, dispatch),
addDatasetById: bindActionCreators(addDatasetById, dispatch),
doSignIn: bindActionCreators(doSignIn, dispatch),
};
}
MintSelectionPage.propTypes = {
perspective: PropTypes.oneOf([
PERSPECTIVE.Datasets,
PERSPECTIVE.Files,
PERSPECTIVE.Events,
]),
};
export default connect(mapStateToProps, mapDispatchToProps)(MintSelectionPage);
export default MintSelectionPage;
import axios from 'axios';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import React, { useState, useEffect } from 'react';
import {
Button,
ButtonToolbar,
......@@ -8,150 +7,83 @@ import {
OverlayTrigger,
Tooltip,
} from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { useSelector, useDispatch } from 'react-redux';
import { setBreadCrumbs } from '../../actions/breadcrumbs';
import { doSignIn, doLogOut } from '../../actions/login';
import { addDatasetById, removeDatasetById } from '../../actions/selection';
import { getDatasetsById } from '../../api/icat-plus/catalogue';
import DatasetTable from '../../components/Dataset/DatasetTable';
import Loader from '../../components/Loader';
import { PERSPECTIVE } from '../../constants';
import { LinkContainer } from 'react-router-bootstrap';
class SelectionPage extends Component {
constructor(props) {
super(props);
function SelectionPage() {
const sessionId = useSelector((state) => state.user.sessionId);
const datasetIds = useSelector((state) => state.selection.datasetIds);
const dispatch = useDispatch();
this.state = {
investigationId: this.props.investigationId,
username: this.props.user.username,
sessionId: this.props.user.sessionId,
datasets: [],
filtered: [],
fetching: true,
datasetIds: this.props.selection.datasetIds,
};
}
const [initialDatsetIds] = useState(datasetIds);
const [state, setState] = useState({ datasets: [], isFetching: false });
componentDidMount() {
this.retrieveSelectedDatasetsFromDatabase();
this.props.setBreadCrumbs([{ name: 'Selection' }]);
}
useEffect(() => {
dispatch(setBreadCrumbs([{ name: 'My Selection' }]));
if (initialDatsetIds.length > 0) {
setState({ datasets: [], isFetching: true });
retrieveSelectedDatasetsFromDatabase() {
if (this.props.selection.datasetIds.length > 0) {
axios
.get(
getDatasetsById(this.state.sessionId, this.props.selection.datasetIds)
)
.then((res) => {
this.setState({
datasets: res.data,
filtered: res.data,
fetching: false,
});
})
.catch((error) => {
if (error.response) {
if (error.response.status === 401) {
//this.props.doSignIn();
}
}
.get(getDatasetsById(sessionId, initialDatsetIds))
.then(({ data }) => {
setState({ datasets: data, isFetching: false });
});
} else {
this.setState({
datasets: [],
filtered: [],
fetching: false,
});
}
}
render() {
if (this.props.user.sessionId == null) {
return null;
}
/** This means that datasets has not been loaded yet. It could be done with FETCHING (?) **/
}, [initialDatsetIds, dispatch, sessionId]);
/*if (this.props.selection.datasetIds.length !== this.state.datasets.length) {
this.retrieveSelectedDatasetsFromDatabase();
}*/
const { datasets, isFetching: fetching } = state;
const tooltip = (text) => <Tooltip id="tooltip">{text}</Tooltip>;
const tooltip = (text) => <Tooltip id="tooltip">{text}</Tooltip>;
return (
<div>
<ButtonToolbar
className="navbar-fixed-top"
style={{ backgroundColor: 'white', marginBottom: 10, marginTop: 100 }}
return (
<div className="app__inner">
<ButtonToolbar>
<OverlayTrigger
placement="bottom"
overlay={tooltip('Mint a DOI for all selected datasets')}
>
<div style={{ marginLeft: 40, marginTop: 10 }}>
<OverlayTrigger
placement="bottom"
overlay={tooltip('Mint a DOI for all selected datasets')}
>
<Button bsSize="small" bsStyle="primary" href="selection/mint">
<Glyphicon glyph="plus" /> Mint a DOI
</Button>
</OverlayTrigger>
<OverlayTrigger
placement="bottom"
overlay={tooltip('Download all selected datasets')}
>
<Button
style={{ marginLeft: 5 }}
bsSize="small"
bsStyle="primary"
target="_blank"
>
<Glyphicon glyph="download" style={{ marginRight: 3 }} />{' '}
Download all
</Button>
</OverlayTrigger>
</div>
</ButtonToolbar>
<div style={{ marginTop: 60 }}>
{this.state.fetching ? (
<Loader message="Loading datasets..." />
) : (
<DatasetTable
selection={this.props.selection}
removeDatasetById={this.props.removeDatasetById}
addDatasetById={this.props.addDatasetById}