Skip to content

Commit

Permalink
Finalise sessions (#48)
Browse files Browse the repository at this point in the history
* Add throbber during session list load
* Add copy link button
* Check target access for fragglebox
* Deploy unrecognised target modal if necessary
* Fix associated bugs!
  • Loading branch information
ricgillams authored Dec 5, 2018
1 parent 9c3c4b6 commit c62b300
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 112 deletions.
1 change: 1 addition & 0 deletions js/actions/actonTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const SET_CURRENT_COMPOUND_CLASS = 'SET_CURRENT_COMPOUND_CLASS';
export const RELOAD_SELECTION_STATE = 'RELOAD_SELECTION_STATE';
export const RELOAD_API_STATE = 'RELOAD_API_STATE';
export const SET_SAVING_STATE = 'SET_SAVING_STATE';
export const SET_SESH_LIST_SAVING = 'SET_SESH_LIST_SAVING';
export const SET_LATEST_SESSION = 'SET_LATEST_SESSION';
export const SET_LATEST_SNAPSHOT = 'SET_LATEST_SNAPSHOT';
export const SET_SESSION_ID = 'SET_SESSION_ID';
Expand Down
9 changes: 9 additions & 0 deletions js/actions/apiActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
SET_DUCK_YANK_DATA,
RELOAD_API_STATE,
SET_SAVING_STATE,
SET_SESH_LIST_SAVING,
SET_LATEST_SNAPSHOT,
SET_LATEST_SESSION,
SET_SESSION_TITLE,
Expand Down Expand Up @@ -212,6 +213,14 @@ export const setSavingState = function (savingState) {
};
}

export const setSeshListSaving = function (seshListSaving) {
console.log("ACTIONS: setting saving state to " + seshListSaving);
return {
type: SET_SESH_LIST_SAVING,
seshListSaving: seshListSaving
};
}

export const setLatestSnapshot = function (uuid) {
console.log("ACTIONS: latest state snapshot is " + uuid)
return {
Expand Down
8 changes: 6 additions & 2 deletions js/components/generalComponents.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ export class GenericList extends React.Component {
base_url += "viewscene/?user_id="+ userId
if (this.props.project_id != undefined) {
get_params.project_id = this.props.project_id
this.props.setSeshListSaving(true);
}
}
else {
console.log("DEFUALT")
console.log("DEFAULT")
}
var url = new URL(base_url)
Object.keys(get_params).forEach(key => url.searchParams.append(key, get_params[key]))
Expand All @@ -112,6 +113,7 @@ export class GenericList extends React.Component {
processResults(json) {
var results = json.results;
this.afterPush(results)
if (this.list_type == listTypes.SESSIONS && this.props.seshListSaving == true) {this.props.setSeshListSaving(false)}
return results;
}

Expand All @@ -124,7 +126,9 @@ export class GenericList extends React.Component {
response => response.json(),
error => console.log('An error occurred.', error)
)
.then(json => this.props.setObjectList(this.processResults(json)))
.then(
json => this.props.setObjectList(this.processResults(json))
)
}
this.old_url = url.toString();
}
Expand Down
3 changes: 2 additions & 1 deletion js/components/landing.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export class Welcome extends React.Component {
}
return (
<Row>
<Col xs={3} md={3}>
<Col xs={1} md={1}></Col>
<Col xs={2} md={2}>
<Row>
<h1>Welcome to Fragalysis{"\n"}</h1>
{text_div}
Expand Down
52 changes: 19 additions & 33 deletions js/components/modalStateSave.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import React, {Component} from "react";
import {connect} from "react-redux";
import ReactModal from "react-modal";
import {Tooltip, OverlayTrigger, ButtonToolbar, Row, Col, Button} from 'react-bootstrap';
import {Tooltip, OverlayTrigger, ButtonToolbar, Row, Col} from 'react-bootstrap';
import * as apiActions from "../actions/apiActions";
import Clipboard from 'react-clipboard.js';

Expand Down Expand Up @@ -129,11 +129,7 @@ export class ModalStateSave extends Component {
}

render() {
const tooltip = (
<Tooltip id="tooltip">
<strong>Copied!</strong>
</Tooltip>
);
const tooltip = (<Tooltip id="tooltip"><strong>Copied!</strong></Tooltip>);
var urlToCopy = "";
var sessionRename = "";
var linkSection = "";
Expand All @@ -159,38 +155,28 @@ export class ModalStateSave extends Component {
}
return (
<ReactModal isOpen={this.props.savingState.startsWith("saving") || this.props.savingState.startsWith("overwriting")} style={customStyles}>
<Col xs={1} md={1}>
</Col>
<Col xs={1} md={1}></Col>
<Col xs={10} md={10}>
<Row>
<p></p>
</Row>
<Row><p></p></Row>
{sessionRename}
<Row>
<p></p>
</Row>
<Row><p></p></Row>
{linkSection}
<Row>
<p></p>
</Row>
<Row>
<p></p>
</Row>
<Row>
<ButtonToolbar>
<OverlayTrigger trigger="click" placement="bottom" overlay={tooltip}>
<Clipboard option-container="modal" data-clipboard-text={urlToCopy}
<Row><p></p></Row>
<Row><p></p></Row>
<Row>
<ButtonToolbar>
<OverlayTrigger trigger="click" placement="bottom" overlay={tooltip}>
<Clipboard option-container="modal" data-clipboard-text={urlToCopy}
button-title="Copy me!">Copy link</Clipboard>
</OverlayTrigger>
<h3 style={{display: "inline"}}> </h3>
<button onClick={this.openFraggleLink}>Open in new tab</button>
<h3 style={{display: "inline"}}> </h3>
<button onClick={this.closeModal}>Close</button>
</ButtonToolbar>
</Row>
</Col>
<Col xs={1} md={1}>
</OverlayTrigger>
<h3 style={{display: "inline"}}> </h3>
<button onClick={this.openFraggleLink}>Open in new tab</button>
<h3 style={{display: "inline"}}> </h3>
<button onClick={this.closeModal}>Close</button>
</ButtonToolbar>
</Row>
</Col>
<Col xs={1} md={1}></Col>
</ReactModal>
);
} else {
Expand Down
52 changes: 32 additions & 20 deletions js/components/modalTargetUnrecognised.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,39 @@ export class ModalTargetUnrecognised extends React.Component {
}

render() {
if (this.state.targetListLength == 0) {
return (
<ReactModal isOpen={this.state.targetUnrecognised} style={customStyles}>
<div>
<h3>The target was not recognised and there are no other available targets.</h3>
<Button bsSize="sm" bsStyle="success" onClick={this.closeModal}>Close</Button>
<ErrorReport />
</div>
</ReactModal>
);
var request = <h3></h3>
if (DJANGO_CONTEXT["username"] == "NOT_LOGGED_IN") {
request = <h3>Please<a className="inline" href="/accounts/login"> sign in</a>, or select a target:</h3>
} else {
return (
<ReactModal isOpen={this.state.targetUnrecognised} style={customStyles}>
<div>
<h3>Target was not recognised. <br/> Please select a target:</h3>
<TargetList key="TARGLIST"/>
<Button bsSize="sm" bsStyle="success" onClick={this.closeModal}>Close</Button>
<ErrorReport/>
</div>
</ReactModal>
);
request = <h3>Please select a target:</h3>
}
if (this.props.targetUnrecognised == true) {
if (this.state.targetListLength == 0) {
return (
<ReactModal isOpen={this.state.targetUnrecognised} style={customStyles}>
<div>
<h3>The target was not recognised and there are no other available targets.</h3>
<Button bsSize="sm" bsStyle="success" onClick={this.closeModal}>Close</Button>
<ErrorReport/>
</div>
</ReactModal>
);
} else {
return (
<ReactModal isOpen={this.state.targetUnrecognised} style={customStyles}>
<div>
<h3>Target was not recognised or you do not have authentication to access
target. <br/></h3>
{request}
<TargetList key="TARGLIST"/>
<Button bsSize="sm" bsStyle="success" onClick={this.closeModal}>Close</Button>
<ErrorReport/>
</div>
</ReactModal>
);
}
} else {
return null;
}
}
}
Expand Down
102 changes: 70 additions & 32 deletions js/components/sessionList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@
* Created by ricgillams on 29/10/2018.
*/

import {ListGroupItem, ListGroup, Row, Col, Button} from "react-bootstrap";
import {ListGroupItem, ListGroup, Row, Col, ButtonTooltip, OverlayTrigger, ButtonToolbar, Tooltip} 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";
import Clipboard from 'react-clipboard.js';
import { css } from 'react-emotion';
import { RingLoader } from 'react-spinners';

const override = css`
display: block;
margin: 0 auto;
border-color: red;
`;

class SessionList extends GenericList {
constructor(props) {
Expand Down Expand Up @@ -72,13 +81,18 @@ class SessionList extends GenericList {
}

deleteStateSession(id) {
var _this = this
let currentSessionList = this.props.object_list;
for (var session in currentSessionList) {
if (currentSessionList[session].id === id) {
currentSessionList.splice(session, 1);
}
}
this.props.updateSessionIdList(currentSessionList)
if (this.props.object_list.length == 23) {
this.props.setSeshListSaving(true)
window.location.reload();
}
}

deleteSession(id) {
Expand All @@ -97,10 +111,19 @@ class SessionList extends GenericList {

renderDeleteButton(data) {
var _this = this;
var deleteButton = <Button bsStyle="danger" bsSize="xsmall" onClick={function onClick() {_this.deleteSession(data.id)}} >Delete</Button>
var deleteButton = <button onClick={function onClick() {_this.deleteSession(data.id)}} >Delete</button>
return deleteButton;
}

renderCopyUrlButton(data) {
const tooltip = (<Tooltip id="tooltip"><strong>Copied!</strong></Tooltip>);
var urlToCopy = window.location.protocol + "//" + window.location.hostname + "/viewer/react/fragglebox/" + data.uuid;
var copyButton = <OverlayTrigger trigger="click" placement="bottom" overlay={tooltip}>
<Clipboard option-container="modal" data-clipboard-text={urlToCopy} button-title="Copy URL">Copy link</Clipboard>
</OverlayTrigger>
return copyButton;
}

render_method(data) {
const {pathname} = this.props.location;
var fragglebox = "/viewer/react/fragglebox/" + data.uuid;
Expand All @@ -109,9 +132,9 @@ class SessionList extends GenericList {
<Row>
<Col xs={3} md={3}><Row></Row><p></p><Row><p>Title: <Link to={fragglebox}>{this.props.object_list[this.props.object_list.findIndex(x => x.id==data.id)].title}</Link></p></Row></Col>
<Col xs={3} md={3}><Row></Row><p></p><Row><p>Last modified on {data.modified.slice(0,10)} at {data.modified.slice(11,19)}</p></Row></Col>
<Col xs={2} md={2}><Row></Row><p></p><Row><p>Target: {data.target_on_name}</p></Row></Col>
<Col xs={1} md={1}><Row></Row><p></p><Row><p>Target: {data.target_on_name}</p></Row></Col>
<Col xs={3} md={3}><input id={data.id} key="sessRnm" style={{width: 250}} defaultValue={data.title} onKeyDown={this.handleSessionNaming}></input><sup><br></br>To rename, type new title & press enter.</sup></Col>
<Col xs={1} md={1}>{this.renderDeleteButton(data)}</Col>
<Col xs={2} md={2}><ButtonToolbar>{this.renderCopyUrlButton(data)} {this.renderDeleteButton(data)}</ButtonToolbar></Col>
</Row>
</ListGroupItem>
} else {
Expand All @@ -131,48 +154,63 @@ class SessionList extends GenericList {

render() {
const {pathname} = this.props.location;
if (this.props != undefined && this.props.object_list) {
if (DJANGO_CONTEXT["username"] == "NOT_LOGGED_IN") {
return <h3>Please log in to view session history.</h3>
} else if (this.props.object_list.length == 0) {
return <div><h3>You do not own any sessions!</h3><p>Proceed to a target to generate sessions.</p></div>
} else {
if (pathname != "/viewer/react/sessions") {
return <div>
<h3>Session List:</h3>
<ListGroup>
{
this.props.object_list.slice(0, 10).map((data) => (this.render_method(data)))
}
</ListGroup>
<p>Full list and session management here: <a href="/viewer/react/sessions">Sessions</a></p>
</div>;
} else {
return <div>
<h3>Session List:</h3>
<ListGroup>
{
this.props.object_list.map((data) => (this.render_method(data)))
}
</ListGroup>
</div>;
}
}
var sessionListTitle;
if (this.props.object_list.length != 0 && this.props.object_list.length <= 10){
sessionListTitle = <h3>Session List:</h3>
} else if (this.props.object_list.length > 10 && this.props.object_list.length < 24){
sessionListTitle = <h3>Session count: {this.props.object_list.length}/24.</h3>
} else if (this.props.object_list.length >= 24){
sessionListTitle = <h3>You have reached session limit (24), please delete old <a href="/viewer/react/sessions">sessions</a>!</h3>
}
if (this.props.seshListSaving == true) {
return <RingLoader className={override} sizeUnit={"px"} size={30} color={'#7B36D7'} loading={(this.props.seshListSaving == true)}/>
} else {
return null;
if (this.props != undefined && this.props.object_list) {
if (DJANGO_CONTEXT["username"] == "NOT_LOGGED_IN") {
return <h3>Please log in to view session history.</h3>
} else if (this.props.object_list.length == 0) {
return <div><h3>You do not own any sessions!</h3><p>Proceed to a target to generate sessions.</p>
</div>
} else {
if (pathname != "/viewer/react/sessions") {
return <div>
{sessionListTitle}
<ListGroup>
{
this.props.object_list.slice(0, 10).map((data) => (this.render_method(data)))
}
</ListGroup>
<p>Full list and session management here: <a href="/viewer/react/sessions">Sessions</a></p>
</div>;
} else {
return <div>
{sessionListTitle}
<ListGroup>
{
this.props.object_list.map((data) => (this.render_method(data)))
}
</ListGroup>
</div>;
}
}
} else {
return null;
}
}
}
}

function mapStateToProps(state) {
return {
object_list: state.apiReducers.present.sessionIdList,
seshListSaving: state.apiReducers.present.seshListSaving,
}
}

const mapDispatchToProps = {
setObjectList: apiActions.setSessionIdList,
updateSessionIdList: apiActions.updateSessionIdList,
setSeshListSaving: apiActions.setSeshListSaving,
}

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

0 comments on commit c62b300

Please sign in to comment.