Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preview Inspector Results #326

Merged
merged 59 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
4070800
Request the appropriate details from Python and create new custom ele…
garrettmflynn Aug 23, 2023
479699a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
0ff289c
Merge branch 'fix-requirement-check' into preview-inspector-results
garrettmflynn Aug 23, 2023
1f1da67
Create a file preview component and asynchronously resolve additional…
garrettmflynn Aug 23, 2023
17e64b8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
9c7dd03
Fix JSON Schema errors
garrettmflynn Aug 23, 2023
cc590a5
Merge branch 'preview-inspector-results' of https://github.com/Neurod…
garrettmflynn Aug 23, 2023
d2ebbdf
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
957065e
Merge branch 'main' into preview-inspector-results
garrettmflynn Aug 23, 2023
e6f29b0
Proper merge
garrettmflynn Aug 23, 2023
a7c6882
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
9c28e7c
Merge branch 'preview-inspector-results' of https://github.com/Neurod…
garrettmflynn Aug 23, 2023
6e6d680
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
566e7e0
Fix results page
garrettmflynn Aug 23, 2023
8df6a46
Merge branch 'preview-inspector-results' of https://github.com/Neurod…
garrettmflynn Aug 23, 2023
385ac10
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
ab5c97c
Update popup title
garrettmflynn Aug 23, 2023
b6bb7ba
Merge branch 'main' into preview-inspector-results
garrettmflynn Aug 23, 2023
1592ca8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
27e7de0
Merge branch 'main' into preview-inspector-results
garrettmflynn Aug 23, 2023
6814cad
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
d0f10e5
Merge branch 'main' into preview-inspector-results
garrettmflynn Aug 23, 2023
f499150
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
55641ec
Create instance renders dynamically
garrettmflynn Aug 23, 2023
53b87af
Merge branch 'preview-inspector-results' of https://github.com/Neurod…
garrettmflynn Aug 23, 2023
bbb1ceb
Show loader for iframe
garrettmflynn Aug 23, 2023
14684e3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
d765b85
Improved loader
garrettmflynn Aug 23, 2023
528a7ee
Merge branch 'preview-inspector-results' of https://github.com/Neurod…
garrettmflynn Aug 23, 2023
9fea282
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
1eb61bc
Avoid loading popup for html request
garrettmflynn Aug 23, 2023
0344525
Update index.ts
garrettmflynn Aug 23, 2023
68ac48d
Fix list re-rendering
garrettmflynn Aug 23, 2023
c9baea3
Merge branch 'main' into preview-inspector-results
garrettmflynn Aug 23, 2023
e3f1dc3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 23, 2023
6db7ece
Merge branch 'main' into preview-inspector-results
CodyCBakerPhD Aug 24, 2023
6f12ef8
Update pyflask/apis/neuroconv.py
garrettmflynn Aug 24, 2023
b88c928
Update endpoints
garrettmflynn Aug 24, 2023
72f339d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 24, 2023
f378053
Merge branch 'main' into preview-inspector-results
CodyCBakerPhD Aug 25, 2023
c805d03
Align conversion message with main
garrettmflynn Aug 25, 2023
6ce616a
Update header for stub preview
garrettmflynn Aug 25, 2023
4ceb940
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 25, 2023
697ab70
Update pyflask/apis/neuroconv.py
garrettmflynn Aug 25, 2023
d245ae9
Apply suggestions from code review
garrettmflynn Aug 25, 2023
3e08b03
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 25, 2023
b60df94
Remove inspector kwargs overrides from the frontend
garrettmflynn Aug 25, 2023
e2dca4e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 25, 2023
006c749
Update inspector test JSON
garrettmflynn Aug 25, 2023
6d99588
Merge branch 'preview-inspector-results' of https://github.com/Neurod…
garrettmflynn Aug 25, 2023
053d69d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 25, 2023
8a228ae
Fix directory derivation on Windows
garrettmflynn Aug 25, 2023
ea2fb84
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 25, 2023
6e7dfb6
Merge branch 'main' into preview-inspector-results
CodyCBakerPhD Aug 25, 2023
348bb7c
Update NWBFilePreview.js
garrettmflynn Aug 25, 2023
3aaab4f
Merge branch 'preview-inspector-results' of https://github.com/Neurod…
garrettmflynn Aug 25, 2023
f9937b9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 25, 2023
9098693
Update NWBFilePreview.js
garrettmflynn Aug 25, 2023
096327d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 25, 2023
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
72 changes: 72 additions & 0 deletions pyflask/apis/neuroconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,78 @@ def post(self):
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"})
def post(self):
try:
import json
from nwbinspector import inspect_nwbfile
from nwbinspector.nwbinspector import InspectorOutputJSONEncoder

return json.loads(
json.dumps(
list(
inspect_nwbfile(
ignore=[
"check_description",
"check_data_orientation",
], # TODO: remove when metadata control is exposed
**neuroconv_api.payload,
)
),
cls=InspectorOutputJSONEncoder,
)
)

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


@neuroconv_api.route("/inspect_folder")
class InspectNWBFolder(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
try:
import json
from nwbinspector import inspect_all
from nwbinspector.nwbinspector import InspectorOutputJSONEncoder

messages = list(
inspect_all(
n_jobs=-2, # uses number of CPU - 1
ignore=[
"check_description",
"check_data_orientation",
], # TODO: remove when metadata control is exposed
**neuroconv_api.payload,
)
)

return json.loads(json.dumps(messages, cls=InspectorOutputJSONEncoder))

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


@neuroconv_api.route("/html")
class NWBToHTML(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
try:
from pynwb import NWBHDF5IO

with NWBHDF5IO(neuroconv_api.payload.nwbfile_path, mode="r") as io:
html = io.read()._repr_html_()
return html

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


@neuroconv_api.route("/generate_dataset")
class GenerateDataset(Resource):
@neuroconv_api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
Expand Down
2 changes: 1 addition & 1 deletion pyflask/manageNeuroconv/manage_neuroconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ def update_conversion_progress(**kwargs):
if not default_output_directory.exists():
os.symlink(resolved_output_directory, default_output_directory)

return str(resolved_output_path)
return dict(file=str(resolved_output_path))


def upload_to_dandi(
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async function isOffline() {
await Swal.fire({
title: "No Internet Connection",
icon: "warning",
text: "It appears that your computer is not connected to the internet. You may continue, but you will not be able to use features of NWB GUIDE related to uploading data to DANDI.",
text: "You may continue, but certain features (e.g. uploading data to DANDI, viewing data on Neurosift, etc.) will be unavailable.",
heightAuto: false,
backdrop: "rgba(0,0,0, 0.4)",
confirmButtonText: "I understand",
Expand Down Expand Up @@ -87,7 +87,7 @@ async function checkInternetConnection() {
window.addEventListener('online', isOnline);
window.addEventListener('offline', isOffline);

let hasInternet = navigator.onLine
const hasInternet = navigator.onLine
if (hasInternet) isOnline()
else await isOffline()

Expand Down
26 changes: 21 additions & 5 deletions src/renderer/src/stories/InstanceManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,20 @@ export class InstanceManager extends LitElement {
this.instances = props.instances ?? {};
this.header = props.header;
this.instanceType = props.instanceType ?? "Instance";
if (props.renderInstance) this.renderInstance = props.renderInstance;
if (props.onAdded) this.onAdded = props.onAdded;
if (props.onRemoved) this.onRemoved = props.onRemoved;
this.controls = props.controls ?? [];
}

renderInstance = (_, value) => value.content ?? value;
#dynamicInstances = {};

getInstanceContent = ({ id, metadata }) => {
const content = metadata.content ?? metadata;
if (typeof content === "function") {
this.#dynamicInstances[id] = content;
return "";
} else return content;
};

updateState = (id, state) => {
const item = this.#items.find((i) => i.id === id);
Expand Down Expand Up @@ -211,6 +218,8 @@ export class InstanceManager extends LitElement {
el.removeAttribute("selected");
this.shadowRoot.querySelector(`div[data-instance="${instance}"]`).setAttribute("hidden", "");
});

this.#onSelected();
};

#isCategory(value) {
Expand Down Expand Up @@ -258,6 +267,13 @@ export class InstanceManager extends LitElement {
#onSelected = () => {
const selected = this.shadowRoot.querySelector("#selectedName");
selected.innerText = this.#selected;

const dynamic = this.#dynamicInstances[this.#selected];
if (typeof dynamic === "function") {
this.shadowRoot
.querySelector(`div[data-instance="${this.#selected}"]`)
.append((this.#dynamicInstances[this.#selected] = dynamic()));
}
};

#render(toRender = this.instances, path = []) {
Expand Down Expand Up @@ -293,7 +309,7 @@ export class InstanceManager extends LitElement {

const list = html`
${Object.entries(instances).map(([key, info], i) => {
if (info instanceof HTMLElement) info = { content: info };
if (info instanceof HTMLElement || typeof info === "function") info = { content: info };
const listItemInfo = {
id: key,
label: key.split("/").pop(),
Expand Down Expand Up @@ -399,7 +415,7 @@ export class InstanceManager extends LitElement {
</div>
<div id="content">
<div class="controls">
<span id="selectedName">${this.#selected}</span>
<span id="selectedName"></span>
<div>
${this.controls.map((o) => {
return html`<nwb-button
Expand All @@ -422,7 +438,7 @@ export class InstanceManager extends LitElement {
${this.#items.map((item, i) => {
return html`
<div data-instance="${item.id}" ?hidden=${this.#selected !== item.id}>
${this.renderInstance(item.id, item.metadata)}
${this.getInstanceContent(item)}
</div>
`;
})}
Expand Down
34 changes: 5 additions & 29 deletions src/renderer/src/stories/JSONSchemaForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { merge } from "./pages/utils";
import { resolveProperties } from "./pages/guided-mode/data/utils";

import { JSONSchemaInput } from "./JSONSchemaInput";
import { InspectorListItem } from "./preview/inspector/InspectorList";

const componentCSS = `

Expand All @@ -29,30 +30,6 @@ const componentCSS = `
background: rgb(255, 229, 228) !important;
}

.errors {
color: #9d0b0b;
}

.errors > * {
padding: 25px;
background: #f8d7da;
border: 1px solid #f5c2c7;
border-radius: 4px;
margin: 0 0 1em;
}

.warnings {
color: #856404;
}

.warnings > * {
padding: 25px;
background: #fff3cd;
border: 1px solid #ffeeba;
border-radius: 4px;
margin: 0 0 1em;
}

.guided--form-label {
display: block;
width: 100%;
Expand Down Expand Up @@ -277,9 +254,8 @@ export class JSONSchemaForm extends LitElement {
#addMessage = (name, message, type) => {
if (Array.isArray(name)) name = name.join("-"); // Convert array to string
const container = this.shadowRoot.querySelector(`#${name} .${type}`);
const p = document.createElement("p");
p.innerText = message;
container.appendChild(p);
const item = new InspectorListItem(message);
container.appendChild(item);
};

#clearMessages = (fullPath, type) => {
Expand Down Expand Up @@ -625,7 +601,7 @@ export class JSONSchemaForm extends LitElement {
this.checkStatus();

// Show aggregated errors and warnings (if any)
warnings.forEach((info) => this.#addMessage(fullPath, info.message, "warnings"));
warnings.forEach((info) => this.#addMessage(fullPath, info, "warnings"));

const isFunction = typeof valid === "function";

Expand Down Expand Up @@ -658,7 +634,7 @@ export class JSONSchemaForm extends LitElement {
[...path, name]
);

errors.forEach((info) => this.#addMessage(fullPath, info.message, "errors"));
errors.forEach((info) => this.#addMessage(fullPath, info, "errors"));
// element.title = errors.map((info) => info.message).join("\n"); // Set all errors to show on hover

return false;
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/stories/List.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ export default {

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

const generateString = () => Math.floor(Math.random() * Date.now()).toString(36);

export const Default = Template.bind({});
Default.args = {
items: [{ value: "test" }],
items: [{ value: "test" }, { value: Array.from({ length: 1000 }).map(generateString).join("") }],
};

export const WithKeys = Template.bind({});
Expand Down
Loading