Skip to content

Commit 5553167

Browse files
authored
Merge pull request #467 from AllenInstitute/feature/open-png
Add 'Browser' as an open with option + fix some path bugs
2 parents caafd7d + e25f8eb commit 5553167

File tree

7 files changed

+56
-91
lines changed

7 files changed

+56
-91
lines changed

packages/core/components/FileDetails/FileAnnotationList.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export default function FileAnnotationList(props: FileAnnotationListProps) {
8080

8181
if (annotation.name === AnnotationName.FILE_PATH) {
8282
// Display the full http://... URL
83-
annotationValue = fileDetails.cloudPath;
83+
annotationValue = fileDetails.path;
8484
}
8585

8686
if (annotationValue === Annotation.MISSING_VALUE) {

packages/core/components/FileDetails/index.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,7 @@ export default function FileDetails(props: Props) {
9999
if (fileDetails.size && fileDetails.size > 0) {
100100
setCalculatedSize(fileDetails.size);
101101
} else {
102-
const { hostname, key } = fileDownloadService.parseS3Url(
103-
fileDetails.downloadPath
104-
);
102+
const { hostname, key } = fileDownloadService.parseS3Url(fileDetails.path);
105103
fileDownloadService
106104
.calculateS3DirectorySize(hostname, key)
107105
.then(setCalculatedSize);
@@ -136,12 +134,14 @@ export default function FileDetails(props: Props) {
136134
id: fileDetails.uid,
137135
name: fileDetails.name,
138136
size: fileDetails.size,
139-
path: fileDetails.downloadPath,
137+
path: fileDownloadService.isFileSystemAccessible
138+
? fileDetails.localPath || fileDetails.path
139+
: fileDetails.path,
140140
},
141141
])
142142
);
143143
}, 1000); // 1s, in ms (arbitrary)
144-
}, [dispatch, fileDetails]);
144+
}, [dispatch, fileDetails, fileDownloadService.isFileSystemAccessible]);
145145

146146
return (
147147
<div

packages/core/entity/FileDetail/index.ts

+9-50
Original file line numberDiff line numberDiff line change
@@ -156,62 +156,20 @@ export default class FileDetail {
156156
return path as string;
157157
}
158158

159-
public get cloudPath(): string {
160-
//// REMOVE THIS (BACKWARDS COMPAT)
161-
if (this.path.startsWith("/allen")) {
162-
return this.convertAicsDrivePathToAicsS3Path(this.path);
163-
}
164-
////
165-
166-
// AICS FMS files' paths are cloud paths
167-
return this.path;
168-
}
169-
170159
public get localPath(): string | null {
171-
//// REMOVE THIS (BACKWARDS COMPAT)
172-
if (this.path.startsWith("/allen")) {
173-
return this.path;
174-
}
175-
////
176-
177-
if (this.getAnnotation("Cache Eviction Date")) {
178-
return this.getLocalPath();
179-
}
180-
return null;
181-
}
182-
183-
public getLocalPath(): string | null {
184-
const localPrefix = NAS_HOST_PREFIXES[this.env];
185160
const cloudPrefix = `${AICS_FMS_S3_URL_PREFIX}${AICS_FMS_S3_BUCKETS[this.env]}`;
186-
187-
if (this.path.startsWith(cloudPrefix)) {
161+
if (this.getAnnotation("Cache Eviction Date") && this.path.startsWith(cloudPrefix)) {
162+
const localPrefix = NAS_HOST_PREFIXES[this.env];
188163
const relativePath = this.path.replace(`${cloudPrefix}`, "");
189164
return `${localPrefix}${relativePath}`;
190165
}
191166

192167
return null;
193168
}
194169

195-
public get downloadPath(): string {
196-
//// REMOVE THIS (BACKWARDS COMPAT)
197-
if (this.path.startsWith("/allen")) {
198-
return `http://aics.corp.alleninstitute.org/labkey/fmsfiles/image${this.path}`;
199-
}
200-
////
201-
202-
const localPath = this.getLocalPath();
203-
// For AICS files that are available on the Vast, users can use the cloud path, but the
204-
// download will be faster and not incur egress fees if we download via the local network.
205-
if (localPath && localPath.startsWith("/allen") && this.env === Environment.PRODUCTION) {
206-
return `http://aics.corp.alleninstitute.org/labkey/fmsfiles/image${localPath}`;
207-
}
208-
// Otherwise just return path (cloud probably)
209-
return this.path;
210-
}
211-
212170
public get downloadInProgress(): boolean {
213171
const shouldBeInLocal = this.getFirstAnnotationValue(AnnotationName.SHOULD_BE_IN_LOCAL);
214-
return Boolean(shouldBeInLocal) && !this.getLocalPath();
172+
return Boolean(shouldBeInLocal) && !this.localPath;
215173
}
216174

217175
public get size(): number | undefined {
@@ -256,14 +214,15 @@ export default class FileDetail {
256214

257215
// If no thumbnail present try to render the file itself as the thumbnail
258216
if (!this.thumbnail) {
217+
if (this.path.endsWith(".zarr")) {
218+
return renderZarrThumbnailURL(this.path);
219+
}
220+
259221
const isFileRenderableImage = RENDERABLE_IMAGE_FORMATS.some((format) =>
260-
this.name.toLowerCase().endsWith(format)
222+
this.path.toLowerCase().endsWith(format)
261223
);
262224
if (isFileRenderableImage) {
263-
return this.downloadPath;
264-
}
265-
if (this.path.includes(".zarr")) {
266-
return await renderZarrThumbnailURL(this.downloadPath);
225+
return this.path;
267226
}
268227
}
269228

packages/core/entity/FileDetail/test/FileDetail.test.ts

+3-28
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,7 @@ import FileDetail from "..";
44
import { Environment } from "../../../constants";
55

66
describe("FileDetail", () => {
7-
describe("file path representation", () => {
8-
it("creates downloadPath from /allen path", () => {
9-
// Arrange
10-
const file_name = "MyFile.txt";
11-
const file_id = "c32e3eed66e4416d9532d369ffe1636f";
12-
13-
// Act
14-
const fileDetail = new FileDetail(
15-
{
16-
file_path: `production.files.allencell.org/${file_name}`,
17-
file_name: file_name,
18-
file_id: file_id,
19-
annotations: [{ name: "Cache Eviction Date", values: ["SOME DATE"] }],
20-
},
21-
Environment.PRODUCTION
22-
);
23-
24-
// Assert
25-
expect(fileDetail.downloadPath).to.equal(
26-
// The downloadPath is HTTP, but will get redirected to HTTPS
27-
`http://aics.corp.alleninstitute.org/labkey/fmsfiles/image/allen/programs/allencell/data/proj0/${file_name}`
28-
);
29-
});
30-
});
31-
32-
describe("getLocalPath", () => {
7+
describe("localPath", () => {
338
it("creates localPath correctly for production environment", () => {
349
// Arrange
3510
const file_name = "ProdFile.czi";
@@ -48,7 +23,7 @@ describe("FileDetail", () => {
4823
);
4924

5025
// Assert
51-
expect(fileDetail.getLocalPath()).to.equal(
26+
expect(fileDetail.localPath).to.equal(
5227
`/allen/programs/allencell/data/proj0/${file_name}`
5328
);
5429
});
@@ -71,7 +46,7 @@ describe("FileDetail", () => {
7146
);
7247

7348
// Assert
74-
expect(fileDetail.getLocalPath()).to.equal(
49+
expect(fileDetail.localPath).to.equal(
7550
`/allen/aics/software/apps/staging/fss/data/${file_name}`
7651
);
7752
});

packages/core/hooks/useOpenWithMenuItems/index.tsx

+33-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import styles from "./useOpenWithMenuItems.module.css";
1111

1212
enum AppKeys {
1313
AGAVE = "agave",
14+
BROWSER = "browser",
1415
NEUROGLANCER = "neuroglancer",
1516
SIMULARIUM = "simularium",
1617
VOLE = "vole",
@@ -19,6 +20,7 @@ enum AppKeys {
1920

2021
interface Apps {
2122
[AppKeys.AGAVE]: IContextualMenuItem;
23+
[AppKeys.BROWSER]: IContextualMenuItem;
2224
[AppKeys.NEUROGLANCER]: IContextualMenuItem;
2325
[AppKeys.SIMULARIUM]: IContextualMenuItem;
2426
[AppKeys.VOLE]: IContextualMenuItem;
@@ -72,11 +74,27 @@ const APPS = (fileDetails?: FileDetail): Apps => ({
7274
);
7375
},
7476
} as IContextualMenuItem,
77+
[AppKeys.BROWSER]: {
78+
key: AppKeys.BROWSER,
79+
text: "Browser",
80+
title: `Open files in the current browser in a new tab`,
81+
href: fileDetails?.path,
82+
disabled: !fileDetails?.path,
83+
target: "_blank",
84+
onRenderContent(props, defaultRenders) {
85+
return (
86+
<>
87+
{defaultRenders.renderItemName(props)}
88+
<span className={styles.secondaryText}>Web</span>
89+
</>
90+
);
91+
},
92+
} as IContextualMenuItem,
7593
[AppKeys.NEUROGLANCER]: {
7694
key: AppKeys.NEUROGLANCER,
7795
text: "Neuroglancer",
7896
title: `Open files with Neuroglancer`,
79-
href: `https://neuroglancer-demo.appspot.com/#!{%22layers%22:[{%22source%22:%22zarr://${fileDetails?.cloudPath}%22,%22name%22:%22${fileDetails?.name}%22}]}`,
97+
href: `https://neuroglancer-demo.appspot.com/#!{%22layers%22:[{%22source%22:%22zarr://${fileDetails?.path}%22,%22name%22:%22${fileDetails?.name}%22}]}`,
8098
disabled: !fileDetails?.path,
8199
target: "_blank",
82100
onRenderContent(props, defaultRenders) {
@@ -92,7 +110,7 @@ const APPS = (fileDetails?: FileDetail): Apps => ({
92110
key: AppKeys.SIMULARIUM,
93111
text: "Simularium",
94112
title: `Open files with Simularium`,
95-
href: `https://simularium.allencell.org/viewer?trajUrl=${fileDetails?.cloudPath}`,
113+
href: `https://simularium.allencell.org/viewer?trajUrl=${fileDetails?.path}`,
96114
disabled: !fileDetails?.path,
97115
target: "_blank",
98116
onRenderContent(props, defaultRenders) {
@@ -108,7 +126,7 @@ const APPS = (fileDetails?: FileDetail): Apps => ({
108126
key: AppKeys.VOLE,
109127
text: "Vol-E",
110128
title: `Open files with Vol-E`,
111-
href: `https://volumeviewer.allencell.org/viewer?url=${fileDetails?.cloudPath}/`,
129+
href: `https://volumeviewer.allencell.org/viewer?url=${fileDetails?.path}/`,
112130
disabled: !fileDetails?.path,
113131
target: "_blank",
114132
onRenderContent(props, defaultRenders) {
@@ -124,7 +142,7 @@ const APPS = (fileDetails?: FileDetail): Apps => ({
124142
key: AppKeys.VOLVIEW,
125143
text: "VolView",
126144
title: `Open files with VolView`,
127-
href: `https://volview.kitware.app/?urls=[${fileDetails?.cloudPath}]`,
145+
href: `https://volview.kitware.app/?urls=[${fileDetails?.path}]`,
128146
disabled: !fileDetails?.path,
129147
target: "_blank",
130148
onRenderContent(props, defaultRenders) {
@@ -149,6 +167,17 @@ function getSupportedApps(fileDetails?: FileDetail): IContextualMenuItem[] {
149167
const fileExt = fileDetails.path.slice(fileDetails.path.lastIndexOf(".") + 1).toLowerCase();
150168
const apps = APPS(fileDetails);
151169
switch (fileExt) {
170+
case "bmp":
171+
case "html":
172+
case "gif":
173+
case "jpg":
174+
case "jpeg":
175+
case "pdf":
176+
case "png":
177+
case "svg":
178+
case "txt":
179+
case "xml":
180+
return [apps.browser];
152181
case "simularium":
153182
return [apps.simularium];
154183
case "dcm":

packages/core/state/interaction/logics.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,9 @@ const downloadFilesLogic = createLogic({
218218
id: file.uid,
219219
name: file.name,
220220
size: file.size,
221-
path: file.downloadPath,
221+
path: fileDownloadService.isFileSystemAccessible
222+
? file.localPath || file.path
223+
: file.path,
222224
}));
223225
}
224226

packages/core/state/interaction/test/logics.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1234,9 +1234,9 @@ describe("Interaction logics", () => {
12341234
});
12351235

12361236
describe("openWith", () => {
1237-
const files: { file_path: string }[] = [];
1237+
const files: { file_path: string; annotations: any[] }[] = [];
12381238
for (let i = 0; i <= 100; i++) {
1239-
files.push({ file_path: `/allen/file_${i}.ext` });
1239+
files.push({ file_path: `/allen/file_${i}.ext`, annotations: [] });
12401240
}
12411241
const fileExplorerServiceBaseUrl = FESBaseUrl.TEST;
12421242
const responseStub = {

0 commit comments

Comments
 (0)