Skip to content

Commit

Permalink
New feature: session renaming and deleting. closes #109, closes #42 (#41
Browse files Browse the repository at this point in the history
)
  • Loading branch information
ricgillams authored Nov 15, 2018
1 parent 0c5fdc9 commit 022c96d
Show file tree
Hide file tree
Showing 11 changed files with 335 additions and 136 deletions.
1 change: 1 addition & 0 deletions js/actions/actonTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,6 @@ export const SET_ERROR_MESSAGE = 'SET_ERROR_MESSAGE';
export const SET_TARGET_UNRECOGNISED = 'SET_TARGET_UNRECOGNISED';
export const SET_BOND_COLOR_MAP = 'SET_BOND_COLOR_MAP';
export const SET_SESSION_ID_LIST = 'SET_SESSION_ID_LIST';
export const UPDATE_SESSION_ID_LIST = 'UPDATE_SESSION_ID_LIST';
export const SET_USER_ID = 'SET_USER_ID';
export const SET_SESSION_TITLE = 'SET_SESSION_TITLE';
13 changes: 12 additions & 1 deletion js/actions/apiActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
SET_SESSION_TITLE,
SET_SESSION_ID,
SET_SESSION_ID_LIST,
UPDATE_SESSION_ID_LIST,
SET_ERROR_MESSAGE,
SET_TARGET_UNRECOGNISED,
SET_UUID,
Expand Down Expand Up @@ -250,6 +251,14 @@ export const setSessionIdList = function (input_json) {
};
}

export const updateSessionIdList = function (input_json) {
console.log("ACTIONS: sessionList summary written to state");
return {
type: UPDATE_SESSION_ID_LIST,
sessionIdList: input_json,
};
}

export const setErrorMessage = function (errorMessage) {
console.log("ACTIONS: errorMessage is " + errorMessage)
return {
Expand Down Expand Up @@ -293,7 +302,9 @@ export const reloadApiState = function (apiReducers) {
mol_group_on: apiReducers.mol_group_on,
hotspot_list: apiReducers.hotspot_list,
hotspot_on: apiReducers.hotspot_on,
app_on: apiReducers.app_on
app_on: apiReducers.app_on,
sessionId: apiReducers.sessionId,
sessionTitle: apiReducers.sessionTitle,
}
}

Expand Down
7 changes: 6 additions & 1 deletion js/components/generalComponents.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export class GenericList extends React.Component {
getUrl() {
// This should be defined by type
var base_url = window.location.protocol + "//" + window.location.host
if (DJANGO_CONTEXT["pk"] != undefined) {
var userId = DJANGO_CONTEXT["pk"].toString()
} else {
var userId = null;
}
// Set the version
base_url += "/api/"
var get_params = {}
Expand Down Expand Up @@ -86,7 +91,7 @@ export class GenericList extends React.Component {
}
}
else if (this.list_type == listTypes.SESSIONS) {
base_url += "viewscene/"
base_url += "viewscene/?user_id="+ userId
if (this.props.project_id != undefined) {
get_params.project_id = this.props.project_id
}
Expand Down
5 changes: 4 additions & 1 deletion js/components/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class Header extends React.Component {
var new_ele;
var navbarBrand;
var username = DJANGO_CONTEXT["username"];

if (username == "NOT_LOGGED_IN") {
new_ele = <NavItem eventKey={1} href={login}>
<Button> Login </Button>
Expand All @@ -89,20 +90,22 @@ class Header extends React.Component {
<h5><b>Hello {username}</b> Logout.</h5>
</NavItem>
}

if (document.location.host.startsWith("fragalysis.diamond") !== true) {
navbarBrand = <Navbar.Brand>
<Row>
<h4><a href={landing}>Fragalysis <b>DEVELOPMENT </b></a></h4>
</Row>
<Row>
<p>Please use: <a href={prodLanding}>production site</a></p>
<p>Please use: <a href={prodLanding} data-toggle='tooltip' title="https://fragalysis.diamond.ac.uk">production site</a></p>
</Row>
</Navbar.Brand>
} else {
navbarBrand = <Navbar.Brand>
<h4><a href={landing}>FragalysisHome</a></h4>
</Navbar.Brand>
}

return <Navbar>
<Navbar.Header>
{navbarBrand}
Expand Down
2 changes: 1 addition & 1 deletion js/components/landing.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class Welcome extends React.Component {
{text_div}
</Row>
<Row>
<p>An overview of target status (only accessible within Diamond) is available <a className="inline" href="http://cs04r-sc-vserv-137.diamond.ac.uk:8089/overview/targets/">here</a></p>
<p><a className="inline" href="http://cs04r-sc-vserv-137.diamond.ac.uk:8089/overview/targets/">Target status overview</a> (only accessible within Diamond)</p>
</Row>
</Col>
<Col xs={4} md={4}>
Expand Down
78 changes: 52 additions & 26 deletions js/components/modalStateSave.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ const customStyles = {
bottom: 'auto',
marginRight: '-20%',
transform: 'translate(-50%, -50%)',
border: '10px solid #7a7a7a'
border: '10px solid #7a7a7a',
width: '60%'
}
};

export class ModalStateSave extends Component {
constructor(props) {
super(props);
this.getCookie = this.getCookie.bind(this);
this.openFraggleLink = this.openFraggleLink.bind(this);
this.handleSessionNaming = this.handleSessionNaming.bind(this);
this.closeModal = this.closeModal.bind(this);
Expand All @@ -38,21 +40,52 @@ export class ModalStateSave extends Component {
};
}

getCookie(name) {
if (!document.cookie) {
return null;
}
const xsrfCookies = document.cookie.split(';')
.map(c => c.trim())
.filter(c => c.startsWith(name + '='));
if (xsrfCookies.length === 0) {
return null;
}
return decodeURIComponent(xsrfCookies[0].split('=')[1]);
}

openFraggleLink() {
var url = "";
if (this.props.savingState == "savingSnapshot") {
url = window.location.protocol + "//" + window.location.hostname + "/viewer/react/snapshot/" + this.props.latestSnapshot.slice(1, -1);
url = window.location.protocol + "//" + window.location.hostname + "/viewer/react/snapshot/" + this.props.latestSnapshot;
window.open(url);
} else if (this.props.savingState == "savingSession" || this.props.savingState == "overwritingSession") {
url = window.location.protocol + "//" + window.location.hostname + "/viewer/react/fragglebox/" + this.props.latestSession.slice(1, -1);
url = window.location.protocol + "//" + window.location.hostname + "/viewer/react/fragglebox/" + this.props.latestSession;
window.open(url);
}
}

handleSessionNaming(e){
if (e.keyCode === 13) {
console.log('submit new session name ' + e.target.value);
this.props.setSessionTitle(e.target.value);
var title = e.target.value;
console.log('submit new session name ' + title);
this.props.setSessionTitle(title);
const csrfToken = this.getCookie("csrftoken");
var uuid = this.props.latestSession;
var formattedState = {
uuid: uuid,
title: title,
};
fetch("/api/viewscene/" + JSON.parse(this.props.sessionId), {
method: "PATCH",
headers: {
'X-CSRFToken': csrfToken,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(formattedState)
}).catch((error) => {
this.props.setErrorMessage(error);
});
}
}

Expand Down Expand Up @@ -80,28 +113,21 @@ export class ModalStateSave extends Component {
</Tooltip>
);
var urlToCopy = "";
var information = "";
var linkSection;
var sessionRename = "";
var linkSection = "";
if (this.state.fraggleBoxLoc != undefined || this.state.snapshotLoc != undefined) {
if (this.props.savingState == "savingSnapshot") {
var urlToCopy = window.location.protocol + "//" + window.location.hostname + "/viewer/react/snapshot/" + this.props.latestSnapshot.slice(1, -1);
var linkSection = <Row><strong>"A permanent, fixed snapshot of the current state has been saved:"<br></br><a href={urlToCopy}>{urlToCopy}</a></strong></Row>
var sessionRename =<Row></Row>
var urlToCopy = window.location.protocol + "//" + window.location.hostname + "/viewer/react/snapshot/" + this.props.latestSnapshot;
var linkSection = <Row><strong>A permanent, fixed snapshot of the current state has been saved:<br></br><a href={urlToCopy}>{urlToCopy}</a></strong></Row>
} else if (this.props.savingState == "savingSession") {
var urlToCopy = window.location.protocol + "//" + window.location.hostname + "/viewer/react/fragglebox/" + this.props.latestSession.slice(1, -1);
var linkSection = <Row><strong>"A new session has been generated:"<br></br><a href={urlToCopy}>{urlToCopy}</a></strong></Row>
var sessionRename = <Row><input id="sessionRename" key="sessionRename" style={{ width:300 }} defaultValue={this.props.sessionTitle} onKeyDown={this.handleSessionNaming}></input><sup><br></br>To overwrite session name, enter new title above and press enter.</sup></Row>
var urlToCopy = window.location.protocol + "//" + window.location.hostname + "/viewer/react/fragglebox/" + this.props.latestSession;
var linkSection = <Row><strong>A new session has been generated:<br></br><a href={urlToCopy}>{urlToCopy}</a></strong></Row>
} else if (this.props.savingState == "overwritingSession") {
var urlToCopy = window.location.protocol + "//" + window.location.hostname + "/viewer/react/fragglebox/" + this.props.latestSession.slice(1, -1);
var linkSection = <Row><strong>"Your session has been overwritten and remains:"<br></br><a href={urlToCopy}>{urlToCopy}</a></strong></Row>
}
if (this.props.savingState == "overwritingSession") {
// Session address:
} else {

}
if (this.props.savingState == "overwritingSession") {
// Session address:
} else {

var sessionRename = <Row><input id="sessionRename" key="sessionRename" style={{ width:300 }} defaultValue={this.props.sessionTitle} onKeyDown={this.handleSessionNaming}></input><sup><br></br>To overwrite session name, enter new title above and press enter.</sup></Row>
var urlToCopy = window.location.protocol + "//" + window.location.hostname + "/viewer/react/fragglebox/" + this.props.latestSession;
var linkSection = <Row><strong>Your session has been overwritten and remains available at:<br></br><a href={urlToCopy}>{urlToCopy}</a></strong></Row>
}
return (
<ReactModal isOpen={this.props.savingState.startsWith("saving") || this.props.savingState.startsWith("overwriting")} style={customStyles}>
Expand All @@ -111,9 +137,7 @@ export class ModalStateSave extends Component {
<Row>
<p></p>
</Row>
<Row>
<input id="sessionRename" key="sessionRename" style={{ width:300 }} defaultValue={this.state.sessionTitle} onKeyDown={this.handleSessionNaming}></input>
</Row>
{sessionRename}
<Row>
<p></p>
</Row>
Expand Down Expand Up @@ -153,12 +177,14 @@ function mapStateToProps(state) {
latestSession: state.apiReducers.present.latestSession,
latestSnapshot: state.apiReducers.present.latestSnapshot,
sessionTitle: state.apiReducers.present.sessionTitle,
sessionId: state.apiReducers.present.sessionId,
}
}

const mapDispatchToProps = {
setSavingState: apiActions.setSavingState,
setSessionTitle: apiActions.setSessionTitle,
setErrorMessage: apiActions.setErrorMessage,
}

export default connect(mapStateToProps, mapDispatchToProps)(ModalStateSave);
101 changes: 66 additions & 35 deletions js/components/proposalList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
* Created by ricgillams on 29/10/2018.
*/

import {ListGroupItem, ListGroup, Col, Checkbox} from "react-bootstrap";
import {ListGroupItem, ListGroup, Col, Checkbox, Row} from "react-bootstrap";
import {GenericList} from "./generalComponents";
import React from "react";
import {connect} from "react-redux";
import * as apiActions from "../actions/apiActions";
import * as listType from "./listTypes";
import {withRouter, Link} from "react-router-dom";

Expand All @@ -15,6 +14,7 @@ class ProposalList extends GenericList {
super(props);
this.list_type = listType.SESSIONS;
this.render_method = this.render_method.bind(this);
this.handleCheckedProposal = this.handleCheckedProposal.bind(this);
this.state = {
proposalList: [
{id: "LB-test1", owner: "qwu18777"},
Expand All @@ -25,20 +25,32 @@ class ProposalList extends GenericList {
{id: "target-test1", proposalId: "LB-test1", owner: "qwu18777"},
{id: "target-test2", proposalId: "LB-test1", owner: "qwu18777"},
{id: "target-test3", proposalId: "LB-test2", owner: "qwu18777"}
]
],
checkedProposals: [],
}
}

// checked={this.state.checkboxChecked} onchange={this.handleCheckedProposal}
// handleChange(evt) {
// this.setState({checkboxChecked: evt.target.checked});
// }
//
// handleToggle() {
// this.setState({ checkboxChecked: !this.state.checkboxChecked });
// }

handleCheckedProposal(e){

}

render_method(data, type) {
if (type == "proposalList") {
return <ListGroupItem key={data.id}>
<p>Title: {data.id} &emsp; &emsp; &emsp; &emsp; <Checkbox inline>Load proposal</Checkbox></p>
<p>Title: {data.id} &emsp; &emsp; &emsp; &emsp; <Checkbox id={data.id} inline>Load proposal</Checkbox></p>
</ListGroupItem>
} else if (type == "targetList") {
return <ListGroupItem key={data.id}>
<p>Title: {data.id}, Proposal: {data.proposalId} &emsp; &emsp; &emsp; &emsp;
<Checkbox inline>Tindspect summary</Checkbox> &emsp;
<Checkbox inline>Fragalysis (private)</Checkbox> &emsp;
<Checkbox inline>Fragalysis (public)</Checkbox>
</p>
Expand All @@ -52,37 +64,57 @@ class ProposalList extends GenericList {
}

render() {
const userPk = DJANGO_CONTEXT["pk"]
const username = DJANGO_CONTEXT["username"]
const {pathname} = this.props.location;
// const userPk = DJANGO_CONTEXT["pk"]
// const username = DJANGO_CONTEXT["username"]
// const {pathname} = this.props.location;
if (this.state.proposalList) {
return <div>
<Col xs={1} md={1}>
</Col>
<Col xs={4} md={4}>
<h3>Proposal List</h3>
<p>Here is a list of the proposals for which you have been registered.</p>
<p>By checking the box, you agree for the list of target names associated with the proposal to be
uploaded onto the Fragalysis cloud infrastructure.</p>
<p>You will then be able to manage the associated data for those targets, including their visibility
within the fragalysis app.</p>
<ListGroup>
{
this.state.proposalList.reverse().map((data) => (this.render_method(data, "proposalList")))
}
</ListGroup>
</Col>
<Col xs={6} md={6}>
<h3>Target List</h3>
<p> For each proposal approved in the left column, the related targets will appear in this list:</p>
<ListGroup>
{
this.state.targetList.reverse().map((data) => (this.render_method(data, "targetList")))
}
</ListGroup>
</Col>
<Col xs={1} md={1}>
</Col>
<Row>
<Col xs={1} md={1}></Col>
<Col xs={4} md={4}>
<h3>Proposal List</h3>
<p></p>
<p>Here is a list of the proposals for which you have been registered.</p>
<p>Upon checking the box, the targets associated with the proposal will be uploaded into the Fragalysis cloud infrastructure.</p>
<p>You will then be able to manage the associated data for each target independently.</p>
</Col>
<Col xs={6} md={6}>
<h3>Target List</h3>
<p></p>
<p> For each proposal approved in the left column, the related targets will appear in the list below.</p>
<p> Upon checking the private box, the target will becoming visible to users from the relevant proposal.</p>
<p> If you would like to make your data publicly accessible, check the public box. Public targets do not require a FedID login for access.</p>
</Col>
<Col xs={1} md={1}></Col>
</Row>
<Row><p></p></Row>
<Row>
<Col xs={1} md={1}></Col>
<Col xs={4} md={4}>
<ListGroup>
{
this.state.proposalList.reverse().map((data) => (this.render_method(data, "proposalList")))
}
</ListGroup>
</Col>
<Col xs={6} md={6}>
<ListGroup>
{
this.state.targetList.reverse().map((data) => (this.render_method(data, "targetList")))
}
</ListGroup>
</Col>
<Col xs={1} md={1}></Col>
</Row>
<Row><p></p></Row>
<Row>
<Col xs={1} md={1}></Col>
<Col xs={10} md={10}>
<h3>In accordance with the Diamond data policy, we use reasonable endeavours to preserve the confidentiality of your experimental data!!!</h3>
<p>The Diamond data policy is located here: <a className="inline" href="https://www.diamond.ac.uk/Users/Policy-Documents/Policies/Experimental-Data-Management-Pol.html">https://www.diamond.ac.uk/Users/Policy-Documents/Policies/Experimental-Data-Management-Pol.html</a></p>
</Col>
<Col xs={1} md={1}></Col>
</Row>
</div>
} else {
return null;
Expand All @@ -97,7 +129,6 @@ function mapStateToProps(state) {
}

const mapDispatchToProps = {
setObjectList: apiActions.setSessionIdList
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ProposalList));
Loading

0 comments on commit 022c96d

Please sign in to comment.