diff --git a/js/actions/actonTypes.js b/js/actions/actonTypes.js index 68e02db3b..27c4a4e90 100644 --- a/js/actions/actonTypes.js +++ b/js/actions/actonTypes.js @@ -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'; diff --git a/js/actions/apiActions.js b/js/actions/apiActions.js index af6b27b56..b7555982a 100644 --- a/js/actions/apiActions.js +++ b/js/actions/apiActions.js @@ -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, @@ -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 { diff --git a/js/components/generalComponents.js b/js/components/generalComponents.js index 7c9180ab6..dc3df7fae 100644 --- a/js/components/generalComponents.js +++ b/js/components/generalComponents.js @@ -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])) @@ -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; } @@ -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(); } diff --git a/js/components/landing.js b/js/components/landing.js index 23d90718b..33189f07d 100644 --- a/js/components/landing.js +++ b/js/components/landing.js @@ -25,7 +25,8 @@ export class Welcome extends React.Component { } return ( - + +

Welcome to Fragalysis{"\n"}

{text_div} diff --git a/js/components/modalStateSave.js b/js/components/modalStateSave.js index f9c6e350e..491cfe3df 100644 --- a/js/components/modalStateSave.js +++ b/js/components/modalStateSave.js @@ -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'; @@ -129,11 +129,7 @@ export class ModalStateSave extends Component { } render() { - const tooltip = ( - - Copied! - - ); + const tooltip = (Copied!); var urlToCopy = ""; var sessionRename = ""; var linkSection = ""; @@ -159,38 +155,28 @@ export class ModalStateSave extends Component { } return ( - - + - -

-
+

{sessionRename} - -

-
+

{linkSection} - -

-
- -

-
- - - -

+

+ + + + Copy link - -

- -

- -
-
- - + +

+ +

+ + +
+ ); } else { diff --git a/js/components/modalTargetUnrecognised.js b/js/components/modalTargetUnrecognised.js index 1f86f2e66..28a401b61 100644 --- a/js/components/modalTargetUnrecognised.js +++ b/js/components/modalTargetUnrecognised.js @@ -50,27 +50,39 @@ export class ModalTargetUnrecognised extends React.Component { } render() { - if (this.state.targetListLength == 0) { - return ( - -
-

The target was not recognised and there are no other available targets.

- - -
-
- ); + var request =

+ if (DJANGO_CONTEXT["username"] == "NOT_LOGGED_IN") { + request =

Please sign in, or select a target:

} else { - return ( - -
-

Target was not recognised.
Please select a target:

- - - -
-
- ); + request =

Please select a target:

+ } + if (this.props.targetUnrecognised == true) { + if (this.state.targetListLength == 0) { + return ( + +
+

The target was not recognised and there are no other available targets.

+ + +
+
+ ); + } else { + return ( + +
+

Target was not recognised or you do not have authentication to access + target.

+ {request} + + + +
+
+ ); + } + } else { + return null; } } } diff --git a/js/components/sessionList.js b/js/components/sessionList.js index 9f9e5be49..836828dd7 100644 --- a/js/components/sessionList.js +++ b/js/components/sessionList.js @@ -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) { @@ -72,6 +81,7 @@ 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) { @@ -79,6 +89,10 @@ class SessionList extends GenericList { } } this.props.updateSessionIdList(currentSessionList) + if (this.props.object_list.length == 23) { + this.props.setSeshListSaving(true) + window.location.reload(); + } } deleteSession(id) { @@ -97,10 +111,19 @@ class SessionList extends GenericList { renderDeleteButton(data) { var _this = this; - var deleteButton = + var deleteButton = return deleteButton; } + renderCopyUrlButton(data) { + const tooltip = (Copied!); + var urlToCopy = window.location.protocol + "//" + window.location.hostname + "/viewer/react/fragglebox/" + data.uuid; + var copyButton = + Copy link + + return copyButton; + } + render_method(data) { const {pathname} = this.props.location; var fragglebox = "/viewer/react/fragglebox/" + data.uuid; @@ -109,9 +132,9 @@ class SessionList extends GenericList {

Title: {this.props.object_list[this.props.object_list.findIndex(x => x.id==data.id)].title}

Last modified on {data.modified.slice(0,10)} at {data.modified.slice(11,19)}

-

Target: {data.target_on_name}

+

Target: {data.target_on_name}



To rename, type new title & press enter.
- {this.renderDeleteButton(data)} + {this.renderCopyUrlButton(data)} {this.renderDeleteButton(data)}
} else { @@ -131,35 +154,48 @@ 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

Please log in to view session history.

- } else if (this.props.object_list.length == 0) { - return

You do not own any sessions!

Proceed to a target to generate sessions.

- } else { - if (pathname != "/viewer/react/sessions") { - return
-

Session List:

- - { - this.props.object_list.slice(0, 10).map((data) => (this.render_method(data))) - } - -

Full list and session management here: Sessions

-
; - } else { - return
-

Session List:

- - { - this.props.object_list.map((data) => (this.render_method(data))) - } - -
; - } - } + var sessionListTitle; + if (this.props.object_list.length != 0 && this.props.object_list.length <= 10){ + sessionListTitle =

Session List:

+ } else if (this.props.object_list.length > 10 && this.props.object_list.length < 24){ + sessionListTitle =

Session count: {this.props.object_list.length}/24.

+ } else if (this.props.object_list.length >= 24){ + sessionListTitle =

You have reached session limit (24), please delete old sessions!

+ } + if (this.props.seshListSaving == true) { + return } else { - return null; + if (this.props != undefined && this.props.object_list) { + if (DJANGO_CONTEXT["username"] == "NOT_LOGGED_IN") { + return

Please log in to view session history.

+ } else if (this.props.object_list.length == 0) { + return

You do not own any sessions!

Proceed to a target to generate sessions.

+
+ } else { + if (pathname != "/viewer/react/sessions") { + return
+ {sessionListTitle} + + { + this.props.object_list.slice(0, 10).map((data) => (this.render_method(data))) + } + +

Full list and session management here: Sessions

+
; + } else { + return
+ {sessionListTitle} + + { + this.props.object_list.map((data) => (this.render_method(data))) + } + +
; + } + } + } else { + return null; + } } } } @@ -167,12 +203,14 @@ class SessionList extends GenericList { 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)); \ No newline at end of file diff --git a/js/components/sessionManagement.js b/js/components/sessionManagement.js index 3e5c8bb5a..7272259f9 100644 --- a/js/components/sessionManagement.js +++ b/js/components/sessionManagement.js @@ -41,6 +41,8 @@ export class SessionManagement extends React.Component { this.redeployVectors = this.redeployVectors.bind(this); this.generateNextUuid = this.generateNextUuid.bind(this); this.getSessionDetails = this.getSessionDetails.bind(this); + this.checkTarget = this.checkTarget.bind(this); + this.reloadSession = this.reloadSession.bind(this); this.state = { saveType: "", nextUuid: "", @@ -48,6 +50,38 @@ export class SessionManagement extends React.Component { }; } + checkTarget(myJson) { + var jsonOfView = JSON.parse(JSON.parse(JSON.parse(myJson.scene)).state); + var target = jsonOfView.apiReducers.present.target_on_name + var targetUnrecognised = true; + for (var i in this.props.targetIdList) { + if (target == this.props.targetIdList[i].title) { + targetUnrecognised = false; + } + } + if (targetUnrecognised == true) { + this.props.setLoadingState(false); + } + this.props.setTargetUnrecognised(targetUnrecognised); + if (targetUnrecognised == false) { + this.reloadSession(myJson) + } + } + + reloadSession(myJson) { + var jsonOfView = JSON.parse(JSON.parse(JSON.parse(myJson.scene)).state); + this.props.reloadApiState(jsonOfView.apiReducers.present); + this.props.reloadSelectionState(jsonOfView.selectionReducers.present); + this.props.setStageColor(jsonOfView.nglReducers.present.stageColor); + this.restoreOrientation(jsonOfView.nglReducers.present.nglOrientations); + if (jsonOfView.selectionReducers.present.vectorOnList.length != 0) { + var url = window.location.protocol + "//" + window.location.host + '/api/vector/' + jsonOfView.selectionReducers.present.vectorOnList[JSON.stringify(0)] + "/" + this.redeployVectors(url); + } + this.props.setSessionTitle(myJson.title); + this.props.setSessionId(myJson.id); + } + getCookie(name) { if (!document.cookie) { return null; @@ -106,22 +140,11 @@ export class SessionManagement extends React.Component { } } - handleJson(myJson){ - if(myJson.scene==undefined){ + handleJson(myJson) { + if (myJson.scene == undefined) { return; } - var jsonOfView = JSON.parse(JSON.parse(JSON.parse(myJson.scene)).state); - this.props.reloadApiState(jsonOfView.apiReducers.present); - this.props.reloadSelectionState(jsonOfView.selectionReducers.present); - this.props.setStageColor(jsonOfView.nglReducers.present.stageColor); - this.restoreOrientation(jsonOfView.nglReducers.present.nglOrientations); - if (jsonOfView.selectionReducers.present.vectorOnList.length != 0){ - var url = window.location.protocol + "//" + window.location.host + '/api/vector/' + jsonOfView.selectionReducers.present.vectorOnList[JSON.stringify(0)] + "/" - this.redeployVectors(url); - } - this.props.setSessionTitle(myJson.title); - this.props.setSessionId(myJson.id); - this.restoreOrientation(jsonOfView.nglReducers.present.nglOrientations); + this.checkTarget(myJson); }; restoreOrientation(myOrientDict) { @@ -254,6 +277,8 @@ export class SessionManagement extends React.Component { if (hasBeenRefreshed==true) { var store = JSON.stringify(getStore().getState()); const csrfToken = this.getCookie("csrftoken"); + const timeOptions = {year:'numeric', month:'numeric', day:'numeric', hour: 'numeric', minute: 'numeric', + second: 'numeric', hour12: false,} var TITLE = 'Created on ' + new Intl.DateTimeFormat('en-GB', timeOptions).format(Date.now()); var userId = DJANGO_CONTEXT["pk"]; var stateObject = JSON.parse(store); @@ -261,8 +286,6 @@ export class SessionManagement extends React.Component { var newApiObject = Object.assign(stateObject.apiReducers, {present: newPresentObject}); var newStateObject = Object.assign(JSON.parse(store), {apiReducers: newApiObject}); var fullState = {state: JSON.stringify(newStateObject)}; - const timeOptions = {year:'numeric', month:'numeric', day:'numeric', hour: 'numeric', minute: 'numeric', - second: 'numeric', hour12: false,} hasBeenRefreshed = false; if (this.state.saveType == "sessionNew" && this.state.newSessionFlag == 1) { this.setState(prevState => ({newSessionFlag: 0})); @@ -311,7 +334,7 @@ export class SessionManagement extends React.Component { const uuidv4 = require('uuid/v4'); var formattedState = { uuid: uuidv4(), - title: TITLE, + title: "undefined", user_id: userId, scene: JSON.stringify(JSON.stringify(fullState)) }; @@ -338,7 +361,7 @@ export class SessionManagement extends React.Component { const {pathname} = this.props.location; var buttons = ""; if (pathname != "/viewer/react/landing" && pathname != "/viewer/react/funders" && pathname != "/viewer/react/sessions" && pathname != "/viewer/react/targetmanagement") { - if (this.props.sessionTitle == undefined) { + if (this.props.sessionTitle == undefined || this.props.sessionTitle == "undefined") { buttons =
@@ -380,6 +403,7 @@ function mapStateToProps(state) { latestSession: state.apiReducers.present.latestSession, sessionId: state.apiReducers.present.sessionId, sessionTitle: state.apiReducers.present.sessionTitle, + targetIdList: state.apiReducers.present.target_id_list, } } @@ -401,5 +425,7 @@ const mapDispatchToProps = { setVectorList: selectionActions.setVectorList, setBondColorMap: selectionActions.setBondColorMap, setMolGroupOn: apiActions.setMolGroupOn, + setTargetUnrecognised: apiActions.setTargetUnrecognised, + setLoadingState: nglLoadActions.setLoadingState, } export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SessionManagement)); \ No newline at end of file diff --git a/js/components/summaryView.js b/js/components/summaryView.js index 76d353d11..5e5f80a2a 100644 --- a/js/components/summaryView.js +++ b/js/components/summaryView.js @@ -261,7 +261,7 @@ class SummaryView extends React.Component{
Number series explored: {this.state.num_series}
Estimated cost: £{this.state.cost}
- +
Selected Interaction: {interaction_select}
diff --git a/js/components/switches.js b/js/components/switches.js index c5877e19c..e18e21cb0 100644 --- a/js/components/switches.js +++ b/js/components/switches.js @@ -21,7 +21,7 @@ class Switches extends Component { - + diff --git a/js/containers/fraggleBoxHolder.js b/js/containers/fraggleBoxHolder.js index a02bb7418..e7afe799a 100644 --- a/js/containers/fraggleBoxHolder.js +++ b/js/containers/fraggleBoxHolder.js @@ -14,12 +14,13 @@ import NGLView from "../components/nglComponents"; import NglViewerControls from "../components/nglViewerControls"; import {withRouter} from "react-router-dom"; import * as apiActions from "../actions/apiActions"; +import * as nglLoadActions from "../actions/nglLoadActions"; +import ModalTargetUnrecognised from "../components/modalTargetUnrecognised"; import ModalLoadingScreen from "../components/modalLoadingScreen"; import ModalStateSave from "../components/modalStateSave"; import ModalErrorMessage from "../components/modalErrorDisplay"; import HotspotList from "../components/hotspotList"; -import {BrowserBomb} from "../components/browserBombModal"; -// import {ModalTargetUnrecognised} from "../components/modalTargetUnrecognised"; +import BrowserBomb from "../components/browserBombModal"; class FraggleBox extends Component { @@ -36,12 +37,12 @@ class FraggleBox extends Component { var snapshotUuid = this.props.match.params.snapshotUuid; this.props.setUuid(snapshotUuid); } - // this.updateTarget(); } render() { var screenHeight= window.innerHeight*0.75.toString()+"px" var molListHeight= window.innerHeight*0.5.toString()+"px" + return ( @@ -61,10 +62,10 @@ class FraggleBox extends Component { + - {/**/} ) @@ -73,11 +74,16 @@ class FraggleBox extends Component { function mapStateToProps(state) { return { + targetOnName: state.apiReducers.present.target_on_name, + targetIdList: state.apiReducers.present.target_id_list, + targetUnrecognised: state.apiReducers.present.targetUnrecognised, } } const mapDispatchToProps = { setUuid: apiActions.setUuid, setLatestSession: apiActions.setLatestSession, + setTargetUnrecognised: apiActions.setTargetUnrecognised, + setLoadingState: nglLoadActions.setLoadingState, } export default withRouter(connect(mapStateToProps, mapDispatchToProps)(FraggleBox)) \ No newline at end of file diff --git a/js/reducers/apiReducers.js b/js/reducers/apiReducers.js index d16f81766..f61a5b796 100644 --- a/js/reducers/apiReducers.js +++ b/js/reducers/apiReducers.js @@ -24,6 +24,7 @@ const INITIALSTATE = { hotspot_on: undefined, hotspot_list: [], savingState: "UNSET", + seshListSaving: true, latestSession: undefined, latestSnapshot: undefined, errorMessage: undefined, @@ -157,6 +158,11 @@ export default function apiReducers(state = INITIALSTATE, action) { savingState: action.savingState }); + case actions.SET_SESH_LIST_SAVING: + return Object.assign({}, state, { + seshListSaving: action.seshListSaving + }); + case actions.SET_LATEST_SNAPSHOT: return Object.assign({}, state, { latestSnapshot: action.latestSnapshot