From de5724c107605a001375ddc40b6b8b7818751b52 Mon Sep 17 00:00:00 2001 From: Will Moore Date: Thu, 7 Jan 2016 23:34:27 +0000 Subject: [PATCH 01/70] Started react rendering of center panel --- .../javascript/react_centre_panel.jsx | 39 + .../static/webclient/react/react-dom.js | 42 + .../webclient/static/webclient/react/react.js | 18791 ++++++++++++++++ .../templates/webclient/data/containers.html | 6 + .../includes/center_plugin.thumbs.js.html | 3 + 5 files changed, 18881 insertions(+) create mode 100644 components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx create mode 100644 components/tools/OmeroWeb/omeroweb/webclient/static/webclient/react/react-dom.js create mode 100644 components/tools/OmeroWeb/omeroweb/webclient/static/webclient/react/react.js diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx new file mode 100644 index 00000000000..c5d2a75baf3 --- /dev/null +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx @@ -0,0 +1,39 @@ + + +(function(){ + var ThumbTable = React.createClass({ + + render: function() { + var selected = this.props.selected; + + if (selected.length === 0) { + return (

None Selected

); + } + var dtype = selected[0].type; + if (selected.length > 1 && dtype !== "image") { + return (

Multiple non-images selected

); + } + if (dtype === "plate" || dtype === "acquisition") { + return (

Plate not supported yet

); + } + if (dtype !== "image") { + return (

Nothing to see!

); + } + + var txt = selected.length + " " + dtype + "s selected"; + return ( +

{txt}

+ ); + } + }); + + + window.OME.renderCentrePanel = function(selected) { + ReactDOM.render( + , + document.getElementById('content_details') + ); + }; + +})(); diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/react/react-dom.js b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/react/react-dom.js new file mode 100644 index 00000000000..d781f1ddd5e --- /dev/null +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/react/react-dom.js @@ -0,0 +1,42 @@ +/** + * ReactDOM v0.14.2 + * + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ +// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js +;(function(f) { + // CommonJS + if (typeof exports === "object" && typeof module !== "undefined") { + module.exports = f(require('react')); + + // RequireJS + } else if (typeof define === "function" && define.amd) { + define(['react'], f); + + // + + + + + diff --git a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/data/includes/center_plugin.thumbs.js.html b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/data/includes/center_plugin.thumbs.js.html index ad226c19a07..86f39224f6d 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/data/includes/center_plugin.thumbs.js.html +++ b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/data/includes/center_plugin.thumbs.js.html @@ -140,6 +140,9 @@ // Get the current selection var selected = inst.get_selected(true); + OME.renderCentrePanel(selected); + return; + if (selected.length === 0) { $("#content_details").html(""); parentId = undefined; From 03efec67f4ec12eaf19e34d3c35f5eac125d04f9 Mon Sep 17 00:00:00 2001 From: Will Moore Date: Sat, 9 Jan 2016 22:41:53 +0000 Subject: [PATCH 02/70] IconTable placeholder with header and footer --- .../webclient/static/webclient/css/dusty.css | 22 ++++ .../javascript/react_centre_panel.jsx | 105 ++++++++++++++++-- .../includes/center_plugin.thumbs.js.html | 2 +- 3 files changed, 119 insertions(+), 10 deletions(-) diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/dusty.css b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/dusty.css index ec2fb7ee0e1..01650c595ba 100755 --- a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/dusty.css +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/dusty.css @@ -930,7 +930,29 @@ button::-moz-focus-inner { + .iconTableHeader, .iconTableFooter, .iconTable { + position: absolute; + left: 0; + right: 0; + border-right: 0; + } + + .iconTableHeader { + top: 0; + height: 29px; + } + .iconTableFooter { + bottom: 0; + height: 25px; + } + + .iconTable { + bottom:25px; + top:29px; + overflow:auto; + margin-top:0px; + } diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx index c5d2a75baf3..ae0e8893b3a 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx @@ -3,34 +3,121 @@ (function(){ var ThumbTable = React.createClass({ - render: function() { - var selected = this.props.selected; + parentTypes: ["dataset", "orphaned", "tag", "share"], + renderNothing: function(selected) { if (selected.length === 0) { - return (

None Selected

); + return true; } var dtype = selected[0].type; + if (dtype === "image") { + return false; + } if (selected.length > 1 && dtype !== "image") { - return (

Multiple non-images selected

); + return true; + } + if (this.parentTypes.indexOf(dtype) === -1) { + return true; + } + }, + + getParentNode: function(dtype, selected, inst) { + if (this.parentTypes.indexOf(dtype) > -1) { + return selected[0]; + } + if (dtype === "image") { + return inst.get_node(inst.get_parent(selected[0])); + } + }, + + // getNodeData: function(inst, parentNode) { + // imgNodes = []; + // parentNode.children.forEach(function(ch){ + // var childNode = inst.get_node(ch); + // // Ignore non-images under tags or 'deleted' under shares + // if (childNode.type == "image") { + // imgNodes.push(childNode); + // } + // }); + + + // }, + + // Most render nothing unless we've selected a Dataset or Image(s) + render: function() { + var selected = this.props.selected, + inst = this.props.jstree, + imgNodes = [], + parentNode, + dtype; + + if (this.renderNothing(selected)) { + return (); } + + dtype = selected[0].type; + parentNode = this.getParentNode(dtype, selected, inst); + if (dtype === "plate" || dtype === "acquisition") { return (

Plate not supported yet

); } - if (dtype !== "image") { - return (

Nothing to see!

); - } var txt = selected.length + " " + dtype + "s selected"; return ( -

{txt}

+
+ + + +
+ ); + } + }); + + + var IconTableHeader = React.createClass({ + + render: function() { + return ( +
+
+ + +
+
+
+ + +
+ + +
+ ); + } + }); + + var IconTableFooter = React.createClass({ + render: function() { + return ( +
+
+
+ ); + } + }); + + var IconTable = React.createClass({ + render: function() { + return ( +
); } }); - window.OME.renderCentrePanel = function(selected) { + window.OME.renderCentrePanel = function(jstree, selected) { ReactDOM.render( , document.getElementById('content_details') ); diff --git a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/data/includes/center_plugin.thumbs.js.html b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/data/includes/center_plugin.thumbs.js.html index 86f39224f6d..d1465a3c53f 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/data/includes/center_plugin.thumbs.js.html +++ b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/data/includes/center_plugin.thumbs.js.html @@ -140,7 +140,7 @@ // Get the current selection var selected = inst.get_selected(true); - OME.renderCentrePanel(selected); + OME.renderCentrePanel(inst, selected); return; if (selected.length === 0) { From 78ce6051dfcd2cb6aa348b2215c7d9ac3661695f Mon Sep 17 00:00:00 2001 From: Will Moore Date: Sun, 10 Jan 2016 15:04:08 +0000 Subject: [PATCH 03/70] Thumbnail layout and selection working --- .../javascript/react_centre_panel.jsx | 121 +++++++++++++++++- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx index ae0e8893b3a..8262e23de8c 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx @@ -62,11 +62,10 @@ return (

Plate not supported yet

); } - var txt = selected.length + " " + dtype + "s selected"; return (
- +
); @@ -105,10 +104,126 @@ } }); + + var IconTableHeadRow = React.createClass({ + render: function() { + return ( +
  • +
    +
    Name
    +
    Date
    +
    Size X
    +
    Size Y
    +
    Size Z
    +
  • + ); + } + }); + + var IconTable = React.createClass({ + render: function() { + var parentNode = this.props.parentNode, + inst = this.props.inst; + var imgNodes = []; + var dateFormatOptions = { + weekday: "short", year: "numeric", month: "short", + day: "numeric", hour: "2-digit", minute: "2-digit" + }; + + parentNode.children.forEach(function(ch){ + var childNode = inst.get_node(ch); + // Ignore non-images under tags or 'deleted' under shares + if (childNode.type == "image") { + imgNodes.push(childNode); + } + }); + + var imgJson = [], + selFileSets = []; + // Convert jsTree nodes into json for template + imgNodes.forEach(function(node){ + var d = node.data.obj.date || node.data.obj.acqDate; + var date = new Date(d); + date = date.toLocaleTimeString(undefined, dateFormatOptions); + var iData = {'id': node.data.obj.id, + 'name': node.text, + 'data': JSON.parse(JSON.stringify(node.data)), + 'selected': node.state.selected, + 'date': date, + }; + // Note fileset IDs for selected images + if (iData.selected) { + var fsId = node.data.obj.filesetId; + if (fsId) { + selFileSets.push(fsId); + } + } + // Thumb version: random to break cache if thumbnails are -1 'in progress' + // or we're refresing 1 or all thumbnails + // if (node.data.obj.thumbVersion != undefined || + // event.type === "refreshThumbnails" || + // event.type === "refreshThumb") { + // var thumbVersion = node.data.obj.thumbVersion; + // if (thumbVersion === -1 || event.type === "refreshThumbnails" || ( + // event.type === "refreshThumb" && data.imageId === iData.id)) { + // thumbVersion = getRandom(); + // // We cache this to prevent new thumbnails requested on every + // // selection change. Refreshing of tree will reset thumbVersion. + // node.data.obj.thumbVersion = thumbVersion; + // } + // iData.thumbVersion = thumbVersion; + // } + // If image is in share and share is not owned by user... + if (node.data.obj.shareId && !parentNode.data.obj.isOwned) { + // share ID will be needed to open image viewer + iData.shareId = node.data.obj.shareId; + } + imgJson.push(iData); + }); + + // Now we know which filesets are selected, we can + // go through all images, adding fs-selection flag if in + if (selFileSets.length > 0) { + imgJson.forEach(function(img){ + if (selFileSets.indexOf(img.data.obj.filesetId) > -1) { + img.fsSelected = true; + } + }); + } + + var icons = imgJson.map(function(image){ + var cls = []; + if (image.selected) {cls.push('ui-selected')}; + if (image.fsSelected) {cls.push('fs-selected')}; + return ( +
  • +
    + image +
    +
      + + {icons} +
    +
    ); } }); From 617e49c02c735361844bdc727aff7ee94162f60d Mon Sep 17 00:00:00 2001 From: Will Moore Date: Mon, 11 Jan 2016 10:28:25 +0000 Subject: [PATCH 04/70] New to handle thumbnail clicks --- .../javascript/react_centre_panel.jsx | 73 ++++++++++++++----- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx index 8262e23de8c..f104a852f33 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx @@ -123,6 +123,18 @@ var IconTable = React.createClass({ + handleIconClick: function(imageId) { + console.log("click", imageId); + + var inst = this.props.inst; + var containerNode = OME.getTreeImageContainerBestGuess(imageId); + var selectedNode = inst.locate_node('image-' + imageId, containerNode)[0]; + + // Deselect all to begin (supress jstree event) + inst.deselect_all(true); + inst.select_node(selectedNode, true); + }, + render: function() { var parentNode = this.props.parentNode, inst = this.props.inst; @@ -194,28 +206,13 @@ } var icons = imgJson.map(function(image){ - var cls = []; - if (image.selected) {cls.push('ui-selected')}; - if (image.fsSelected) {cls.push('fs-selected')}; return ( -
  • -
    - image @@ -228,6 +225,44 @@ } }); + var ImageIcon = React.createClass({ + + handleIconClick: function() { + // this.setState ({selected: true}); + this.props.handleIconClick(this.props.image.id); + }, + + // getInitialState: function() { + // return {selected: this.props.image.selected}; + // }, + + render: function() { + + var image = this.props.image, + cls = []; + if (image.selected) {cls.push('ui-selected')}; + if (image.fsSelected) {cls.push('fs-selected')}; + + return ( +
  • +
    + image Date: Mon, 11 Jan 2016 11:21:18 +0000 Subject: [PATCH 06/70] layout buttons setState(layout) --- .../javascript/react_centre_panel.jsx | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx index f104a852f33..59266ec41ec 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/react_centre_panel.jsx @@ -5,6 +5,14 @@ parentTypes: ["dataset", "orphaned", "tag", "share"], + getInitialState: function() { + return {layout: 'icon'}; + }, + + setLayout: function(layout) { + this.setState({layout: layout}); + }, + renderNothing: function(selected) { if (selected.length === 0) { return true; @@ -64,8 +72,11 @@ return (
    - - + +
    ); @@ -75,12 +86,30 @@ var IconTableHeader = React.createClass({ + handleLayoutClick: function(event) { + var layout = event.target.getAttribute('data-layout'); + this.props.setLayout(layout); + }, + render: function() { + var layout = this.props.layout; + var iconBtnClass = layout === "icon" ? "checked" : "", + tableBtnClass = layout === "table" ? "checked" : ""; return (
    - - +
    @@ -124,8 +153,6 @@ var IconTable = React.createClass({ handleIconClick: function(imageId) { - console.log("click", imageId); - var inst = this.props.inst; var containerNode = OME.getTreeImageContainerBestGuess(imageId); var selectedNode = inst.locate_node('image-' + imageId, containerNode)[0]; @@ -216,7 +243,7 @@ return (
    -