Skip to content
Snippets Groups Projects
uploadDialog.js 23.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • define([
            "base/js/dialog",
            "base/js/utils",
            "jquery",
            "./state",
            "./common",
    
        function (dialog, utils, $, state, common, entitySearcher) {
    
            var errorElements = { }
            function createErrorElement(name) {
                var element = document.createElement("STRONG")
                element.textContent = ""
                element.style.marginLeft = "8px"
                element.style.color = "red"
    
                errorElements[name.toLowerCase()] = element
    
                return element
            }
            function cleanErrors() {
                Object.keys(errorElements).forEach(key => errorElements[key].textContent="")
            }
    
            var spinner = document.createElement("IMG")
            spinner.className="openbis-feedback"
            spinner.src=""
    
            function showSpinner(env) {
    
    Juan Fuentes's avatar
    Juan Fuentes committed
                var userName = window.location.pathname.split("/")[2];
                spinner.src = '/user/' + userName+ '/nbextensions/jupyter-openbis-extension/spinner.gif'
    
            function hideSpinner(env) {
    
            function get_file_list(env, container, path) {
    
                // get the file list (relative to the notebook) using the existing jupyter api
    
                var url = env.notebook.base_url + 'api/contents'
                if (path !== "") {
                    url = url + '/' + path
                }
    
    
                fetch(url)
                    .then( function(response) {
                        if (response.ok) {
                            response.json()
                                .then(function(data){
    
                                    createFileTable(env, data, container, state)
                                    //state.fileCheckboxes = createFileTable(env, data, container, state.selectedFiles)
    
                                })
                        }
                        else {
                            console.error(response.status)
                        }
                    })
            }
    
            function get_dataset_list(env, container) {
                var datasets = env.notebook.metadata.datasets
                if (datasets != null) {
                    var values = Object.keys(datasets)
                    values.sort()
    
                    state.datasetCheckboxes = createSelectTable(values, container, true, state.unselectedDatasets)
    
                // Search for the history id on the metadata, new format, hidden from the user
    
                if(Jupyter && 
                    Jupyter.notebook && 
                    Jupyter.notebook.metadata && 
                    Jupyter.notebook.metadata.openbisHistoryId) {
                    resultDatasetHistoryId = Jupyter.notebook.metadata.openbisHistoryId;
                }
    
                // Search for the history id on the cells, older format
    
                if (!resultDatasetHistoryId) {
                    var resultDatasetHistoryIdIdx = 0;
                    while(Jupyter.notebook.get_cell(resultDatasetHistoryIdIdx) != null) {
                        var cell = Jupyter.notebook.get_cell(resultDatasetHistoryIdIdx);
                        var cellText = cell.get_text();
                        if(cell.get_text().startsWith("resultDatasetHistoryId='")) {
                            var firstIndexOf = cell.get_text().indexOf("'");
                            var lastIndexOf = cell.get_text().indexOf("'", firstIndexOf + 1);
                            resultDatasetHistoryId = cell.get_text().substring(firstIndexOf + 1, lastIndexOf);
                        }
                        resultDatasetHistoryIdIdx++;
                    }
                }
    
                return resultDatasetHistoryId; // We always return at least the empty one
    
            function getDatasetTypes(env, connection_name, dataset_types, input_fields) {
                // get all DatasetTypes of a given connection
    
                var url = env.notebook.base_url + 'openbis/datasetTypes/' + connection_name
                fetch(url)
                    .then(function (response) {
                        if (response.ok) {
                            response.json()
                                .then(function (data) {
                                    var change_input_fields = function () {
    
                                        var oldType = state.uploadDataSetType
                                        if (oldType != null && !(oldType in state.uploadDataSetTypes)) {
                                            state.uploadDataSetTypes[oldType] = {}
                                        }
    
                                        state.uploadDataSetType = dataset_types.options[dataset_types.selectedIndex].value
    
    
                                        // remove existing input fields
                                        while (input_fields.firstChild) {
    
                                            var element = input_fields.firstChild
    
                                            if (element.nodeName === "INPUT" && state.uploadDataSetType != null) {
                                                state.uploadDataSetTypes[oldType][element.name] = element.value
                                            }
    
                                            input_fields.removeChild(element)
    
                                        }
    
                                        // for every property assignment, create an input field.
                                        for (pa of dts[dataset_types.selectedIndex].propertyAssignments) {
    
                                            var input_title = document.createElement("STRONG")
                                            input_title.textContent = pa.mandatory ? pa.label + " (mandatory)" : pa.label
                                            var input_error = createErrorElement('prop.'+pa.code)
    
    
                                            var input_field = document.createElement("INPUT")
                                            input_field.type = "text"
                                            input_field.name = pa.code
    
                                            input_field.placeholder = pa.description ? pa.description : pa.label
    
                                            var mem = state.uploadDataSetTypes[dts[dataset_types.selectedIndex].code]
                                            if (mem == null) {
    
                                                    "$HISTORY_ID" : getOpenBISHistoryId() // History Id should get automatically populated if available
    
                                            input_fields.appendChild(input_title)
                                            input_fields.appendChild(input_error)
    
                                            input_fields.appendChild(input_field)
                                            input_fields.appendChild(document.createElement("BR"))
                                        }
                                    }
                                    dataset_types.onchange = change_input_fields
    
                                    // remove the old and add the new dataset-types
                                    dts = data.dataSetTypes
                                    while (dataset_types.firstChild) {
                                        dataset_types.removeChild(dataset_types.firstChild);
                                    }
    
                                    for (dt of dts) {
                                        var option = document.createElement("OPTION")
                                        option.value = dt.code
                                        option.textContent = dt.description ? dt.code + ": " + dt.description : dt.code
                                        dataset_types.appendChild(option)
    
    
                                        if (dt.code === state.uploadDataSetType) {
                                            selectedIndex = index
                                        }
                                        index++
    
    
                                    dataset_types.selectedIndex = selectedIndex === -1 ? 0 : selectedIndex
    
                                    // change the input fields, since we just received new datasetTypes
                                    change_input_fields()
    
                                })
                                .catch(function (error) {
                                    console.error("Error while parsing dataset types", error)
                                })
    
    
                        }
                        else {
                            // ! response.ok
                            errorElements.main.textContent = "Network problem: please check your connection first."
    
                            while (dataset_types.firstChild) {
                                dataset_types.removeChild(dataset_types.firstChild);
                            }
                        }
                    })
                    .catch(function (error) {
                        console.error("Error while fetching dataset types:", error)
                    })
    
            function createSelectTable(values, container, checked, overrides) {
    
    
                var table = document.createElement("TABLE")
                table.className = 'table-bordered table-striped table-condensed'
                table.style.width = "100%"
                
                var body = table.createTBody()
    
                var checkboxes = []
                values.forEach( value => {
                    var row = body.insertRow()
                    var checkbox = document.createElement("INPUT")
                    checkbox.type = "checkbox"
                    checkbox.value = value
    
                    checkbox.checked = overrides.includes(value) ? !checked :  checked
    
                    checkboxes.push(checkbox)
                    row.insertCell().appendChild(checkbox)
                    var valueCell = row.insertCell()
                    valueCell.textContent = value
                    valueCell.style.width = "100%"
                })
                container.appendChild(table)
    
    
                return checkboxes
    
            function createFileTable(env, data, container, state) {
                // list of files that will be uploaded as a dataSet.
    
    
                var table = document.createElement("TABLE")
                table.className = 'table-bordered table-striped table-condensed'
                table.style.width = "100%"
    
                var body = table.createTBody()
                if (data.path !== "") {
                    var row = body.insertRow()
                    row.insertCell()
                    var iconCell = row.insertCell()
                    iconCell.className = "item_icon folder_icon icon-fixed-width"
                    var filenameCell = row.insertCell()
                    filenameCell.textContent = ".."
                    filenameCell.style.width = "80%"
    
                    filenameCell.style.cursor = "pointer"
    
                    filenameCell.onclick = function(){
                        var elems = data.path.split('/')
                        elems.pop()
                        get_file_list(env, container, elems.join('/'))
                    }
    
                    var sizeCell = row.insertCell()
                    sizeCell.style.textAlign = "right"
                    sizeCell.style.width = "15%"
                }
    
    
                var registerFile = function () {
                    if (this.checked) {
                        // add file to state
                        state.selectedFiles.push(this.value)
                    }
                    else {
                        // remove file from state
                        state.selectedFiles.splice(state.selectedFiles.indexOf(this.value), 1)
                    }
                }
    
    
                var checkboxes = []
                data.content.sort( (a, b) => a.name.localeCompare(b.name, undefined, {sensitivity: 'base'}) ).forEach( file => {
    
                    var row = body.insertRow()
                    var checkboxCell = row.insertCell()
                    checkboxCell.style.width="5%"
                    var iconCell = row.insertCell()
                    var filenameCell = row.insertCell()
    
                    filenameCell.textContent = file.name
                    filenameCell.style.width = "100%"
    
                    filenameCell.style.cursor = "pointer"
    
    
                    if (file.type === "directory") {
                        iconCell.className = "item_icon folder_icon icon-fixed-width"
                        filenameCell.onclick = function () {
                            get_file_list(env, container, file.path)
                        }
                    }
                    else {
                        var checkbox = document.createElement("INPUT")
                        checkbox.type = "checkbox"
                        checkbox.value = file.path
    
                        checkbox.checked = state.selectedFiles.includes(file.path) ? true: false
                        checkbox.onclick = registerFile
    
                        checkboxes.push(checkbox)
                        checkboxCell.appendChild(checkbox)
    
                        if (file.type === "notebook") {
                            iconCell.className = "item_icon notebook_icon icon-fixed-width"
                        }
                        else {
                            iconCell.className = "item_icon file_icon icon-fixed-width"
                        }
                        filenameCell.onclick = function () {
    
                            checkbox.checked = !checkbox.checked
                            registerFile.call(checkbox)
    
                        }
                    }
    
                    var sizeCell = row.insertCell()
                    sizeCell.textContent = file.size
                    sizeCell.style.textAlign = "right"
                    sizeCell.style.width = "15%"
    
                })
                container.innerHTML = ""
                container.appendChild(table)
                return checkboxes
            }
    
    
            return {
                help: 'upload Notebook and Data to openBIS',
                icon: 'fa-upload',
                help_index: '',
                handler: function (env) {
    
    
                    var main_error = createErrorElement('main')
    
    
                    var dst_title = document.createElement("STRONG")
    
                    dst_title.textContent = "choose a dataSet type"
    
                    var dataset_types = document.createElement("SELECT")
                    dataset_types.id = "dataset_type"
                    dataset_types.className = "form-control select-xs"
    
                    dataset_types.style.marginLeft = 0
    
                    input_fields.setAttribute("id", "upload-input-fields");
    
    
                    getDatasetTypes(env, state.connection.name, dataset_types, input_fields)
    
                    var sample_title = document.createElement("STRONG")
    
                    sample_title.textContent = "enter a sample/experiment identifier to attach this dataSet to:"
    
                    var sample_error = createErrorElement('entityIdentifier')
    
                    //var entityIdentifier = entitySearcher.getEntitySearcherForUpload(state)
                    var entityIdentifier = document.createElement("INPUT")
                    entityIdentifier.type = "text"
                    entityIdentifier.name = "entityIdentifier"
                    entityIdentifier.size = 40
                    entityIdentifier.placeholder = "Sample or Experiment identifier/permId"
                    entityIdentifier.value = state.entityIdentifier ? state.entityIdentifier : ""
    
                    var dataSetListContainer = document.createElement("DIV")
    
                    if (env.notebook.metadata.datasets) {
    
                        ds_title.textContent = "Parent DataSets"
    
                        dataSetListContainer.style.maxHeight="150px"
                        dataSetListContainer.style.overflow="auto"
                        get_dataset_list(env, dataSetListContainer)
                    }
    
    
                    var files_title = document.createElement("STRONG")
    
                    files_title.textContent = "Files to upload"
    
                    var fileListContainer = document.createElement("DIV")
    
                    fileListContainer.style.height="200px"
    
                    fileListContainer.style.overflow="auto"
    
    Swen Vermeul's avatar
    Swen Vermeul committed
                    // get the relative path
                    let re = new RegExp(env.notebook.notebook_name+"$")
                    rel_path = env.notebook.notebook_path.replace(re, "")
                    get_file_list(env, fileListContainer, rel_path)
    
                    var inputs = document.createElement("DIV")
                    inputs.style.marginTop = '10px'
    
                    inputs.appendChild(main_error)
                    inputs.appendChild(spinner)
                    inputs.appendChild(document.createElement("BR"))
    
                    inputs.appendChild(dst_title)
                    inputs.appendChild(dataset_types)
                    inputs.appendChild(input_fields)
                    inputs.appendChild(sample_title)
    
                    inputs.appendChild(document.createElement('BR'))
    
                    inputs.appendChild(document.createElement('BR'))
    
                    inputs.appendChild(document.createElement('BR'))
    
                    inputs.appendChild(dataSetListContainer)
                    inputs.appendChild(files_title)
                    inputs.appendChild(fileListContainer)
    
                    var uploadDialogBox = $('<div/>').append(inputs)
    
                    function saveState() {
                        state.uploadDataSetTypes[state.uploadDataSetType] = {}
                        for (element of input_fields.children) {
                            if (element.nodeName === "INPUT" && state.uploadDataSetType != null) {
                                state.uploadDataSetTypes[state.uploadDataSetType][element.name] = element.value
                            }
                        }
    
                        state.unselectedDatasets = state.datasetCheckboxes.filter(cb => !cb.checked).map(cb => cb.value)
    
                        //state.selectedFiles = state.fileCheckboxes.filter(cb => cb.checked).map(cb => cb.value)
    
                    function onOk() {
                        var connection_name = state.connection.name
    
                        if (!connection_name) {
                            alert("No connection selected")
                            return false
                        }
    
                        var uploadUrl = env.notebook.base_url + 'openbis/dataset/' + connection_name
    
    Swen Vermeul's avatar
    Swen Vermeul committed
    
                        // add this notebook to the list of files
    
                        var files = state.selectedFiles
    
    Swen Vermeul's avatar
    Swen Vermeul committed
                        if (! files.includes(env.notebook.notebook_path)) {
                            files.push(env.notebook.notebook_path)
    
                        }
                        console.log(files)
    
    
                        var props = {}
                        for (input of $('#upload-input-fields').find('input')) {
                            props[input.name] = input.value
                        }
    
    
                        var dataSetInfo = {
                            "type": dataset_types.value,
                            "files": files,
    
                            "parents": state.datasetCheckboxes.filter(cb => cb.checked).map(cb => cb.value),
    
                            "entityIdentifier": entityIdentifier.value,
    
                        console.log(dataSetInfo);
    
    
                        var settings = {
                            url: uploadUrl,
                            processData: false,
                            type: 'POST',
                            dataType: 'json',
                            data: JSON.stringify(dataSetInfo),
                            contentType: 'application/json',
                            success: function (data) {
    
                                $('div.modal').remove()
                                $('div.modal-backdrop').remove()
    
                                common.createFeedback('success', data.statusText)
    
                                // write statusText from returned data to notebooks metadata
    
    Swen Vermeul's avatar
    Swen Vermeul committed
                                if (typeof env.notebook.metadata.openbis === 'undefined') {
                                    env.notebook.metadata.openbis = {}
    
    Swen Vermeul's avatar
    Swen Vermeul committed
                                if (typeof env.notebook.metadata.openbis.permIds === 'undefined') {
                                    env.notebook.metadata.openbis.permIds = {}
    
    Swen Vermeul's avatar
    Swen Vermeul committed
                                    env.notebook.metadata.openbis.permIds[data.permId] = data.statusText
    
                                if ("errors" in data.responseJSON) {
                                    var errors = data.responseJSON.errors
    
                                    for (error of errors) {
                                        let key, value
                                        Object.keys(error).forEach(k => {
    
                                        errorElements[key in errorElements ? key : "main"].textContent = value
    
                                } else {
                                    errorElements["main"].textContent = "Server error"
    
                    dialog_params = {
                        body: uploadDialogBox,
                        title: 'Upload openBIS DataSet',
                        buttons: {
                            'Cancel': {
                                click: onCancel
    
                            'Upload': {
                                class: 'btn-primary btn-large',
                                click: onOk
                            }
                        },
                        notebook: env.notebook,
                        keyboard_manager: env.notebook.keyboard_manager
                    }
    
                    if (env.notebook.dirty === true) {
                        env.notebook.save_notebook()
                            .then(function () {
                                dialog.modal(dialog_params)
                            })
                            .catch(function (error) {
                                dialog.modal({
                                    body: error,
                                    title: 'Error saving the notebook',
                                    buttons: {
                                        'Back': {}
                                    },
                                    notebook: env.notebook,
                                    keyboard_manager: env.notebook.keyboard_manager
                                })
                            })
                    }
                    else {
                        dialog.modal(dialog_params)