diff --git a/src/components/DownloadTrajectoryMenu/index.tsx b/src/components/DownloadTrajectoryMenu/index.tsx
index 9908711a..1ff696a0 100644
--- a/src/components/DownloadTrajectoryMenu/index.tsx
+++ b/src/components/DownloadTrajectoryMenu/index.tsx
@@ -3,23 +3,21 @@ import { Button, Tooltip } from "antd";
import { ISimulariumFile } from "@aics/simularium-viewer/type-declarations";
import { DATA_BUCKET_URL, TOOLTIP_COLOR } from "../../constants";
-import {
- NetworkedSimFile,
- LocalSimFile,
- isNetworkSimFileInterface,
-} from "../../state/trajectory/types";
+import { NetworkedSimFile, LocalSimFile } from "../../state/trajectory/types";
import { Download } from "../Icons";
import styles from "./style.css";
interface DownloadTrajectoryMenuProps {
isBuffering: boolean;
+ isNetworkedFile: boolean;
simulariumFile: LocalSimFile | NetworkedSimFile;
}
const DownloadTrajectoryMenu = ({
isBuffering,
simulariumFile,
+ isNetworkedFile,
}: DownloadTrajectoryMenuProps): JSX.Element => {
const fileIsLoaded = () => !!simulariumFile.name;
@@ -27,10 +25,11 @@ const DownloadTrajectoryMenu = ({
if (!fileIsLoaded()) {
return "";
}
- if (isNetworkSimFileInterface(simulariumFile)) {
+ if (isNetworkedFile) {
return `${DATA_BUCKET_URL}/trajectory/${simulariumFile.name}`;
} else {
- const data: ISimulariumFile = simulariumFile.data;
+ const localFile = simulariumFile as LocalSimFile; // isNetworkedFile checks for this
+ const data: ISimulariumFile = localFile.data;
const blob = data.getAsBlob();
return URL.createObjectURL(blob);
}
diff --git a/src/components/ShareTrajectoryButton/index.tsx b/src/components/ShareTrajectoryButton/index.tsx
index e26038f1..021675ef 100644
--- a/src/components/ShareTrajectoryButton/index.tsx
+++ b/src/components/ShareTrajectoryButton/index.tsx
@@ -2,15 +2,12 @@ import React from "react";
import { Button, Tooltip } from "antd";
import { TOOLTIP_COLOR } from "../../constants";
-import {
- NetworkedSimFile,
- LocalSimFile,
- isLocalFileInterface,
-} from "../../state/trajectory/types";
+import { NetworkedSimFile, LocalSimFile } from "../../state/trajectory/types";
import { Share } from "../Icons";
import ShareTrajectoryModal from "../ShareTrajectoryModal";
import styles from "./style.css";
+import { isOnlineTrajectory } from "../../util/userUrlHandling";
interface ShareTrajectoryButtonProps {
simulariumFile: LocalSimFile | NetworkedSimFile;
@@ -21,7 +18,7 @@ const ShareTrajectoryButton = ({
}: ShareTrajectoryButtonProps): JSX.Element => {
const [isSharing, setIsSharing] = React.useState(false);
- const isLocalFile = isLocalFileInterface(simulariumFile);
+ const trajectoryIsSharable = isOnlineTrajectory(location.href);
const handleShare = () => {
setIsSharing(!isSharing);
@@ -42,7 +39,7 @@ const ShareTrajectoryButton = ({
{isSharing ? (
diff --git a/src/components/ShareTrajectoryModal/index.tsx b/src/components/ShareTrajectoryModal/index.tsx
index da38ad2e..e10c64d1 100644
--- a/src/components/ShareTrajectoryModal/index.tsx
+++ b/src/components/ShareTrajectoryModal/index.tsx
@@ -17,14 +17,14 @@ import styles from "./style.css";
import theme from "../theme/light-theme.css";
interface ShareTrajectoryModalProps {
- isLocalFile: boolean;
+ trajectoryIsSharable: boolean;
closeModal: () => void;
timeUnits: TimeUnits;
displayTimes: DisplayTimes;
}
const ShareTrajectoryModal = ({
- isLocalFile,
+ trajectoryIsSharable,
closeModal,
timeUnits,
displayTimes,
@@ -102,7 +102,7 @@ const ShareTrajectoryModal = ({
};
const modalOptions = {
- localFile: {
+ errorMessage: {
content: (
<>
{Warn} The current file is stored on your device.
@@ -134,7 +134,7 @@ const ShareTrajectoryModal = ({
),
},
- networkedFile: {
+ isSharable: {
content: (
<>
@@ -177,20 +177,20 @@ const ShareTrajectoryModal = ({
- {isLocalFile
- ? modalOptions.localFile.content
- : modalOptions.networkedFile.content}
+ {trajectoryIsSharable
+ ? modalOptions.isSharable.content
+ : modalOptions.errorMessage.content}
);
diff --git a/src/components/ViewerTitle/index.tsx b/src/components/ViewerTitle/index.tsx
index 9df3e7df..e2f370f6 100644
--- a/src/components/ViewerTitle/index.tsx
+++ b/src/components/ViewerTitle/index.tsx
@@ -7,6 +7,7 @@ import { VIEWER_PATHNAME } from "../../routes";
import TRAJECTORIES from "../../constants/networked-trajectories";
import styles from "./style.css";
+import { URL_PARAM_KEY_FILE_NAME } from "../../constants";
interface ViewerTitleProps {
simulariumFileName: string;
@@ -27,7 +28,10 @@ const ViewerTitle: React.FunctionComponent
= (
// networked-trajectories.ts to get its version info
// TODO: Eventually we should put all the contents of networked-trajectories.ts in the
// Simularium files themselves
- const trajectoryId = location.search.replace("?trajFileName=", "");
+ const trajectoryId = location.search.replace(
+ `?${URL_PARAM_KEY_FILE_NAME}=`,
+ ""
+ );
const currentTrajectory = TRAJECTORIES.find(
(trajectory) => trajectory.id === trajectoryId
);
diff --git a/src/containers/AppHeader/index.tsx b/src/containers/AppHeader/index.tsx
index 85f7a220..57aef185 100644
--- a/src/containers/AppHeader/index.tsx
+++ b/src/containers/AppHeader/index.tsx
@@ -31,6 +31,7 @@ import DownloadTrajectoryMenu from "../../components/DownloadTrajectoryMenu";
interface AppHeaderProps {
simulariumFile: LocalSimFile | NetworkedSimFile;
isBuffering: boolean;
+ isNetworkedFile: boolean;
clearSimulariumFile: ActionCreator;
changeToLocalSimulariumFile: ActionCreator;
changeToNetworkedFile: ActionCreator;
@@ -48,6 +49,7 @@ class AppHeader extends React.Component {
setViewerStatus,
clearSimulariumFile,
setError,
+ isNetworkedFile,
} = this.props;
let lastModified = 0;
let displayName = "";
@@ -89,6 +91,7 @@ class AppHeader extends React.Component {
@@ -101,6 +104,8 @@ function mapStateToProps(state: State) {
simulariumFile:
trajectoryStateBranch.selectors.getSimulariumFile(state),
isBuffering: viewerStateBranch.selectors.getIsBuffering(state),
+ isNetworkedFile:
+ trajectoryStateBranch.selectors.getIsNetworkedFile(state),
};
}
diff --git a/src/state/trajectory/types.ts b/src/state/trajectory/types.ts
index d05b5850..f0238d05 100644
--- a/src/state/trajectory/types.ts
+++ b/src/state/trajectory/types.ts
@@ -60,6 +60,7 @@ export interface NetworkedSimFile {
}
export const isLocalFileInterface = (file: any): file is LocalSimFile =>
!!file.lastModified;
+
export const isNetworkSimFileInterface = (
file: any
): file is NetworkedSimFile => !!file.title;
diff --git a/src/util/test/index.test.ts b/src/util/test/index.test.ts
index 0352c491..cdb7040b 100644
--- a/src/util/test/index.test.ts
+++ b/src/util/test/index.test.ts
@@ -1,6 +1,10 @@
import * as React from "react";
-import { USER_TRAJ_REDIRECTS } from "../../constants";
+import {
+ URL_PARAM_KEY_FILE_NAME,
+ URL_PARAM_KEY_USER_URL,
+ USER_TRAJ_REDIRECTS,
+} from "../../constants";
import {
bindAll,
convertToSentenceCase,
@@ -16,6 +20,7 @@ import {
getRedirectUrl,
getUserTrajectoryUrl,
isGoogleDriveUrl,
+ isOnlineTrajectory,
urlCheck,
} from "../userUrlHandling";
@@ -373,4 +378,21 @@ describe("User Url handling", () => {
expect(result).toEqual("dl.dropboxusercontent.com/path");
});
});
+ describe("isOnlineTrajectory", () => {
+ it("it returns true if the trajectory is hosted online", () => {
+ const cloudTrajectoryUrl = `simularium?${URL_PARAM_KEY_USER_URL}=url`;
+ const result = isOnlineTrajectory(cloudTrajectoryUrl);
+ expect(result).toBeTruthy;
+ });
+ it("true if the trajectory is one of our networked models", () => {
+ const networkedUrl = `simularium?${URL_PARAM_KEY_FILE_NAME}=url`;
+ const result = isOnlineTrajectory(networkedUrl);
+ expect(result).toBeTruthy;
+ });
+ it("it returns false if no relevant url params are present", () => {
+ const url = `simularium?other_url_param=value`;
+ const result = isOnlineTrajectory(url);
+ expect(result).toBeFalsy;
+ });
+ });
});
diff --git a/src/util/userUrlHandling.ts b/src/util/userUrlHandling.ts
index ea827b83..26a85e8f 100644
--- a/src/util/userUrlHandling.ts
+++ b/src/util/userUrlHandling.ts
@@ -1,8 +1,13 @@
import { isString } from "lodash";
-import { USER_TRAJ_REDIRECTS } from "../constants";
+import {
+ URL_PARAM_KEY_FILE_NAME,
+ URL_PARAM_KEY_USER_URL,
+ USER_TRAJ_REDIRECTS,
+} from "../constants";
-const googleDriveUrlRegEx = /(?:drive.google\.com\/file\/d\/)(.*)(?=\/)|(?:drive.google\.com\/file\/d\/)(.*)/g;
+const googleDriveUrlRegEx =
+ /(?:drive.google\.com\/file\/d\/)(.*)(?=\/)|(?:drive.google\.com\/file\/d\/)(.*)/g;
const googleDriveUrlExcludingIdRegEx = /(drive.google\.com\/file\/d\/)(?=.*)/g;
export const urlCheck = (urlToCheck: any): string => {
@@ -14,7 +19,8 @@ export const urlCheck = (urlToCheck: any): string => {
* I had to modify the original to allow s3 buckets which have multiple `.letters-letters.` in them
* and I made the http(s) required
*/
- const regEx = /(https?:\/\/)([\w\-]){0,200}(\.[a-zA-Z][^\-])([\/\w]*)*\/?\??([^\n\r]*)?([^\n\r]*)/g;
+ const regEx =
+ /(https?:\/\/)([\w\-]){0,200}(\.[a-zA-Z][^\-])([\/\w]*)*\/?\??([^\n\r]*)?([^\n\r]*)/g;
if (regEx.test(urlToCheck)) {
return urlToCheck;
}
@@ -68,18 +74,14 @@ export const getFileIdFromUrl = (
export const getRedirectUrl = (url: string, fileName: string | undefined) => {
if (url && fileName && USER_TRAJ_REDIRECTS.includes(url)) {
// ex) simularium.allencell.org/viewer?trajFileName=endocytosis.simularium
- return `${location.origin}${
- location.pathname
- }?trajFileName=${fileName}`;
+ return `${location.origin}${location.pathname}?${URL_PARAM_KEY_FILE_NAME}=${fileName}`;
} else {
return "";
}
};
export const getGoogleApiUrl = (id: string) => {
- return `https://www.googleapis.com/drive/v2/files/${id}?alt=media&key=${
- process.env.GOOGLE_API_KEY
- }`;
+ return `https://www.googleapis.com/drive/v2/files/${id}?alt=media&key=${process.env.GOOGLE_API_KEY}`;
};
export const getUserTrajectoryUrl = (url: string, fileId?: string) => {
@@ -89,3 +91,10 @@ export const getUserTrajectoryUrl = (url: string, fileId?: string) => {
return url.replace("dropbox.com", "dl.dropboxusercontent.com");
}
};
+
+export const isOnlineTrajectory = (url: string) => {
+ return (
+ url.includes(URL_PARAM_KEY_USER_URL) ||
+ url.includes(URL_PARAM_KEY_FILE_NAME)
+ );
+};