From 4027b2fc23554d67f3a4165f005d0082ca47d2b6 Mon Sep 17 00:00:00 2001 From: rly Date: Fri, 7 Mar 2025 15:55:48 -0800 Subject: [PATCH 1/7] Clear Neurosift storage when rendering Neurosift --- src/electron/frontend/core/components/Neurosift.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/electron/frontend/core/components/Neurosift.js b/src/electron/frontend/core/components/Neurosift.js index 381e6dbca..efcc5946f 100644 --- a/src/electron/frontend/core/components/Neurosift.js +++ b/src/electron/frontend/core/components/Neurosift.js @@ -78,6 +78,10 @@ export class Neurosift extends LitElement { } render() { + // Clear neurosift cross-session storage database + // see https://github.com/NeurodataWithoutBorders/nwb-guide/issues/974 + indexedDB.deleteDatabase("neurosift-hdf5-cache"); + return this.url ? html`
${new Loader({ From 15056462b6f220fc5f7d97ed8cb6d61509f6b01b Mon Sep 17 00:00:00 2001 From: rly Date: Tue, 11 Mar 2025 17:14:53 -0700 Subject: [PATCH 2/7] Add neurosift clear cache test and ts declarations --- .../frontend/core/components/Neurosift.js | 4 +- .../core/components/Neurosift.js.d.ts | 16 +++++ tests/components/Neurosift.test.ts | 65 +++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/electron/frontend/core/components/Neurosift.js.d.ts create mode 100644 tests/components/Neurosift.test.ts diff --git a/src/electron/frontend/core/components/Neurosift.js b/src/electron/frontend/core/components/Neurosift.js index efcc5946f..9a0033852 100644 --- a/src/electron/frontend/core/components/Neurosift.js +++ b/src/electron/frontend/core/components/Neurosift.js @@ -80,7 +80,9 @@ export class Neurosift extends LitElement { render() { // Clear neurosift cross-session storage database // see https://github.com/NeurodataWithoutBorders/nwb-guide/issues/974 - indexedDB.deleteDatabase("neurosift-hdf5-cache"); + if (this.url) { + indexedDB.deleteDatabase("neurosift-hdf5-cache"); + } return this.url ? html`
diff --git a/src/electron/frontend/core/components/Neurosift.js.d.ts b/src/electron/frontend/core/components/Neurosift.js.d.ts new file mode 100644 index 000000000..61f0ef588 --- /dev/null +++ b/src/electron/frontend/core/components/Neurosift.js.d.ts @@ -0,0 +1,16 @@ +import { LitElement, CSSResult, TemplateResult } from "lit"; + +export declare function getURLFromFilePath(file: string, projectName: string): string; + +export declare class Neurosift extends LitElement { + url?: string; + fullscreen: boolean; + + static get styles(): CSSResult; + + static get properties(): { + url: { type: typeof String; reflect: true }; + }; + + protected render(): TemplateResult | string; +} diff --git a/tests/components/Neurosift.test.ts b/tests/components/Neurosift.test.ts new file mode 100644 index 000000000..f9c5e4e91 --- /dev/null +++ b/tests/components/Neurosift.test.ts @@ -0,0 +1,65 @@ +// Test that the indexed database is not cleared on initial render and cleared +// when a url is provided and the component is rendered again as in PreviewPage.js +import { describe, test, expect, beforeEach, afterEach, vi } from 'vitest'; +import { Neurosift } from '../../src/electron/frontend/core/components/Neurosift.js'; + +describe('Neurosift', () => { + let originalIndexedDB: IDBFactory; + let mockDeleteDatabase: ReturnType; + + beforeEach(() => { + // Mock indexedDB.deleteDatabase so that we can test if it is called + mockDeleteDatabase = vi.fn(); + originalIndexedDB = window.indexedDB; + window.indexedDB = { + deleteDatabase: mockDeleteDatabase, + open: vi.fn(), + databases: vi.fn(), + cmp: vi.fn() + } as unknown as IDBFactory; + }); + + afterEach(() => { + // Restore original indexedDB + window.indexedDB = originalIndexedDB; + }); + + test('if neurosift storage is not cleared on initial render', async () => { + const neurosift = new Neurosift(); + + // Add the component to the DOM + document.body.appendChild(neurosift); + + // Wait for the component to render + await neurosift.requestUpdate(); + + // Verify deleteDatabase was not called + expect(mockDeleteDatabase).not.toHaveBeenCalled(); + + // Remove the component from the DOM + document.body.removeChild(neurosift); + }); + + test('if neurosift storage is cleared when url is provided and component is rendered again', async () => { + const neurosift = new Neurosift(); + + // Add the component to the DOM + document.body.appendChild(neurosift); + + // Wait for the component to render + await neurosift.requestUpdate(); + + // Set the URL to a test URL + neurosift.url = 'http://test.url/files/test.nwb'; + + // Wait for the component to render again + await neurosift.requestUpdate(); + + // Verify deleteDatabase was called + expect(mockDeleteDatabase).toHaveBeenCalledWith('neurosift-hdf5-cache'); + expect(mockDeleteDatabase).toHaveBeenCalledTimes(1); + + // Remove the component from the DOM + document.body.removeChild(neurosift); + }); +}); \ No newline at end of file From 51db9d825c3bcdf61dc821d6a9f476417fb76aa7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 00:16:05 +0000 Subject: [PATCH 3/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/electron/frontend/core/components/Neurosift.js.d.ts | 2 +- tests/components/Neurosift.test.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/electron/frontend/core/components/Neurosift.js.d.ts b/src/electron/frontend/core/components/Neurosift.js.d.ts index 61f0ef588..2bcdcd493 100644 --- a/src/electron/frontend/core/components/Neurosift.js.d.ts +++ b/src/electron/frontend/core/components/Neurosift.js.d.ts @@ -1,6 +1,6 @@ import { LitElement, CSSResult, TemplateResult } from "lit"; -export declare function getURLFromFilePath(file: string, projectName: string): string; +export declare function getURLFromFilePath(file: string, projectName: string): string; export declare class Neurosift extends LitElement { url?: string; diff --git a/tests/components/Neurosift.test.ts b/tests/components/Neurosift.test.ts index f9c5e4e91..7cfe83573 100644 --- a/tests/components/Neurosift.test.ts +++ b/tests/components/Neurosift.test.ts @@ -27,7 +27,7 @@ describe('Neurosift', () => { test('if neurosift storage is not cleared on initial render', async () => { const neurosift = new Neurosift(); - // Add the component to the DOM + // Add the component to the DOM document.body.appendChild(neurosift); // Wait for the component to render @@ -43,7 +43,7 @@ describe('Neurosift', () => { test('if neurosift storage is cleared when url is provided and component is rendered again', async () => { const neurosift = new Neurosift(); - // Add the component to the DOM + // Add the component to the DOM document.body.appendChild(neurosift); // Wait for the component to render @@ -62,4 +62,4 @@ describe('Neurosift', () => { // Remove the component from the DOM document.body.removeChild(neurosift); }); -}); \ No newline at end of file +}); From 86cbf078fd69f286108aedf0ca17fabc89a13a4a Mon Sep 17 00:00:00 2001 From: rly Date: Tue, 11 Mar 2025 17:16:53 -0700 Subject: [PATCH 4/7] Expand neurosift clear cache test --- tests/components/Neurosift.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/components/Neurosift.test.ts b/tests/components/Neurosift.test.ts index 7cfe83573..70d4c0428 100644 --- a/tests/components/Neurosift.test.ts +++ b/tests/components/Neurosift.test.ts @@ -59,6 +59,13 @@ describe('Neurosift', () => { expect(mockDeleteDatabase).toHaveBeenCalledWith('neurosift-hdf5-cache'); expect(mockDeleteDatabase).toHaveBeenCalledTimes(1); + // Wait for the component to render again + await neurosift.requestUpdate(); + + // Verify deleteDatabase was called + expect(mockDeleteDatabase).toHaveBeenCalledWith('neurosift-hdf5-cache'); + expect(mockDeleteDatabase).toHaveBeenCalledTimes(2); + // Remove the component from the DOM document.body.removeChild(neurosift); }); From 9f4331f9079cd59f1c691a536c750869a94de723 Mon Sep 17 00:00:00 2001 From: rly Date: Tue, 11 Mar 2025 17:34:39 -0700 Subject: [PATCH 5/7] convert neurosift.js to a ts file --- .../core/components/Neurosift.js.d.ts | 16 -- .../components/{Neurosift.js => Neurosift.ts} | 215 +++++++++--------- tests/components/Neurosift.test.ts | 12 +- 3 files changed, 117 insertions(+), 126 deletions(-) delete mode 100644 src/electron/frontend/core/components/Neurosift.js.d.ts rename src/electron/frontend/core/components/{Neurosift.js => Neurosift.ts} (74%) diff --git a/src/electron/frontend/core/components/Neurosift.js.d.ts b/src/electron/frontend/core/components/Neurosift.js.d.ts deleted file mode 100644 index 2bcdcd493..000000000 --- a/src/electron/frontend/core/components/Neurosift.js.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { LitElement, CSSResult, TemplateResult } from "lit"; - -export declare function getURLFromFilePath(file: string, projectName: string): string; - -export declare class Neurosift extends LitElement { - url?: string; - fullscreen: boolean; - - static get styles(): CSSResult; - - static get properties(): { - url: { type: typeof String; reflect: true }; - }; - - protected render(): TemplateResult | string; -} diff --git a/src/electron/frontend/core/components/Neurosift.js b/src/electron/frontend/core/components/Neurosift.ts similarity index 74% rename from src/electron/frontend/core/components/Neurosift.js rename to src/electron/frontend/core/components/Neurosift.ts index 9a0033852..015434dd8 100644 --- a/src/electron/frontend/core/components/Neurosift.js +++ b/src/electron/frontend/core/components/Neurosift.ts @@ -1,105 +1,110 @@ -import { LitElement, css, html } from "lit"; - -import { Loader } from "./Loader"; -import { FullScreenToggle } from "./FullScreenToggle"; -import { baseUrl } from "../server/globals"; - -export function getURLFromFilePath(file, projectName) { - const regexp = new RegExp(`.+(${projectName}.+)`); - return `${baseUrl}/preview/${file.match(regexp)[1]}`; -} - -export class Neurosift extends LitElement { - static get styles() { - return css` - :host { - background: white; - width: 100%; - height: 100%; - display: grid; - grid-template-rows: 100%; - grid-template-columns: 100%; - position: relative; - --loader-color: hsl(200, 80%, 50%); - } - - iframe, - .loader-container { - width: 100%; - height: 100%; - } - - .loader-container { - display: flex; - align-items: center; - justify-content: center; - position: absolute; - top: 0; - left: 0; - } - - .fullscreen-toggle { - display: flex; - position: absolute; - top: 10px; - right: 10px; - padding: 10px; - color: white; - background-color: gainsboro; - border: 1px solid gray; - border-radius: 10px; - cursor: pointer; - } - - span { - font-size: 14px; - } - - small { - padding-left: 10px; - } - - iframe { - border: 0; - } - `; - } - - static get properties() { - return { - url: { type: String, reflect: true }, - }; - } - - constructor({ url, fullscreen = true } = {}) { - super(); - this.url = url; - this.fullscreen = fullscreen; - } - - render() { - // Clear neurosift cross-session storage database - // see https://github.com/NeurodataWithoutBorders/nwb-guide/issues/974 - if (this.url) { - indexedDB.deleteDatabase("neurosift-hdf5-cache"); - } - - return this.url - ? html`
- ${new Loader({ - message: `Loading Neurosift view...
${this.url}`, - })} -
- ${this.fullscreen ? new FullScreenToggle({ target: this }) : ""} - ` - : ``; - } -} - -customElements.get("neurosift-iframe") || customElements.define("neurosift-iframe", Neurosift); +import { LitElement, css, html, CSSResult, TemplateResult } from "lit"; +import { Loader } from "./Loader"; +import { FullScreenToggle } from "./FullScreenToggle"; +import { baseUrl } from "../server/globals"; + +export function getURLFromFilePath(file: string, projectName: string): string { + const regexp = new RegExp(`.+(${projectName}.+)`); + const match = file.match(regexp); + if (!match) throw new Error(`File path ${file} does not contain project name ${projectName}`); + return `${baseUrl}/preview/${match[1]}`; +} + +export class Neurosift extends LitElement { + static get styles(): CSSResult { + return css` + :host { + background: white; + width: 100%; + height: 100%; + display: grid; + grid-template-rows: 100%; + grid-template-columns: 100%; + position: relative; + --loader-color: hsl(200, 80%, 50%); + } + + iframe, + .loader-container { + width: 100%; + height: 100%; + } + + .loader-container { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 0; + left: 0; + } + + .fullscreen-toggle { + display: flex; + position: absolute; + top: 10px; + right: 10px; + padding: 10px; + color: white; + background-color: gainsboro; + border: 1px solid gray; + border-radius: 10px; + cursor: pointer; + } + + span { + font-size: 14px; + } + + small { + padding-left: 10px; + } + + iframe { + border: 0; + } + `; + } + + static get properties() { + return { + url: { type: String, reflect: true }, + fullscreen: { type: Boolean } + }; + } + + declare url?: string; + declare fullscreen: boolean; + + constructor(options: { url?: string; fullscreen?: boolean } = {}) { + super(); + this.url = options.url; + this.fullscreen = options.fullscreen ?? true; + } + + render(): TemplateResult | string { + // Clear neurosift cross-session storage database + // see https://github.com/NeurodataWithoutBorders/nwb-guide/issues/974 + if (this.url) { + indexedDB.deleteDatabase("neurosift-hdf5-cache"); + } + + return this.url + ? html`
+ ${new Loader({ + message: `Loading Neurosift view...
${this.url}`, + })} +
+ ${this.fullscreen ? new FullScreenToggle({ target: this }) : ""} + ` + : ""; + } +} + +customElements.get("neurosift-iframe") || customElements.define("neurosift-iframe", Neurosift); \ No newline at end of file diff --git a/tests/components/Neurosift.test.ts b/tests/components/Neurosift.test.ts index 70d4c0428..d9efe93fc 100644 --- a/tests/components/Neurosift.test.ts +++ b/tests/components/Neurosift.test.ts @@ -1,7 +1,7 @@ // Test that the indexed database is not cleared on initial render and cleared // when a url is provided and the component is rendered again as in PreviewPage.js import { describe, test, expect, beforeEach, afterEach, vi } from 'vitest'; -import { Neurosift } from '../../src/electron/frontend/core/components/Neurosift.js'; +import { Neurosift } from '../../src/electron/frontend/core/components/Neurosift'; describe('Neurosift', () => { let originalIndexedDB: IDBFactory; @@ -31,7 +31,7 @@ describe('Neurosift', () => { document.body.appendChild(neurosift); // Wait for the component to render - await neurosift.requestUpdate(); + neurosift.requestUpdate(); // Verify deleteDatabase was not called expect(mockDeleteDatabase).not.toHaveBeenCalled(); @@ -47,20 +47,22 @@ describe('Neurosift', () => { document.body.appendChild(neurosift); // Wait for the component to render - await neurosift.requestUpdate(); + neurosift.requestUpdate(); // Set the URL to a test URL neurosift.url = 'http://test.url/files/test.nwb'; // Wait for the component to render again - await neurosift.requestUpdate(); + neurosift.requestUpdate(); + await neurosift.updateComplete; // Verify deleteDatabase was called expect(mockDeleteDatabase).toHaveBeenCalledWith('neurosift-hdf5-cache'); expect(mockDeleteDatabase).toHaveBeenCalledTimes(1); // Wait for the component to render again - await neurosift.requestUpdate(); + neurosift.requestUpdate(); + await neurosift.updateComplete; // Verify deleteDatabase was called expect(mockDeleteDatabase).toHaveBeenCalledWith('neurosift-hdf5-cache'); From 9057b8d72e7dc849ca9a0e5831da1f543c763d48 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 00:34:58 +0000 Subject: [PATCH 6/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/electron/frontend/core/components/Neurosift.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/electron/frontend/core/components/Neurosift.ts b/src/electron/frontend/core/components/Neurosift.ts index 015434dd8..3214396f1 100644 --- a/src/electron/frontend/core/components/Neurosift.ts +++ b/src/electron/frontend/core/components/Neurosift.ts @@ -107,4 +107,4 @@ export class Neurosift extends LitElement { } } -customElements.get("neurosift-iframe") || customElements.define("neurosift-iframe", Neurosift); \ No newline at end of file +customElements.get("neurosift-iframe") || customElements.define("neurosift-iframe", Neurosift); From acfe2eec9fdf8aa29f8a10edf3666944626fc1fa Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Mon, 24 Mar 2025 23:52:03 -0400 Subject: [PATCH 7/7] Fix import issue --- .../frontend/core/components/pages/preview/PreviewPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/electron/frontend/core/components/pages/preview/PreviewPage.js b/src/electron/frontend/core/components/pages/preview/PreviewPage.js index 8dfe7b4d6..0b4c44eca 100644 --- a/src/electron/frontend/core/components/pages/preview/PreviewPage.js +++ b/src/electron/frontend/core/components/pages/preview/PreviewPage.js @@ -2,7 +2,7 @@ import { html } from "lit"; import { Page } from "../Page.js"; import { onThrow } from "../../../errors"; import { JSONSchemaInput } from "../../JSONSchemaInput.js"; -import { Neurosift } from "../../Neurosift.js"; +import { Neurosift } from "../../Neurosift"; import { baseUrl } from "../../../server/globals"; export class PreviewPage extends Page {