diff --git a/src/renderer/src/stories/FullScreenToggle.ts b/src/renderer/src/stories/FullScreenToggle.ts
new file mode 100644
index 000000000..ff1e1557f
--- /dev/null
+++ b/src/renderer/src/stories/FullScreenToggle.ts
@@ -0,0 +1,72 @@
+import { LitElement, css, html } from "lit";
+
+import fullScreenIcon from './assets/fullscreen.svg?raw'
+import fullScreenExitIcon from './assets/fullscreen_exit.svg?raw'
+
+import { unsafeHTML } from "lit/directives/unsafe-html.js";
+
+type FullScreenToggleProps = {
+ target: HTMLElement | (() => HTMLElement);
+}
+
+export class FullScreenToggle extends LitElement {
+ static get styles() {
+ return css`
+ :host {
+ display: flex;
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ padding: 10px;
+ color: white;
+ background-color: gainsboro;
+ border: 1px solid gray;
+ border-radius: 10px;
+ cursor: pointer;
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.3);
+ z-index: 1000;
+ opacity: 0.5;
+ transition: opacity 0.5s;
+ }
+
+ :host(:hover) {
+ opacity: 1;
+ }
+ `;
+ }
+
+ static get properties() {
+ return {
+ icon: { type: String },
+ };
+ }
+
+ declare icon: string;
+ declare target: FullScreenToggleProps['target'];
+
+ constructor({ target }: FullScreenToggleProps) {
+
+ super();
+ this.target = target;
+ this.icon = fullScreenIcon
+
+ const fullscreenchanged = () => this.icon = document.fullscreenElement ? fullScreenExitIcon : fullScreenIcon
+
+ this.addEventListener('click', () => {
+ const target = (typeof this.target === 'function' ? this.target() : this.target)
+
+ target.addEventListener("fullscreenchange", fullscreenchanged);
+
+ const fullScreenEl = document.fullscreenElement
+ if (!fullScreenEl) target.requestFullscreen()
+ else document.exitFullscreen()
+
+ })
+ }
+
+ render() {
+ return html`${unsafeHTML(this.icon)}`;
+ }
+}
+
+customElements.get("fullscreen-toggle") || customElements.define("fullscreen-toggle", FullScreenToggle);
diff --git a/src/renderer/src/stories/List.ts b/src/renderer/src/stories/List.ts
index 69c57b1b8..7ffb24b26 100644
--- a/src/renderer/src/stories/List.ts
+++ b/src/renderer/src/stories/List.ts
@@ -240,10 +240,10 @@ export class List extends LitElement {
const { items, emptyMessage} = this
- return items.length || !emptyMessage ? html`
+ return html`
- ${items.map(this.#renderListItem)}
-
` : html`${emptyMessage}
`
+ ${(items.length || !emptyMessage) ? items.map(this.#renderListItem) : html`${emptyMessage}
`}
+ `
}
}
diff --git a/src/renderer/src/stories/Modal.ts b/src/renderer/src/stories/Modal.ts
index 62e19f008..83363090f 100644
--- a/src/renderer/src/stories/Modal.ts
+++ b/src/renderer/src/stories/Modal.ts
@@ -51,6 +51,7 @@ export class Modal extends LitElement {
/* Modal Body */
.modal-body {
+ position: relative;
overflow-y: auto;
width: 100%;
flex-grow: 1;
diff --git a/src/renderer/src/stories/assets/fullscreen.svg b/src/renderer/src/stories/assets/fullscreen.svg
new file mode 100644
index 000000000..f1d258a7d
--- /dev/null
+++ b/src/renderer/src/stories/assets/fullscreen.svg
@@ -0,0 +1 @@
+
diff --git a/src/renderer/src/stories/assets/fullscreen_exit.svg b/src/renderer/src/stories/assets/fullscreen_exit.svg
new file mode 100644
index 000000000..9a3189294
--- /dev/null
+++ b/src/renderer/src/stories/assets/fullscreen_exit.svg
@@ -0,0 +1 @@
+
diff --git a/src/renderer/src/stories/preview/NWBFilePreview.js b/src/renderer/src/stories/preview/NWBFilePreview.js
index 3a5de8286..cf3a1e66b 100644
--- a/src/renderer/src/stories/preview/NWBFilePreview.js
+++ b/src/renderer/src/stories/preview/NWBFilePreview.js
@@ -6,6 +6,7 @@ import { run } from "../pages/guided-mode/options/utils";
import { until } from "lit/directives/until.js";
import { InstanceManager } from "../InstanceManager";
import { path } from "../../electron";
+import { FullScreenToggle } from "../FullScreenToggle";
export function getSharedPath(array) {
array = array.map((str) => str.replace(/\\/g, "/")); // Convert to Mac-style path
@@ -55,7 +56,7 @@ class NWBPreviewInstance extends LitElement {
const isOnline = navigator.onLine;
return isOnline
- ? new Neurosift({ url: getURLFromFilePath(this.file, this.project) })
+ ? new Neurosift({ url: getURLFromFilePath(this.file, this.project), fullscreen: false })
: until(
(async () => {
const htmlRep = await run("html", { nwbfile_path: this.file }, { swal: false });
@@ -71,11 +72,27 @@ customElements.get("nwb-preview-instance") || customElements.define("nwb-preview
export class NWBFilePreview extends LitElement {
static get styles() {
return css`
+ :host {
+ display: block;
+ width: 100%;
+ height: 100%;
+ background: white;
+ position: relative;
+ }
+
iframe {
width: 100%;
height: 100%;
border: 0;
}
+
+ #inspect {
+ display: flex;
+ flex-direction: column;
+ border-left: 1px solid gray;
+ box-shadow: -5px 0 5px -5px rgba(0, 0, 0, 0.5);
+ z-index: 1;
+ }
`;
}
@@ -105,58 +122,60 @@ export class NWBFilePreview extends LitElement {
const onlyFirstFile = fileArr.length <= 1;
- return html`
-
- ${(() => {
- if (onlyFirstFile) return new NWBPreviewInstance(fileArr[0].info, this.project);
- else {
- const _instances = fileArr.map(this.createInstance);
-
- const instances = _instances.reduce((acc, { subject, session, display }) => {
- if (!acc[`sub-${subject}`]) acc[`sub-${subject}`] = {};
- acc[`sub-${subject}`][`ses-${session}`] = display;
- return acc;
- }, {});
-
- return new InstanceManager({ instances });
- }
- })()}
-
- ${this.inspect
- ? html`
-
Inspector Report
- ${until(
- (async () => {
- const opts = {}; // NOTE: Currently options are handled on the Python end until exposed to the user
-
- const title = "Inspecting your file";
-
- const items = onlyFirstFile
- ? removeFilePaths(
- await run(
- "inspect_file",
- { nwbfile_path: fileArr[0].info.file, ...opts },
- { title }
- )
- ) // Inspect the first file
- : await (async () =>
- truncateFilePaths(
- await run("inspect_folder", { path, ...opts }, { title: title + "s" }),
- getSharedPath(fileArr.map((o) => o.info.file))
- ))();
-
- const list = new InspectorList({
- items: items,
- listStyles: { maxWidth: "350px" },
- });
- list.style.padding = "10px";
- return list;
- })(),
- html`Loading inspector report...`
- )}
- `
- : ""}
-
`;
+ return html` ${new FullScreenToggle({ target: this })}
+
+
+ ${(() => {
+ if (onlyFirstFile) return new NWBPreviewInstance(fileArr[0].info, this.project);
+ else {
+ const _instances = fileArr.map(this.createInstance);
+
+ const instances = _instances.reduce((acc, { subject, session, display }) => {
+ if (!acc[`sub-${subject}`]) acc[`sub-${subject}`] = {};
+ acc[`sub-${subject}`][`ses-${session}`] = display;
+ return acc;
+ }, {});
+
+ return new InstanceManager({ instances });
+ }
+ })()}
+
+ ${this.inspect
+ ? html`
+
Inspector Report
+ ${until(
+ (async () => {
+ const opts = {}; // NOTE: Currently options are handled on the Python end until exposed to the user
+
+ const title = "Inspecting your file";
+
+ const items = onlyFirstFile
+ ? removeFilePaths(
+ await run(
+ "inspect_file",
+ { nwbfile_path: fileArr[0].info.file, ...opts },
+ { title }
+ )
+ ) // Inspect the first file
+ : await (async () =>
+ truncateFilePaths(
+ await run("inspect_folder", { path, ...opts }, { title: title + "s" }),
+ getSharedPath(fileArr.map((o) => o.info.file))
+ ))();
+
+ const list = new InspectorList({
+ items: items,
+ listStyles: { minWidth: "300px", maxWidth: "350px" },
+ emptyMessage: "No issues found.",
+ });
+ list.style.padding = "10px";
+ return list;
+ })(),
+ html`Loading inspector report...`
+ )}
+ `
+ : ""}
+
`;
}
}
diff --git a/src/renderer/src/stories/preview/Neurosift.js b/src/renderer/src/stories/preview/Neurosift.js
index 622148da9..aaf626bb4 100644
--- a/src/renderer/src/stories/preview/Neurosift.js
+++ b/src/renderer/src/stories/preview/Neurosift.js
@@ -2,6 +2,7 @@ import { LitElement, css, html } from "lit";
import { baseUrl } from "../../globals";
import { Loader } from "../Loader";
+import { FullScreenToggle } from "../FullScreenToggle";
export function getURLFromFilePath(file, projectName) {
const regexp = new RegExp(`.+(${projectName}.+)`);
@@ -12,6 +13,7 @@ export class Neurosift extends LitElement {
static get styles() {
return css`
:host {
+ background: white;
width: 100%;
height: 100%;
display: grid;
@@ -21,7 +23,8 @@ export class Neurosift extends LitElement {
--loader-color: hsl(200, 80%, 50%);
}
- :host > * {
+ iframe,
+ .loader-container {
width: 100%;
height: 100%;
}
@@ -35,6 +38,19 @@ export class Neurosift extends LitElement {
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;
}
@@ -55,9 +71,10 @@ export class Neurosift extends LitElement {
};
}
- constructor({ url } = {}) {
+ constructor({ url, fullscreen = true } = {}) {
super();
this.url = url;
+ this.fullscreen = fullscreen;
}
render() {
@@ -65,11 +82,12 @@ export class Neurosift extends LitElement {
? html`
${new Loader({ message: `Loading Neurosift view...
${this.url}` })}
+ ${this.fullscreen ? new FullScreenToggle({ target: this }) : ""}
`
: ``;