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