From 906436bafa5ee9949893ae04ab2c21ff29466bdd Mon Sep 17 00:00:00 2001
From: Antti Luomi <antti.luomi@id.ethz.ch>
Date: Mon, 25 Mar 2019 12:20:38 +0100
Subject: [PATCH] Paging of datasets and population of working directory in
 download dialog

---
 README.md                                     |  20 +++
 jupyter-openbis-extension/sample.py           |   7 +-
 .../static/downloadDialog.js                  | 142 ++++++++++++------
 jupyter-openbis-extension/static/state.js     |   8 +-
 .../static/uploadDialog.js                    |  19 +--
 vagrant/files/setup-vagrant.sh                |   3 +
 6 files changed, 139 insertions(+), 60 deletions(-)

diff --git a/README.md b/README.md
index 57e78cd..130717d 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,26 @@ The jupyter-openbis-extension needs at least **Python 3.3** in order to run. The
 
 This extension has been successfully tested with Safari 12.0.3, Chrome 72.0 and Firefox 66.0. There is a known incompatibility before Firefox 61.0b13.
 
+## Development with Vagrant
+
+If you want to use a predefined development environment, follow these steps:
+
+1. Install latest version of VirtualBox (<https://www.virtualbox.org>)
+
+2. Install latest version of Vagrant (<https://www.vagrantup.com/downloads.html>)
+
+3. vagrant plugin install vagrant-vbguest vagrant-notify-forwarder vagrant-disksize
+ 
+4. cd vagrant
+
+5. vagrant up
+
+After the setup is complete, you'll have
+
+* Jupyter with openBIS extension running at <http://localhost:8888>.
+* openBIS running at <http://localhost:8122>, with credentials admin/password.
+* Experiment /DEFAULT/DEFAULT with a lot of datasets for testing.
+
 ## Install the extension
 
 If you haven't done yet: download the latest jupyter-openbis-extension from pip. It will automatically install the various dependencies, e.g. Pandas and NumPy.
diff --git a/jupyter-openbis-extension/sample.py b/jupyter-openbis-extension/sample.py
index ace30bf..752dfe7 100644
--- a/jupyter-openbis-extension/sample.py
+++ b/jupyter-openbis-extension/sample.py
@@ -2,6 +2,8 @@ from notebook.base.handlers import IPythonHandler
 import numpy as np
 import os
 from .connection import openbis_connections
+from urllib.parse import parse_qs
+
 
 
 def get_entity_for_identifier(conn, identifier):
@@ -68,8 +70,9 @@ class SampleHandler(IPythonHandler):
             })
             return None
 
-        start_with = params.get('start_with', None)
-        count      = params.get('count', None)
+        querystring = parse_qs(self.request.query)
+        start_with = querystring.get('start_with', ['0'])[0]
+        count      = querystring.get('count', ['10'])[0]
 
         datasets = get_datasets(entity, start_with=start_with, count=count)
         if datasets is not None:
diff --git a/jupyter-openbis-extension/static/downloadDialog.js b/jupyter-openbis-extension/static/downloadDialog.js
index a78bb13..08f0f92 100644
--- a/jupyter-openbis-extension/static/downloadDialog.js
+++ b/jupyter-openbis-extension/static/downloadDialog.js
@@ -23,9 +23,15 @@ define([
             }
         }
 
-        function show_datasets_table(data, datasets_table) {
+        function show_datasets_table(env, data, datasets_table, downloadPath, entityIdentifier) {
+            if (downloadPath.value === '') {
+                downloadPath.value = data.cwd
+            }
+
             var table = document.createElement("TABLE")
             table.className = "table-bordered table-striped table-condensed text-nowrap"
+            table.style.width = "100%"
+
             var thead = table.createTHead()
             var t_row = thead.insertRow()
             var titles = ['', 'permId', 'Type', 'Experiment', 'Registration Date', 'Status', 'Size']
@@ -36,10 +42,12 @@ define([
 
             for (dataSet of data.dataSets) {
 
-                var permId = document.createElement("INPUT")
+                const permId = document.createElement("INPUT")
                 permId.type = "checkbox"
                 permId.name = "permId"
                 permId.value = dataSet.permId
+                permId.checked = state.selectedDatasets.has(permId.value)
+                permId.onclick = () => permId.checked ? state.selectedDatasets.add(permId.value) : state.selectedDatasets.delete(permId.value)
 
                 var row = tbody.insertRow()
                 row.insertCell().appendChild(permId)
@@ -55,6 +63,80 @@ define([
                 datasets_table.removeChild(datasets_table.firstChild);
             }
             datasets_table.appendChild(table)
+
+            const totalCount = parseInt(data.totalCount)
+            const count = parseInt(data.count)
+            const startWith = parseInt(data.start_with)
+            const hasNext = startWith + count < totalCount
+            const hasPrevious = startWith > 0
+            const nextCmd = () => getDatasets(env, startWith+5, 5, entityIdentifier, datasets_table, downloadPath)
+            const previousCmd = () => getDatasets(env, startWith-5, 5, entityIdentifier, datasets_table, downloadPath)
+
+            var previous = document.createElement("A")
+            var linkText = document.createTextNode("<<< Previous")
+            previous.appendChild(linkText)
+            previous.href = "#"
+            previous.onclick = previousCmd
+
+            var next = document.createElement("A")
+            var linkText = document.createTextNode("Next >>>")
+            next.appendChild(linkText)
+            next.href = "#"
+            next.onclick = nextCmd
+            next.style.float="right"
+
+            var paging = document.createElement("DIV")
+            paging.style.width = "100%"
+            if (hasPrevious) {
+                paging.appendChild(previous)
+            }
+            if (hasNext) {
+                paging.appendChild(next)
+            }
+
+            datasets_table.appendChild(paging)
+        }
+
+        function getDatasets(env, startWith, count, entityIdentifier, datasets_table, downloadPath) {
+            var connection_name = state.connection.name
+            if (!connection_name) {
+                alert('Please choose a connection')
+                return false
+            }
+
+            currentEntityIdentifier = entityIdentifier.value
+            if (!currentEntityIdentifier) {
+                alert('Please specify a Sample or Experiment identifier/permId')
+                return false
+            }
+            var url = env.notebook.base_url 
+                + 'openbis/sample/' 
+                + connection_name 
+                + '/' 
+                + encodeURIComponent(currentEntityIdentifier)
+                + "?start_with="
+                + startWith 
+                + "&count="
+                + count
+
+            fetch(url)
+                .then(function (response) {
+                    if (response.ok) {
+                        response.json()
+                            .then(function (data) {
+                                show_datasets_table(env, data, datasets_table, downloadPath, entityIdentifier)
+                            })
+                    } else {
+                        response.json()
+                            .then(function (error) {
+                                console.log(error.reason)
+                                alert("Error: " + error.reason)
+                            })
+                    }
+                })
+                .catch(function (error) {
+                    console.error('A serious network problem occured:', error)
+                })
         }
 
 
@@ -63,6 +145,8 @@ define([
             icon: 'fa-download',
             help_index: '',
             handler: function (env) {
+                state.selectedDatasets = new Set([])
+
                 conn_table = document.createElement("DIV")
                 conn_table.id = "openbis_connections"
 
@@ -80,62 +164,20 @@ define([
                 entityIdentifier.value = ''
 
                 var datasets_table = document.createElement("DIV")
-                datasets_table.id = "dataset_table"
-                datasets_table.className = "output output_scroll"
-                datasets_table.style.maxHeight = "10em"
 
                 var show_datasets_btn = document.createElement("BUTTON")
                 show_datasets_btn.className = "btn-info btn-xs"
                 show_datasets_btn.textContent = "show datasets"
+                show_datasets_btn.style.margin="10px"
 
-                show_datasets_btn.onclick = function () {
-                    var selected_conn = state.connection.name
-                    if (!selected_conn) {
-                        alert('Please choose a connection')
-                        return false
-                    }
-                    connection_name = state.connection.name
-
-                    currentConnection = connection_name
-                    currentEntityIdentifier = entityIdentifier.value
-                    if (!currentEntityIdentifier) {
-                        alert('Please specify a Sample or Experiment identifier/permId')
-                        return false
-                    }
-                    var url = env.notebook.base_url + 'openbis/sample/' + connection_name + '/' + encodeURIComponent(currentEntityIdentifier)
-
-                    fetch(url)
-                        .then(function (response) {
-                            if (response.ok) {
-                                response.json()
-                                    .then(function (data) {
-                                        show_datasets_table(data, datasets_table)
-                                    })
-                            } else {
-                                response.json()
-                                    .then(function (error) {
-                                        console.log(error.reason)
-                                        alert("Error: " + error.reason)
-                                    })
-                            }
-                        })
-                        .catch(function (error) {
-                            console.error('A serious network problem occured:', error)
-                        })
-
-                }
                 showDataSets.appendChild(entityIdentifier)
                 showDataSets.appendChild(show_datasets_btn)
                 showDataSets.appendChild(datasets_table)
 
-                // dataSetPermId only
                 var dataset_direct = document.createElement("P")
                 dataset_direct.style.marginTop = '10px'
-                dataset_direct.innerHTML = '<strong>enter DataSet permId directly: </strong>'
+                dataset_direct.innerHTML = '<strong>Enter DataSet permId directly: </strong>'
 
-                //var dataset = $('<p>')
-                //    .css('margin-top', '10px')
-                //    .append($('<b>').text('... or enter DataSet permId directly: '))
                 var datasetPermId = document.createElement("INPUT")
                 datasetPermId.type = "text"
                 datasetPermId.name = "datasetPermId"
@@ -150,6 +192,9 @@ define([
                 downloadPath.size = "90"
                 downloadPath.value = ''
 
+                show_datasets_btn.onclick = 
+                    () => getDatasets(env, 0, 5, entityIdentifier, datasets_table, downloadPath)
+                
                 var path = document.createElement("DIV")
                 path.innerHTML = "<strong>download data to path: </strong>"
                 path.appendChild(downloadPath)
@@ -202,8 +247,8 @@ define([
                     }
 
                     var selectedPermIds = []
-                    for (row of document.querySelectorAll('input[name=permId]:checked')) {
-                        selectedPermIds.push(row.value)
+                    for (row of state.selectedDatasets) {
+                        selectedPermIds.push(row)
                     }
                     if (datasetPermId.value) {
                         selectedPermIds.push(datasetPermId.value)
@@ -217,6 +262,7 @@ define([
                         alert('Please specify where you would like to download your files!')
                         return false
                     }
+
                     downloadDataset(selected_conn, selectedPermIds, downloadPath.value)
                 }
 
diff --git a/jupyter-openbis-extension/static/state.js b/jupyter-openbis-extension/static/state.js
index e5008e9..6f05b5e 100644
--- a/jupyter-openbis-extension/static/state.js
+++ b/jupyter-openbis-extension/static/state.js
@@ -1,17 +1,23 @@
 define([],
     function () {
         return {
+            // connection dialog
             connection: {
                 name: null,
                 candidateName: null
             },
+
+            // upload dialog
             uploadDataSetType: null,
             uploadDataSetTypes: {},
             uploadEntityIdentifier: '',
             datasetCheckboxes: [],
             fileCheckboxes: [],
             selectedFiles: [],
-            unselectedDatasets: []
+            unselectedDatasets: [],
+
+            // download dialog
+            selectedDatasets: new Set([])
         }
     }
 )
\ No newline at end of file
diff --git a/jupyter-openbis-extension/static/uploadDialog.js b/jupyter-openbis-extension/static/uploadDialog.js
index fd84a46..0690d40 100644
--- a/jupyter-openbis-extension/static/uploadDialog.js
+++ b/jupyter-openbis-extension/static/uploadDialog.js
@@ -13,7 +13,7 @@ define([
             element.textContent = ""
             element.style.marginLeft = "8px"
             element.style.color = "red"
-            errorElements[name] = element
+            errorElements[name.toLowerCase()] = element
             return element
         }
         function cleanErrors() {
@@ -50,7 +50,6 @@ define([
         }
 
         function get_dataset_list(env, container) {
-            console.log(env.notebook.metadata.datasets)
             var datasets = env.notebook.metadata.datasets
             if (datasets != null) {
                 var values = Object.keys(datasets)
@@ -217,17 +216,19 @@ define([
                 entityIdentifier.style.width="100%"
 
                 var ds_title = document.createElement("STRONG")
-                ds_title.textContent = "DataSets"
                 var dataSetListContainer = document.createElement("DIV")
-                dataSetListContainer.style.height="150px"
-                dataSetListContainer.style.overflow="scroll"
-                get_dataset_list(env, dataSetListContainer)
+                if (env.notebook.metadata.datasets) {
+                    ds_title.textContent = "DataSets"
+                    dataSetListContainer.style.maxHeight="150px"
+                    dataSetListContainer.style.overflow="auto"
+                    get_dataset_list(env, dataSetListContainer)
+                }
 
                 var files_title = document.createElement("STRONG")
                 files_title.textContent = "Files"
                 var fileListContainer = document.createElement("DIV")
-                fileListContainer.style.height="150px"
-                fileListContainer.style.overflow="scroll"
+                fileListContainer.style.maxHeight="150px"
+                fileListContainer.style.overflow="auto"
                 get_file_list(env, fileListContainer)
                 
                 var inputs = document.createElement("DIV")
@@ -321,7 +322,7 @@ define([
                                 for (error of errors) {
                                     let key, value
                                     Object.keys(error).forEach(k => {
-                                        key = k
+                                        key = k.toLowerCase()
                                         value = error[k]
                                     })
                                     errorElements[key in errorElements ? key : "main"].textContent = value
diff --git a/vagrant/files/setup-vagrant.sh b/vagrant/files/setup-vagrant.sh
index 0d0ff35..37f4342 100755
--- a/vagrant/files/setup-vagrant.sh
+++ b/vagrant/files/setup-vagrant.sh
@@ -33,3 +33,6 @@ jupyter serverextension enable --py jupyter-openbis-extension
 jupyter nbextension install --py jupyter-openbis-extension --user --symlink
 jupyter nbextension enable jupyter-openbis-extension --user --py
 cd
+
+mkdir -p /home/vagrant/dss_root/incoming-default
+for i in $(seq 1 100); do touch /home/vagrant/dss_root/incoming-default/dataset${i}.txt; done
-- 
GitLab