Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/electron/frontend/core/components/BasicTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ export class BasicTable extends LitElement {
size="small"
@click=${() => {
const input = document.createElement("input");
input.type = "file";
input.type = "file-path";
input.accept = "text/tab-separated-values";
input.click();
input.onchange = () => {
Expand Down
81 changes: 50 additions & 31 deletions src/electron/frontend/core/components/FileSystemSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,41 @@ const { dialog } = remote;
import restartSVG from "../../assets/icons/restart.svg?raw";
import { unsafeSVG } from "lit/directives/unsafe-svg.js";

function getObjectTypeReferenceString(type, multiple, { nested, native } = {}) {
if (Array.isArray(type))
return `${multiple ? "" : "a "}${type
.map((type) => getObjectTypeReferenceString(type, multiple, { native, nested: true }))
.join(" / ")}`;

const isDir = type === "directory";
return multiple && (!isDir || (isDir && !native) || dialog)
? type === "directory"
? "directories"
: "files"
: nested
? type
: `a ${type}`;
/**
* Generates a human-readable reference string for filesystem object types.
*
* @param {string|Array<string>} type - The filesystem object type(s). Can be "file-path",
* "directory-path", or an array ["file-path", "directory-path"].
* @param {boolean} multiple - Whether multiple objects are expected (affects pluralization).
*
* @returns {string} A formatted reference string like "a file", "directories",
* "a file / directory", etc.
*/
function getObjectTypeReferenceString(type, multiple) {
if (Array.isArray(type)) {
const article = multiple ? "" : "a ";
return `${article}file / directory`;
}

if (multiple) {
return type === "directory-path" ? "directories" : "files";
}

const cleanTypeName = type.replace("-path", "");
return `a ${cleanTypeName}`;
}

/**
* Generates a simple string representation of a filesystem object type.
*
* @param {string|Array<string>} type - The filesystem object type(s).
* @returns {string} A simple string representation of the type(s): "file", "directory", or "file / directory".
*/
function getSimpleObjectTypeString(type) {
if (Array.isArray(type)) {
return "file / directory";
}
return type.replace("-path", "");
}

const componentCSS = css`
Expand Down Expand Up @@ -113,7 +134,7 @@ export class FilesystemSelector extends LitElement {

this.accept = props.accept;
this.multiple = props.multiple;
this.type = props.type ?? "file";
this.type = props.type ?? "file-path";
this.value = props.value ?? "";
this.dialogOptions = props.dialogOptions ?? {};
this.onChange = props.onChange ?? (() => {});
Expand Down Expand Up @@ -146,7 +167,7 @@ export class FilesystemSelector extends LitElement {
}

options.properties = [
type === "file" ? "openFile" : "openDirectory",
type === "file-path" ? "openFile" : "openDirectory",
"noResolveAliases",
...(options.properties ?? []),
];
Expand All @@ -165,8 +186,11 @@ export class FilesystemSelector extends LitElement {
#check = (value) => {
// Check type
const isLikelyFile = fs ? fs.statSync(value).isFile() : value.split(".").length;
if ((this.type === "directory" && isLikelyFile) || (this.type === "file" && !isLikelyFile))
this.#onThrow("Incorrect filesystem object", `Please provide a <b>${this.type}</b> instead.`);
if ((this.type === "directory-path" && isLikelyFile) || (this.type === "file-path" && !isLikelyFile))
this.#onThrow(
"Incorrect filesystem object",
`Please provide a <b>${this.type.replace("-path", "")}</b> instead.`
);
};

#handleFiles = async (pathOrPaths, type) => {
Expand All @@ -182,7 +206,7 @@ export class FilesystemSelector extends LitElement {
if (Array.isArray(resolvedValue) && !this.multiple) {
if (resolvedValue.length > 1)
this.#onThrow(
`Too many ${resolvedType === "directory" ? "directories" : "files"} detected`,
`Too many ${resolvedType === "directory-path" ? "directories" : "files"} detected`,
`This selector will only accept one.`
);
resolvedValue = resolvedValue[0];
Expand All @@ -205,7 +229,7 @@ export class FilesystemSelector extends LitElement {
this.#handleFiles(results.filePath ?? results.filePaths, type);
} else {
let handles = await (
type === "directory"
type === "directory-path"
? window.showDirectoryPicker()
: window.showOpenFilePicker({ multiple: this.multiple })
).catch(() => []); // Call using the same options
Expand All @@ -230,8 +254,6 @@ export class FilesystemSelector extends LitElement {
: this.value[0]
: this.value;

const objectTypeReference = getObjectTypeReferenceString(this.type, this.multiple);

const instanceThis = this;

return html`
Expand Down Expand Up @@ -261,20 +283,18 @@ export class FilesystemSelector extends LitElement {
${dialog
? ""
: html`<br /><small
>Cannot get full ${isMultipleTypes ? this.type.join(" / ") : this.type}
>Cannot get full ${getSimpleObjectTypeString(this.type)}
path${this.multiple ? "s" : ""} on web distribution</small
>`}
`
: html`<span
>Drop ${objectTypeReference}
>Drop ${getObjectTypeReferenceString(this.type, this.multiple)}
here${isMultipleTypes
? ""
: `, or click to choose ${getObjectTypeReferenceString(this.type, this.multiple, {
native: true,
})}`}</span
: `, or click to choose ${getObjectTypeReferenceString(this.type, this.multiple)}`}</span
>${this.multiple &&
(this.type === "directory" ||
(isMultipleTypes && this.type.includes("directory") && !dialog))
(this.type === "directory-path" ||
(isMultipleTypes && this.type.includes("directory-path") && !dialog))
? html`<br /><small
>Multiple directory support only available using drag-and-drop.</small
>`
Expand All @@ -301,8 +321,7 @@ export class FilesystemSelector extends LitElement {
${this.type.map(
(type) =>
html`<nwb-button primary @click=${() => this.selectFormat(type)}
>Select
${getObjectTypeReferenceString(type, this.multiple, { native: true })}</nwb-button
>Select ${getObjectTypeReferenceString(type, this.multiple)}</nwb-button
>`
)}
</div>`
Expand Down
4 changes: 2 additions & 2 deletions src/electron/frontend/core/components/JSONSchemaInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,8 @@ const isFilesystemSelector = (name = "", format) => {
if (Array.isArray(format)) return format.map((f) => isFilesystemSelector(name, f)).every(Boolean) ? format : null;

const matched = name.match(/(.+_)?(.+)_paths?/);
if (!format && matched) format = matched[2] === "folder" ? "directory" : matched[2];
return ["file", "directory"].includes(format) ? format : null; // Handle file and directory formats
if (!format && matched) format = matched[2] === "folder" ? "directory-path" : matched[2];
return ["file-path", "directory-path"].includes(format) ? format : null; // Handle file and directory formats
};

function getFirstFocusableElement(element) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function autocompleteFormatString(path) {
const schema = getSchema(path, this.info.globalState.schema.source_data);

const isFile = "file_path" in schema.properties;
const pathType = isFile ? "file" : "directory";
const pathType = isFile ? "file-path" : "directory-path";

const description = isFile ? schema.properties.file_path.description : schema.properties.folder_path.description;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const options = {
name: "Upload Timestamps",
schema: {
type: "string",
format: "file",
format: "file-path",
description: "A CSV file containing the timestamps of the recording.",
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const questions = {

base_directory: {
type: "string",
format: "directory",
format: "directory-path",
title: "Where is your data located?",
description:
"A single directory where all data is contained. Can override for specific data formats.<br><small>Leave blank if unknown</small>",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class InspectPage extends Page {
type: "array",
items: {
type: "string",
format: ["file", "directory"],
format: ["file-path", "directory-path"],
multiple: true,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class PreviewPage extends Page {
path: ["file_path"],
schema: {
type: "string",
format: "file",
format: "file-path",
description:
"Please provide a file path that you'd like to visualize using Neurosift. The GUIDE will serve this file and access the appropriate URL automatically.",
},
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/json/dandi/standalone.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "array",
"items":{
"type": "string",
"format": ["file", "directory"]
"format": ["file-path", "directory-path"]
},
"minItems": 1
},
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/json/developer/globals.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"properties": {
"testing_data_folder": {
"type": "string",
"format": "directory",
"format": "directory-path",
"description": "Common folder where GIN testing data (e.g. ephy_testing_data, ophys_testing_data) can be found"
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/json/path-expansion.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"properties": {
"base_directory": {
"type": "string",
"format": "directory",
"format": "directory-path",
"description": "Enter the base directory of your data."
},
"format_string_path": {
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/json/project/globals.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"properties": {
"conversion_output_folder": {
"type": "string",
"format": "directory",
"format": "directory-path",
"description": "Provide a custom output location for your NWB files. Will default to ~/NWB_GUIDE/conversions"
}
},
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/json/tutorial.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"properties": {
"test_data_directory_path": {
"type": "string",
"format": "directory",
"format": "directory-path",
"description": "Enter the path to your local instance of the ephy_testing_data directory",
"placeholder": "Enter testing directory path"
}
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/source-data.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function preprocessSourceDataSchema (schema) {

if (schema.properties.file_paths) {
Object.assign(schema.properties.file_paths, {
items: { type: 'string' },
items: { format: 'file-path', type: 'string' },
description: '<b>Only one file supported at this time.</b> Multiple file support coming soon.',
maxItems: 1,
})
Expand Down
2 changes: 1 addition & 1 deletion stories/components/FileSystemSelector.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {

const Template = (args) => new FilesystemSelector(args);

const types = ["file", "directory"];
const types = ["file-path", "directory-path"];

export const File = Template.bind({});
export const Folder = Template.bind({});
Expand Down
4 changes: 2 additions & 2 deletions stories/components/JSONSchemaForm.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ const defaultSchema = {
},
optional: {
type: "string",
format: "file",
format: "file-path",
},
list: {
type: "array",
items: {
type: "string",
format: "file",
format: "file-path",
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
"required": [],
"properties": {
"AlphaOmegaRecordingInterface": {
"required": [
"folder_path"
],
"properties": {
"folder_path": {
"format": "directory",
"format": "directory-path",
"type": "string",
"description": "Path to the folder of .mpx files."
},
"verbose": {
"type": "boolean",
"default": true
"default": true,
"type": "boolean"
},
"es_key": {
"type": "string",
"default": "ElectricalSeries"
"default": "ElectricalSeries",
"type": "string"
}
},
"required": [
"folder_path"
],
"type": "object",
"additionalProperties": false
}
Expand Down
14 changes: 9 additions & 5 deletions stories/inputs/interface_schemas/AudioInterface.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@
"required": [],
"properties": {
"AudioInterface": {
"required": [
"file_paths"
],
"properties": {
"file_paths": {
"items": {
"format": "file-path",
"type": "string"
},
"type": "array"
},
"verbose": {
"type": "boolean",
"default": false
"default": false,
"type": "boolean"
}
},
"required": [
"file_paths"
],
"type": "object",
"additionalProperties": false
}
Expand Down
16 changes: 8 additions & 8 deletions stories/inputs/interface_schemas/AxonaRecordingInterface.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
"required": [],
"properties": {
"AxonaRecordingInterface": {
"required": [
"file_path"
],
"properties": {
"file_path": {
"format": "file",
"format": "file-path",
"type": "string",
"description": "Path to .bin file."
},
"verbose": {
"type": "boolean",
"default": true
"default": true,
"type": "boolean"
},
"es_key": {
"type": "string",
"default": "ElectricalSeries"
"default": "ElectricalSeries",
"type": "string"
}
},
"required": [
"file_path"
],
"type": "object",
"additionalProperties": false
}
Expand Down
Loading
Loading