Skip to content

Commit

Permalink
Merge pull request #372 from NeurodataWithoutBorders/dandi-files-or-f…
Browse files Browse the repository at this point in the history
…olders

Upload Multiple Files and Directories
  • Loading branch information
CodyCBakerPhD authored Oct 2, 2023
2 parents 2a1b940 + 1b255dd commit 308ac3c
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 14 deletions.
32 changes: 27 additions & 5 deletions pyflask/apis/neuroconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
inspect_nwb_file,
inspect_nwb_folder,
inspect_multiple_filesystem_objects,
upload_to_dandi,
upload_folder_to_dandi,
upload_multiple_filesystem_objects_to_dandi,
)

from errorHandlers import notBadRequestException
Expand Down Expand Up @@ -112,13 +115,11 @@ def post(self):
neuroconv_api.abort(500, str(e))


@neuroconv_api.route("/upload")
@neuroconv_api.route("/upload/project")
class Upload(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
try:
from manageNeuroconv import upload_to_dandi

return upload_to_dandi(**neuroconv_api.payload)

except Exception as e:
Expand All @@ -131,15 +132,36 @@ class Upload(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
try:
from manageNeuroconv import upload_folder_to_dandi

return upload_folder_to_dandi(**neuroconv_api.payload)

except Exception as e:
if notBadRequestException(e):
neuroconv_api.abort(500, str(e))


@neuroconv_api.route("/upload")
class Upload(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
from os.path import isdir

try:
paths = neuroconv_api.payload["filesystem_paths"]

if len(paths) == 1 and isdir(paths[0]):
kwargs = {**neuroconv_api.payload}
del kwargs["filesystem_paths"]
kwargs["nwb_folder_path"] = paths[0]
return upload_folder_to_dandi(**kwargs)

else:
return upload_multiple_filesystem_objects_to_dandi(**neuroconv_api.payload)

except Exception as e:
if notBadRequestException(e):
neuroconv_api.abort(500, str(e))


@neuroconv_api.route("/inspect_file")
class InspectNWBFile(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
Expand Down
1 change: 1 addition & 0 deletions pyflask/manageNeuroconv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
validate_metadata,
upload_to_dandi,
upload_folder_to_dandi,
upload_multiple_filesystem_objects_to_dandi,
listen_to_neuroconv_events,
generate_dataset,
inspect_nwb_file,
Expand Down
10 changes: 10 additions & 0 deletions pyflask/manageNeuroconv/manage_neuroconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,16 @@ def update_conversion_progress(**kwargs):
return dict(file=str(resolved_output_path))


def upload_multiple_filesystem_objects_to_dandi(**kwargs):
tmp_folder_path = aggregate_symlinks_in_new_directory(kwargs["filesystem_paths"], "upload")
innerKwargs = {**kwargs}
del innerKwargs["filesystem_paths"]
innerKwargs["nwb_folder_path"] = tmp_folder_path
result = upload_folder_to_dandi(**innerKwargs)
rmtree(tmp_folder_path)
return result


def upload_folder_to_dandi(
dandiset_id: str,
api_key: str,
Expand Down
11 changes: 7 additions & 4 deletions schemas/json/dandi/standalone.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
{
"properties": {
"nwb_folder_path": {
"type": "string",
"format": "directory"
"filesystem_paths": {
"type": "array",
"items":{
"type": "string",
"format": ["file", "directory"]
}
}
},
"required": ["nwb_folder_path"]
"required": ["filesystem_paths"]
}
4 changes: 4 additions & 0 deletions src/renderer/src/stories/FileSystemSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ const componentCSS = css`
gap: 5px;
}
#button-div > nwb-button {
margin-bottom: 10px;
}
button {
background: WhiteSmoke;
border: 1px solid #c3c3c3;
Expand Down
15 changes: 10 additions & 5 deletions src/renderer/src/stories/pages/uploads/UploadsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { html } from "lit";
import { JSONSchemaForm } from "../../JSONSchemaForm.js";
import { Page } from "../Page.js";
import { onThrow } from "../../../errors";

const folderPathKey = "filesystem_paths";
import dandiUploadSchema from "../../../../../../schemas/json/dandi/upload.json";
import dandiStandaloneSchema from "../../../../../../schemas/json/dandi/standalone.json";
const dandiSchema = merge(dandiStandaloneSchema, merge(dandiUploadSchema, {}), { arrays: true });
Expand All @@ -18,8 +20,10 @@ import { DandiResults } from "../../DandiResults.js";

export const isStaging = (id) => parseInt(id) >= 100000;

export async function uploadToDandi(info, type = "project" in info ? "" : "folder") {
const staging = isStaging(info.dandiset_id); // Automatically detect staging IDs
export async function uploadToDandi(info, type = "project" in info ? "project" : "") {
const { dandiset_id } = info;

const staging = isStaging(dandiset_id); // Automatically detect staging IDs

const whichAPIKey = staging ? "staging_api_key" : "main_api_key";
const api_key = global.data.DANDI?.api_keys?.[whichAPIKey];
Expand Down Expand Up @@ -54,7 +58,9 @@ export async function uploadToDandi(info, type = "project" in info ? "" : "folde
if (result)
notyf.open({
type: "success",
message: `${info.project ?? info.nwb_folder_path} successfully uploaded to Dandiset ${info.dandiset_id}`,
message: `${
info.project ?? `${info[folderPathKey].length} filesystem entries`
} successfully uploaded to Dandiset ${dandiset_id}`,
});

return result;
Expand Down Expand Up @@ -89,13 +95,12 @@ export class UploadsPage extends Page {
},
});

const folderPathKey = "nwb_folder_path";
// NOTE: API Keys and Dandiset IDs persist across selected project
this.form = new JSONSchemaForm({
results: globalState,
schema: dandiSchema,
sort: ([k1]) => {
if (k1 === "nwb_folder_path") return -1;
if (k1 === folderPathKey) return -1;
},
onUpdate: ([id]) => {
if (id === folderPathKey) {
Expand Down

0 comments on commit 308ac3c

Please sign in to comment.