diff --git a/packages/core/App.tsx b/packages/core/App.tsx index 325f5605b..197ce2f42 100644 --- a/packages/core/App.tsx +++ b/packages/core/App.tsx @@ -14,7 +14,7 @@ import GlobalActionButtonRow from "./components/GlobalActionButtonRow"; import StatusMessage from "./components/StatusMessage"; import TutorialTooltip from "./components/TutorialTooltip"; import QuerySidebar from "./components/QuerySidebar"; -import { AicsLoadBalancerBaseUrl, FileExplorerServiceBaseUrl } from "./constants"; +import { Environment } from "./constants"; import { interaction, selection } from "./state"; import useLayoutMeasurements from "./hooks/useLayoutMeasurements"; @@ -39,15 +39,11 @@ interface AppProps { // Localhost: "https://localhost:9081" // Stage: "http://stg-aics-api.corp.alleninstitute.org" // From the web (behind load balancer): "/" - aicsLoadBalancerBaseUrl?: string; - fileExplorerServiceBaseUrl?: string; + environment?: Environment; } export default function App(props: AppProps) { - const { - aicsLoadBalancerBaseUrl = AicsLoadBalancerBaseUrl.PRODUCTION, - fileExplorerServiceBaseUrl = FileExplorerServiceBaseUrl.PRODUCTION, - } = props; + const { environment = Environment.PRODUCTION } = props; const dispatch = useDispatch(); const hasQuerySelected = useSelector(selection.selectors.hasQuerySelected); @@ -86,11 +82,10 @@ export default function App(props: AppProps) { React.useEffect(() => { dispatch( interaction.actions.initializeApp({ - aicsLoadBalancerBaseUrl, - fileExplorerServiceBaseUrl, + environment, }) ); - }, [dispatch, aicsLoadBalancerBaseUrl, fileExplorerServiceBaseUrl]); + }, [dispatch, environment]); // Respond to screen size changes React.useEffect(() => { diff --git a/packages/core/components/AnnotationFilterForm/test/AnnotationFilterForm.test.tsx b/packages/core/components/AnnotationFilterForm/test/AnnotationFilterForm.test.tsx index 24ecae207..705b24ee7 100644 --- a/packages/core/components/AnnotationFilterForm/test/AnnotationFilterForm.test.tsx +++ b/packages/core/components/AnnotationFilterForm/test/AnnotationFilterForm.test.tsx @@ -10,6 +10,7 @@ import Annotation from "../../../entity/Annotation"; import FileFilter from "../../../entity/FileFilter"; import { initialState, reducer, reduxLogics, interaction, selection } from "../../../state"; import HttpAnnotationService from "../../../services/AnnotationService/HttpAnnotationService"; +import { FESBaseUrl } from "../../../constants"; describe("", () => { const LISTROW_TESTID_PREFIX = "default-button-"; @@ -31,14 +32,14 @@ describe("", () => { it("shows all values as unchecked at first", async () => { // arrange const responseStub = { - when: `test/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, + when: `${FESBaseUrl.TEST}/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, respondWith: { data: { data: ["a", "b", "c", "d"] }, }, }; const mockHttpClient = createMockHttpClient(responseStub); const annotationService = new HttpAnnotationService({ - baseUrl: "test", + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, httpClient: mockHttpClient, }); sandbox.stub(interaction.selectors, "getAnnotationService").returns(annotationService); @@ -68,14 +69,14 @@ describe("", () => { it("deselects and selects a value", async () => { // arrange const responseStub = { - when: `test/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, + when: `${FESBaseUrl.TEST}/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, respondWith: { data: { data: ["a", "b", "c", "d"] }, }, }; const mockHttpClient = createMockHttpClient(responseStub); const annotationService = new HttpAnnotationService({ - baseUrl: "test", + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, httpClient: mockHttpClient, }); sandbox.stub(interaction.selectors, "getAnnotationService").returns(annotationService); @@ -124,14 +125,14 @@ describe("", () => { it("naturally sorts values", async () => { // arrange const responseStub = { - when: `test/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, + when: `${FESBaseUrl.TEST}/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, respondWith: { data: { data: ["AICS-24", "AICS-0", "aics-32", "aICs-2"] }, }, }; const mockHttpClient = createMockHttpClient(responseStub); const annotationService = new HttpAnnotationService({ - baseUrl: "test", + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, httpClient: mockHttpClient, }); sandbox.stub(interaction.selectors, "getAnnotationService").returns(annotationService); @@ -172,14 +173,14 @@ describe("", () => { }); const responseStub = { - when: `test/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, + when: `${FESBaseUrl.TEST}/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, respondWith: { data: { data: [true, false] }, }, }; const mockHttpClient = createMockHttpClient(responseStub); const annotationService = new HttpAnnotationService({ - baseUrl: "test", + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, httpClient: mockHttpClient, }); @@ -279,14 +280,14 @@ describe("", () => { it("naturally sorts values", async () => { // arrange const responseStub = { - when: `test/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, + when: `${FESBaseUrl.TEST}/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, respondWith: { data: { data: [5, 8, 6.3, -12, 10000000000, 0] }, }, }; const mockHttpClient = createMockHttpClient(responseStub); const annotationService = new HttpAnnotationService({ - baseUrl: "test", + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, httpClient: mockHttpClient, }); sandbox.stub(interaction.selectors, "getAnnotationService").returns(annotationService); @@ -334,14 +335,14 @@ describe("", () => { it("naturally sorts values", async () => { // arrange const responseStub = { - when: `test/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, + when: `${FESBaseUrl.TEST}/file-explorer-service/1.0/annotations/${fooAnnotation.name}/values`, respondWith: { data: { data: [446582220, 125, 10845000, 86400000] }, }, }; const mockHttpClient = createMockHttpClient(responseStub); const annotationService = new HttpAnnotationService({ - baseUrl: "test", + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, httpClient: mockHttpClient, }); sandbox.stub(interaction.selectors, "getAnnotationService").returns(annotationService); diff --git a/packages/core/components/DirectoryTree/test/DirectoryTree.test.tsx b/packages/core/components/DirectoryTree/test/DirectoryTree.test.tsx index b8bb860ee..7e32f6a46 100644 --- a/packages/core/components/DirectoryTree/test/DirectoryTree.test.tsx +++ b/packages/core/components/DirectoryTree/test/DirectoryTree.test.tsx @@ -19,7 +19,7 @@ import { import { Provider } from "react-redux"; import { createSandbox } from "sinon"; -import { TOP_LEVEL_FILE_ANNOTATIONS } from "../../../constants"; +import { FESBaseUrl, TOP_LEVEL_FILE_ANNOTATIONS } from "../../../constants"; import Annotation from "../../../entity/Annotation"; import AnnotationName from "../../../entity/Annotation/AnnotationName"; import { FmsFileAnnotation } from "../../../services/FileService"; @@ -53,14 +53,10 @@ describe("", () => { type: "Text", }); - const baseUrl = "http://test-aics.corp.alleninstitute.org"; const baseDisplayAnnotations = TOP_LEVEL_FILE_ANNOTATIONS.filter( (a) => a.name === AnnotationName.FILE_NAME ); const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: baseUrl, - }, selection: { annotationHierarchy: [fooAnnotation.name, barAnnotation.name], displayAnnotations: [...baseDisplayAnnotations, fooAnnotation, barAnnotation], @@ -188,9 +184,13 @@ describe("", () => { }, ]; const mockHttpClient = createMockHttpClient(responseStubs); - const annotationService = new HttpAnnotationService({ baseUrl, httpClient: mockHttpClient }); + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: fileExplorerServiceBaseUrl, + httpClient: mockHttpClient, + }); const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl: fileExplorerServiceBaseUrl, httpClient: mockHttpClient, downloadService: new FileDownloadServiceNoop(), }); @@ -353,9 +353,6 @@ describe("", () => { it("only includes one filter value per annotation for an annotation within the hierarchy", async () => { const oneAnnotationDeepState = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: baseUrl, - }, selection: { annotationHierarchy: [fooAnnotation.name], displayAnnotations: [...baseDisplayAnnotations, fooAnnotation, barAnnotation], diff --git a/packages/core/components/Modal/MetadataManifest/test/MetadataManifest.test.tsx b/packages/core/components/Modal/MetadataManifest/test/MetadataManifest.test.tsx index fdf28fa6d..c0fed64a2 100644 --- a/packages/core/components/Modal/MetadataManifest/test/MetadataManifest.test.tsx +++ b/packages/core/components/Modal/MetadataManifest/test/MetadataManifest.test.tsx @@ -12,6 +12,7 @@ import { Provider } from "react-redux"; import { createSandbox } from "sinon"; import Modal, { ModalType } from "../.."; +import { FESBaseUrl } from "../../../../constants"; import Annotation from "../../../../entity/Annotation"; import FileFilter from "../../../../entity/FileFilter"; import { initialState, interaction, reduxLogics } from "../../../../state"; @@ -19,10 +20,11 @@ import HttpFileService from "../../../../services/FileService/HttpFileService"; import FileDownloadServiceNoop from "../../../../services/FileDownloadService/FileDownloadServiceNoop"; describe("", () => { - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; + const environment = "TEST"; const visibleDialogState = mergeState(initialState, { interaction: { - fileExplorerServiceBaseUrl: baseUrl, + environment: environment, visibleModal: ModalType.MetadataManifest, }, }); @@ -35,7 +37,7 @@ describe("", () => { }; const mockHttpClient = createMockHttpClient(responseStub); const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient: mockHttpClient, downloadService: new FileDownloadServiceNoop(), }); diff --git a/packages/core/components/Modal/SmallScreenWarning/test/SmallScreenWarning.test.tsx b/packages/core/components/Modal/SmallScreenWarning/test/SmallScreenWarning.test.tsx index 91b76a105..ce446e63d 100644 --- a/packages/core/components/Modal/SmallScreenWarning/test/SmallScreenWarning.test.tsx +++ b/packages/core/components/Modal/SmallScreenWarning/test/SmallScreenWarning.test.tsx @@ -8,10 +8,8 @@ import Modal, { ModalType } from "../.."; import { initialState, interaction, reduxLogics } from "../../../../state"; describe("", () => { - const baseUrl = "test"; const visibleDialogState = mergeState(initialState, { interaction: { - fileExplorerServiceBaseUrl: baseUrl, visibleModal: ModalType.SmallScreenWarning, }, }); diff --git a/packages/core/constants/index.ts b/packages/core/constants/index.ts index f3dbbcc86..929b628d4 100644 --- a/packages/core/constants/index.ts +++ b/packages/core/constants/index.ts @@ -5,16 +5,11 @@ import { AnnotationType } from "../entity/AnnotationFormatter"; export const APP_ID = "fms-file-explorer-core"; // Refer to packages/fms-file-explorer-electron/src/main/menu -export enum FileExplorerServiceBaseUrl { - LOCALHOST = "http://localhost:9081", - STAGING = "https://staging.int.allencell.org", - PRODUCTION = "https://production.int.allencell.org", -} - -export enum AicsLoadBalancerBaseUrl { - LOCALHOST = "http://localhost:8080", - STAGING = "http://stg-aics.corp.alleninstitute.org", - PRODUCTION = "http://aics.corp.alleninstitute.org", +export enum Environment { + LOCALHOST = "LOCALHOST", + STAGING = "STAGING", + PRODUCTION = "PRODUCTION", + TEST = "TEST", } export const TOP_LEVEL_FILE_ANNOTATIONS = [ @@ -65,3 +60,24 @@ export const THUMBNAIL_SIZE_TO_NUM_COLUMNS = { }; export const AICS_FMS_DATA_SOURCE_NAME = "AICS FMS"; + +export enum FESBaseUrl { + LOCALHOST = "http://localhost:9081", + STAGING = "https://staging.int.allencell.org", + PRODUCTION = "https://production.int.allencell.org", + TEST = "http://test.int.allencell.org", +} + +export enum MMSBaseUrl { + LOCALHOST = "http://localhost:9060", + STAGING = "http://stg-aics-api", + PRODUCTION = "http://prod-aics-api", + TEST = "http://test-aics-api", +} + +export enum LoadBalancerBaseUrl { + LOCALHOST = "http://localhost:8080", + STAGING = "http://stg-aics.corp.alleninstitute.org", + PRODUCTION = "http://aics.corp.alleninstitute.org", + TEST = "http://test-aics.corp.alleninstitute.org", +} diff --git a/packages/core/entity/FileSelection/test/FileSelection.test.ts b/packages/core/entity/FileSelection/test/FileSelection.test.ts index 5a12775a8..ba369db9e 100644 --- a/packages/core/entity/FileSelection/test/FileSelection.test.ts +++ b/packages/core/entity/FileSelection/test/FileSelection.test.ts @@ -6,6 +6,7 @@ import FileSet from "../../FileSet"; import NumericRange from "../../NumericRange"; import FileSelection, { FocusDirective } from ".."; +import { FESBaseUrl } from "../../../constants"; import FileDetail from "../../FileDetail"; import FileFilter from "../../FileFilter"; import FuzzyFilter from "../../FileFilter/FuzzyFilter"; @@ -344,7 +345,7 @@ describe("FileSelection", () => { describe("fetchAllDetails", () => { it("returns file details for each selected item", async () => { // Arrange - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; const queryResult = []; for (let i = 0; i < 31; i++) { queryResult.push(i); @@ -354,13 +355,15 @@ describe("FileSelection", () => { .slice(1, 31) .map((detail) => new FileDetail(detail as any)); const httpClient = createMockHttpClient({ - when: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=${0}&limit=${31}`, + when: `${fileExplorerServiceBaseUrl}/${ + HttpFileService.BASE_FILES_URL + }?from=${0}&limit=${31}`, respondWith: { data: { data: queryResult }, }, }); const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient, downloadService: new FileDownloadServiceNoop(), }); diff --git a/packages/core/entity/FileSet/index.ts b/packages/core/entity/FileSet/index.ts index b68fe0b6b..ae744ecf7 100644 --- a/packages/core/entity/FileSet/index.ts +++ b/packages/core/entity/FileSet/index.ts @@ -84,7 +84,7 @@ export default class FileSet { * by using this as the component's `key` attribute. */ public get hash() { - return `${this.toQueryString()}:${this.fileService.baseUrl}`; + return `${this.toQueryString()}:${this.fileService.fileExplorerServiceBaseUrl}`; } public async fetchTotalCount() { @@ -210,7 +210,7 @@ export default class FileSet { public toJSON() { return { queryString: this.toQueryString(), - baseUrl: this.fileService.baseUrl, + fileExplorerServiceBaseUrl: this.fileService.fileExplorerServiceBaseUrl, }; } diff --git a/packages/core/entity/FileSet/test/FileSet.test.ts b/packages/core/entity/FileSet/test/FileSet.test.ts index 94851ae0d..702a73a38 100644 --- a/packages/core/entity/FileSet/test/FileSet.test.ts +++ b/packages/core/entity/FileSet/test/FileSet.test.ts @@ -3,6 +3,7 @@ import { expect } from "chai"; import { createSandbox } from "sinon"; import FileSet from "../"; +import { FESBaseUrl } from "../../../constants"; import FileFilter from "../../FileFilter"; import FileSort, { SortOrder } from "../../FileSort"; import { makeFileDetailMock } from "../../FileDetail/mocks"; @@ -148,40 +149,40 @@ describe("FileSet", () => { }); it("turns indicies for requested data into a properly formed pagination query", async () => { - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; const spec = [ { - expectedUrl: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=1&limit=28`, + expectedUrl: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=1&limit=28`, start: 35, end: 55, }, { - expectedUrl: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=11&limit=23`, + expectedUrl: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=11&limit=23`, start: 256, end: 274, }, { - expectedUrl: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=6`, + expectedUrl: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=6`, start: 0, end: 5, }, { - expectedUrl: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=1&limit=11`, + expectedUrl: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=1&limit=11`, start: 14, end: 21, }, { - expectedUrl: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=6`, + expectedUrl: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=6`, start: 2, end: 5, }, { - expectedUrl: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=3&limit=4`, + expectedUrl: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=3&limit=4`, start: 12, end: 15, }, { - expectedUrl: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=301`, + expectedUrl: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=301`, start: 2, end: 300, }, @@ -203,7 +204,7 @@ describe("FileSet", () => { const fileSet = new FileSet({ fileService: new HttpFileService({ httpClient, - baseUrl, + fileExplorerServiceBaseUrl, downloadService: new FileDownloadServiceNoop(), }), }); diff --git a/packages/core/hooks/useOpenWithMenuItems/index.tsx b/packages/core/hooks/useOpenWithMenuItems/index.tsx index 32937c686..7090f1b22 100644 --- a/packages/core/hooks/useOpenWithMenuItems/index.tsx +++ b/packages/core/hooks/useOpenWithMenuItems/index.tsx @@ -177,9 +177,9 @@ export default (fileDetails?: FileDetail, filters?: FileFilter[]): IContextualMe const annotationNameToAnnotationMap = useSelector( metadata.selectors.getAnnotationNameToAnnotationMap ); - const aicsLoadBalancerBaseUrl = useSelector(interaction.selectors.getAicsLoadBalancerBaseUrl); + const loadBalancerBaseUrl = useSelector(interaction.selectors.getLoadBalancerBaseUrl); - const plateLink = fileDetails?.getLinkToPlateUI(aicsLoadBalancerBaseUrl); + const plateLink = fileDetails?.getLinkToPlateUI(loadBalancerBaseUrl); const annotationNameToLinkMap = React.useMemo( () => fileDetails?.annotations diff --git a/packages/core/services/AnnotationService/HttpAnnotationService/index.ts b/packages/core/services/AnnotationService/HttpAnnotationService/index.ts index 3a6d7b649..0fdb9ff19 100644 --- a/packages/core/services/AnnotationService/HttpAnnotationService/index.ts +++ b/packages/core/services/AnnotationService/HttpAnnotationService/index.ts @@ -30,7 +30,7 @@ export default class HttpAnnotationService extends HttpServiceBase implements An * Fetch all annotations. */ public async fetchAnnotations(): Promise { - const requestUrl = `${this.baseUrl}/${HttpAnnotationService.BASE_ANNOTATION_URL}${this.pathSuffix}`; + const requestUrl = `${this.fileExplorerServiceBaseUrl}/${HttpAnnotationService.BASE_ANNOTATION_URL}${this.pathSuffix}`; const response = await this.get(requestUrl); return [ @@ -45,7 +45,7 @@ export default class HttpAnnotationService extends HttpServiceBase implements An public async fetchValues(annotation: string): Promise { // Encode any special characters in the annotation as necessary const encodedAnnotation = HttpServiceBase.encodeURISection(annotation); - const requestUrl = `${this.baseUrl}/${HttpAnnotationService.BASE_ANNOTATION_URL}/${encodedAnnotation}/values${this.pathSuffix}`; + const requestUrl = `${this.fileExplorerServiceBaseUrl}/${HttpAnnotationService.BASE_ANNOTATION_URL}/${encodedAnnotation}/values${this.pathSuffix}`; const response = await this.get(requestUrl); return response.data; @@ -70,7 +70,7 @@ export default class HttpAnnotationService extends HttpServiceBase implements An .filter((param) => !!param) .join("&"); - const requestUrl = `${this.baseUrl}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_ROOT_URL}${this.pathSuffix}?${queryParams}`; + const requestUrl = `${this.fileExplorerServiceBaseUrl}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_ROOT_URL}${this.pathSuffix}?${queryParams}`; const response = await this.get(requestUrl); return response.data; @@ -91,7 +91,7 @@ export default class HttpAnnotationService extends HttpServiceBase implements An ] .filter((param) => !!param) .join("&"); - const requestUrl = `${this.baseUrl}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_UNDER_PATH_URL}${this.pathSuffix}?${queryParams}`; + const requestUrl = `${this.fileExplorerServiceBaseUrl}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_UNDER_PATH_URL}${this.pathSuffix}?${queryParams}`; const response = await this.get(requestUrl); return response.data; @@ -103,7 +103,7 @@ export default class HttpAnnotationService extends HttpServiceBase implements An */ public async fetchAvailableAnnotationsForHierarchy(annotations: string[]): Promise { const queryParams = this.buildQueryParams(QueryParam.HIERARCHY, [...annotations].sort()); - const requestUrl = `${this.baseUrl}/${HttpAnnotationService.BASE_AVAILABLE_ANNOTATIONS_UNDER_HIERARCHY}${this.pathSuffix}?${queryParams}`; + const requestUrl = `${this.fileExplorerServiceBaseUrl}/${HttpAnnotationService.BASE_AVAILABLE_ANNOTATIONS_UNDER_HIERARCHY}${this.pathSuffix}?${queryParams}`; const response = await this.get(requestUrl); if (!response.data) { diff --git a/packages/core/services/AnnotationService/HttpAnnotationService/test/HttpAnnotationService.test.ts b/packages/core/services/AnnotationService/HttpAnnotationService/test/HttpAnnotationService.test.ts index 5ac7d9111..9d9db25dd 100644 --- a/packages/core/services/AnnotationService/HttpAnnotationService/test/HttpAnnotationService.test.ts +++ b/packages/core/services/AnnotationService/HttpAnnotationService/test/HttpAnnotationService.test.ts @@ -2,7 +2,7 @@ import { createMockHttpClient } from "@aics/redux-utils"; import { expect } from "chai"; import { spy } from "sinon"; -import { TOP_LEVEL_FILE_ANNOTATION_NAMES } from "../../../../constants"; +import { TOP_LEVEL_FILE_ANNOTATION_NAMES, FESBaseUrl } from "../../../../constants"; import Annotation from "../../../../entity/Annotation"; import { annotationsJson } from "../../../../entity/Annotation/mocks"; import FileFilter from "../../../../entity/FileFilter"; @@ -12,7 +12,7 @@ import HttpAnnotationService from ".."; describe("HttpAnnotationService", () => { describe("fetchAnnotations", () => { const httpClient = createMockHttpClient({ - when: `test/${HttpAnnotationService.BASE_ANNOTATION_URL}`, + when: `${FESBaseUrl.TEST}/${HttpAnnotationService.BASE_ANNOTATION_URL}`, respondWith: { data: { data: annotationsJson, @@ -21,7 +21,10 @@ describe("HttpAnnotationService", () => { }); it("issues request for all available Annotations", async () => { - const annotationService = new HttpAnnotationService({ baseUrl: "test", httpClient }); + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, + httpClient, + }); const annotations = await annotationService.fetchAnnotations(); expect(annotations.length).to.equal( annotationsJson.length + TOP_LEVEL_FILE_ANNOTATION_NAMES.length @@ -35,7 +38,7 @@ describe("HttpAnnotationService", () => { const annotation = "foo"; const values = ["a", "b", "c"]; const httpClient = createMockHttpClient({ - when: `test/${HttpAnnotationService.BASE_ANNOTATION_URL}/${annotation}/values`, + when: `${FESBaseUrl.TEST}/${HttpAnnotationService.BASE_ANNOTATION_URL}/${annotation}/values`, respondWith: { data: { data: values, @@ -43,7 +46,10 @@ describe("HttpAnnotationService", () => { }, }); - const annotationService = new HttpAnnotationService({ baseUrl: "test", httpClient }); + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, + httpClient, + }); const actualValues = await annotationService.fetchValues(annotation); expect(actualValues.length).to.equal(values.length); expect(actualValues).to.be.deep.equal(values); @@ -54,7 +60,7 @@ describe("HttpAnnotationService", () => { it("issues a request for annotation values for the first level of the annotation hierarchy", async () => { const expectedValues = ["foo", "bar", "baz"]; const httpClient = createMockHttpClient({ - when: `test/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_ROOT_URL}?order=foo`, + when: `${FESBaseUrl.TEST}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_ROOT_URL}?order=foo`, respondWith: { data: { data: expectedValues, @@ -62,7 +68,10 @@ describe("HttpAnnotationService", () => { }, }); - const annotationService = new HttpAnnotationService({ baseUrl: "test", httpClient }); + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, + httpClient, + }); const values = await annotationService.fetchRootHierarchyValues(["foo"], []); expect(values).to.equal(expectedValues); }); @@ -71,7 +80,7 @@ describe("HttpAnnotationService", () => { const expectedValues = ["foo", "bar", "baz"]; const httpClient = createMockHttpClient({ // note order of query params - when: `test/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_ROOT_URL}?order=z&order=a&order=b&order=c`, + when: `${FESBaseUrl.TEST}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_ROOT_URL}?order=z&order=a&order=b&order=c`, respondWith: { data: { data: expectedValues, @@ -80,7 +89,10 @@ describe("HttpAnnotationService", () => { }); const getSpy = spy(httpClient, "get"); - const annotationService = new HttpAnnotationService({ baseUrl: "test", httpClient }); + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, + httpClient, + }); // first time around const firstCallRet = await annotationService.fetchRootHierarchyValues( @@ -105,7 +117,7 @@ describe("HttpAnnotationService", () => { it("issues a request for annotation values for the first level of the annotation hierarchy with filters", async () => { const expectedValues = ["foo", "barValue", "baz"]; const httpClient = createMockHttpClient({ - when: `test/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_ROOT_URL}?order=foo&filter=bar=barValue`, + when: `${FESBaseUrl.TEST}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_ROOT_URL}?order=foo&filter=bar=barValue`, respondWith: { data: { data: expectedValues, @@ -113,7 +125,10 @@ describe("HttpAnnotationService", () => { }, }); - const annotationService = new HttpAnnotationService({ baseUrl: "test", httpClient }); + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, + httpClient, + }); const filter = new FileFilter("bar", "barValue"); const values = await annotationService.fetchRootHierarchyValues(["foo"], [filter]); expect(values).to.equal(expectedValues); @@ -124,7 +139,7 @@ describe("HttpAnnotationService", () => { it("issues request for hierarchy values under a specific path within the hierarchy", async () => { const expectedValues = [1, 2, 3]; const httpClient = createMockHttpClient({ - when: `test/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_UNDER_PATH_URL}?order=foo&order=bar&path=baz`, + when: `${FESBaseUrl.TEST}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_UNDER_PATH_URL}?order=foo&order=bar&path=baz`, respondWith: { data: { data: expectedValues, @@ -132,7 +147,10 @@ describe("HttpAnnotationService", () => { }, }); - const annotationService = new HttpAnnotationService({ baseUrl: "test", httpClient }); + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, + httpClient, + }); const values = await annotationService.fetchHierarchyValuesUnderPath( ["foo", "bar"], ["baz"], @@ -144,7 +162,7 @@ describe("HttpAnnotationService", () => { it("issues request for hierarchy values under a specific path within the hierarchy with filters", async () => { const expectedValues = [1, "barValue", 3]; const httpClient = createMockHttpClient({ - when: `test/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_UNDER_PATH_URL}?order=foo&order=bar&path=baz&filter=bar=barValue`, + when: `${FESBaseUrl.TEST}/${HttpAnnotationService.BASE_ANNOTATION_HIERARCHY_UNDER_PATH_URL}?order=foo&order=bar&path=baz&filter=bar=barValue`, respondWith: { data: { data: expectedValues, @@ -152,7 +170,10 @@ describe("HttpAnnotationService", () => { }, }); - const annotationService = new HttpAnnotationService({ baseUrl: "test", httpClient }); + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, + httpClient, + }); const filter = new FileFilter("bar", "barValue"); const values = await annotationService.fetchHierarchyValuesUnderPath( ["foo", "bar"], @@ -167,7 +188,7 @@ describe("HttpAnnotationService", () => { it("issues request for annotations that can be combined with current hierarchy", async () => { const annotationsFromServer = ["cell_dead", "date_created"]; const httpClient = createMockHttpClient({ - when: `test/${HttpAnnotationService.BASE_ANNOTATION_URL}/hierarchy/available?hierarchy=cas9&hierarchy=cell_line`, + when: `${FESBaseUrl.TEST}/${HttpAnnotationService.BASE_ANNOTATION_URL}/hierarchy/available?hierarchy=cas9&hierarchy=cell_line`, respondWith: { data: { data: annotationsFromServer, @@ -181,7 +202,10 @@ describe("HttpAnnotationService", () => { ...annotationsFromServer, ...hierarchy, ]; - const annotationService = new HttpAnnotationService({ baseUrl: "test", httpClient }); + const annotationService = new HttpAnnotationService({ + fileExplorerServiceBaseUrl: FESBaseUrl.TEST, + httpClient, + }); const values = await annotationService.fetchAvailableAnnotationsForHierarchy(hierarchy); expect(values.sort()).to.deep.equal(expectedValues.sort()); }); diff --git a/packages/core/services/FileService/HttpFileService/index.ts b/packages/core/services/FileService/HttpFileService/index.ts index 24f041c5a..d917c0481 100644 --- a/packages/core/services/FileService/HttpFileService/index.ts +++ b/packages/core/services/FileService/HttpFileService/index.ts @@ -40,7 +40,9 @@ export default class HttpFileService extends HttpServiceBase implements FileServ */ public async isNetworkAccessible(): Promise { try { - await this.get(`${this.baseUrl}/${HttpFileService.BASE_FILE_COUNT_URL}`); + await this.get( + `${this.fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILE_COUNT_URL}` + ); return true; } catch (error) { console.error(`Unable to access AICS network ${error}`); @@ -51,7 +53,7 @@ export default class HttpFileService extends HttpServiceBase implements FileServ public async getCountOfMatchingFiles(fileSet: FileSet): Promise { const requestUrl = join( compact([ - `${this.baseUrl}/${HttpFileService.BASE_FILE_COUNT_URL}${this.pathSuffix}`, + `${this.fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILE_COUNT_URL}${this.pathSuffix}`, fileSet.toQueryString(), ]), "?" @@ -72,7 +74,7 @@ export default class HttpFileService extends HttpServiceBase implements FileServ ): Promise { const selections = fileSelection.toCompactSelectionList(); const postBody: SelectionAggregationRequest = { selections }; - const requestUrl = `${this.baseUrl}/${HttpFileService.SELECTION_AGGREGATE_URL}${this.pathSuffix}`; + const requestUrl = `${this.fileExplorerServiceBaseUrl}/${HttpFileService.SELECTION_AGGREGATE_URL}${this.pathSuffix}`; const response = await this.post( requestUrl, @@ -93,7 +95,7 @@ export default class HttpFileService extends HttpServiceBase implements FileServ public async getFiles(request: GetFilesRequest): Promise { const { from, limit, fileSet } = request; - const base = `${this.baseUrl}/${HttpFileService.BASE_FILES_URL}${this.pathSuffix}?from=${from}&limit=${limit}`; + const base = `${this.fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}${this.pathSuffix}?from=${from}&limit=${limit}`; const requestUrl = join(compact([base, fileSet.toQueryString()]), "&"); const response = await this.get(requestUrl); @@ -115,7 +117,7 @@ export default class HttpFileService extends HttpServiceBase implements FileServ } const postData = JSON.stringify({ annotations, selections }); - const url = `${this.baseUrl}/${HttpFileService.BASE_CSV_DOWNLOAD_URL}${this.pathSuffix}`; + const url = `${this.fileExplorerServiceBaseUrl}/${HttpFileService.BASE_CSV_DOWNLOAD_URL}${this.pathSuffix}`; const manifest = await this.downloadService.prepareHttpResourceForDownload(url, postData); const name = `file-manifest-${new Date()}.csv`; @@ -137,13 +139,13 @@ export default class HttpFileService extends HttpServiceBase implements FileServ fileIds: string[], username?: string ): Promise<{ cacheFileStatuses: { [fileId: string]: string } }> { - const requestUrl = `${this.aicsLoadBalancerBaseUrl}/${HttpFileService.BASE_FILE_CACHE_URL}${this.pathSuffix}`; + const requestUrl = `${this.loadBalancerBaseUrl}/${HttpFileService.BASE_FILE_CACHE_URL}${this.pathSuffix}`; const requestBody = JSON.stringify({ fileIds }); const headers = { "Content-Type": "application/json", "X-User-Id": username || "anonymous", }; - console.log(headers); + console.log(requestUrl, requestBody, headers); try { const cacheStatuses = await this.rawPut<{ cacheFileStatuses: { [fileId: string]: string }; diff --git a/packages/core/services/FileService/HttpFileService/test/HttpFileService.test.ts b/packages/core/services/FileService/HttpFileService/test/HttpFileService.test.ts index a53564a5d..adec881d1 100644 --- a/packages/core/services/FileService/HttpFileService/test/HttpFileService.test.ts +++ b/packages/core/services/FileService/HttpFileService/test/HttpFileService.test.ts @@ -2,14 +2,15 @@ import { createMockHttpClient } from "@aics/redux-utils"; import { expect } from "chai"; import HttpFileService from ".."; +import { FESBaseUrl, LoadBalancerBaseUrl } from "../../../../constants"; import FileSelection from "../../../../entity/FileSelection"; import FileSet from "../../../../entity/FileSet"; import NumericRange from "../../../../entity/NumericRange"; import FileDownloadServiceNoop from "../../../FileDownloadService/FileDownloadServiceNoop"; describe("HttpFileService", () => { - const baseUrl = "test"; - const aicsLoadBalancerBaseUrlMock = "http://loadbalancer-test.aics.corp.alleninstitute.org"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; + const loadBalancerBaseUrl = LoadBalancerBaseUrl.TEST; const fileIds = ["abc123", "def456", "ghi789", "jkl012"]; const files = fileIds.map((file_id) => ({ file_id, @@ -29,7 +30,7 @@ describe("HttpFileService", () => { it("issues request for files that match given parameters", async () => { const httpFileService = new HttpFileService({ - baseUrl: baseUrl, + fileExplorerServiceBaseUrl: fileExplorerServiceBaseUrl, httpClient, downloadService: new FileDownloadServiceNoop(), }); @@ -49,7 +50,7 @@ describe("HttpFileService", () => { const totalFileSize = 12424114; const totalFileCount = 7; const httpClient = createMockHttpClient({ - when: `${baseUrl}/${HttpFileService.SELECTION_AGGREGATE_URL}`, + when: `${fileExplorerServiceBaseUrl}/${HttpFileService.SELECTION_AGGREGATE_URL}`, respondWith: { data: { data: [{ count: totalFileCount, size: totalFileSize }], @@ -60,7 +61,7 @@ describe("HttpFileService", () => { it("issues request for aggregated information about given files", async () => { // Arrange const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient, downloadService: new FileDownloadServiceNoop(), }); @@ -81,7 +82,7 @@ describe("HttpFileService", () => { describe("cacheFiles", () => { const httpClient = createMockHttpClient({ - when: `${aicsLoadBalancerBaseUrlMock}/${HttpFileService.BASE_FILE_CACHE_URL}`, + when: `${loadBalancerBaseUrl}/${HttpFileService.BASE_FILE_CACHE_URL}`, respondWith: { data: { cacheFileStatuses: { @@ -95,7 +96,7 @@ describe("HttpFileService", () => { it("sends file IDs to be cached and returns their statuses", async () => { // Arrange const fileService = new HttpFileService({ - aicsLoadBalancerBaseUrl: aicsLoadBalancerBaseUrlMock, + loadBalancerBaseUrl: loadBalancerBaseUrl, httpClient, downloadService: new FileDownloadServiceNoop(), }); diff --git a/packages/core/services/FileService/index.ts b/packages/core/services/FileService/index.ts index a540f2da4..9b5a53474 100644 --- a/packages/core/services/FileService/index.ts +++ b/packages/core/services/FileService/index.ts @@ -39,7 +39,7 @@ export interface Selection { } export default interface FileService { - baseUrl?: string; + fileExplorerServiceBaseUrl?: string; download( annotations: string[], selections: Selection[], diff --git a/packages/core/services/HttpServiceBase/index.ts b/packages/core/services/HttpServiceBase/index.ts index 3516272f1..220ec42a9 100644 --- a/packages/core/services/HttpServiceBase/index.ts +++ b/packages/core/services/HttpServiceBase/index.ts @@ -2,22 +2,24 @@ import axios, { AxiosInstance } from "axios"; import { Policy } from "cockatiel"; import LRUCache from "lru-cache"; -import { AicsLoadBalancerBaseUrl, FileExplorerServiceBaseUrl } from "../../constants"; +import { FESBaseUrl, LoadBalancerBaseUrl, MMSBaseUrl } from "../../constants"; import RestServiceResponse from "../../entity/RestServiceResponse"; export interface ConnectionConfig { - aicsLoadBalancerBaseUrl?: string | keyof typeof AicsLoadBalancerBaseUrl; applicationVersion?: string; - baseUrl?: string | keyof typeof FileExplorerServiceBaseUrl; + fileExplorerServiceBaseUrl?: FESBaseUrl; httpClient?: AxiosInstance; + loadBalancerBaseUrl?: LoadBalancerBaseUrl; + metadataManagementServiceBaseURl?: MMSBaseUrl; pathSuffix?: string; userName?: string; } export const DEFAULT_CONNECTION_CONFIG = { - aicsLoadBalancerBaseUrl: AicsLoadBalancerBaseUrl.PRODUCTION, - baseUrl: FileExplorerServiceBaseUrl.PRODUCTION, + fileExplorerServiceBaseUrl: FESBaseUrl.PRODUCTION, httpClient: axios.create(), + loadBalancerBaseUrl: LoadBalancerBaseUrl.PRODUCTION, + metadataManagementServiceBaseURl: MMSBaseUrl.PRODUCTION, }; const CHARACTER_TO_ENCODING_MAP: { [index: string]: string } = { @@ -47,7 +49,7 @@ const retry = Policy.handleAll() }); /** - * Base class for services that interact with AICS APIs. + * Base class for services that interact with APIs. */ export default class HttpServiceBase { /** @@ -68,7 +70,7 @@ export default class HttpServiceBase { } // encode ampersands that do not separate query string components, so first - // need to separate the query string componenets (which are split by ampersands themselves) + // need to separate the query string components (which are split by ampersands themselves) // handles case like `workflow=R&DExp&cell_line=AICS-46&foo=bar&cTnT%=3.0` const re = /&(?=(?:[^&])+\=)/g; const queryStringComponents = queryString.split(re); @@ -99,10 +101,11 @@ export default class HttpServiceBase { .join(""); } - public aicsLoadBalancerBaseUrl: string | keyof typeof AicsLoadBalancerBaseUrl = - DEFAULT_CONNECTION_CONFIG.aicsLoadBalancerBaseUrl; - public baseUrl: string | keyof typeof FileExplorerServiceBaseUrl = - DEFAULT_CONNECTION_CONFIG.baseUrl; + public fileExplorerServiceBaseUrl: string = + DEFAULT_CONNECTION_CONFIG.fileExplorerServiceBaseUrl; + public loadBalancerBaseUrl: string = DEFAULT_CONNECTION_CONFIG.loadBalancerBaseUrl; + public metadataManagementServiceBaseURl: string = + DEFAULT_CONNECTION_CONFIG.metadataManagementServiceBaseURl; protected httpClient = DEFAULT_CONNECTION_CONFIG.httpClient; private applicationVersion = "NOT SET"; @@ -111,10 +114,6 @@ export default class HttpServiceBase { private readonly urlToResponseDataCache = new LRUCache({ max: MAX_CACHE_SIZE }); constructor(config: ConnectionConfig = {}) { - if (config.aicsLoadBalancerBaseUrl) { - this.setAicsLoadBalancerBaseUrl(config.aicsLoadBalancerBaseUrl); - } - if (config.applicationVersion) { this.setApplicationVersion(config.applicationVersion); } @@ -123,14 +122,22 @@ export default class HttpServiceBase { this.setUserName(config.userName); } - if (config.baseUrl) { - this.setBaseUrl(config.baseUrl); + if (config.fileExplorerServiceBaseUrl) { + this.setFileExplorerServiceBaseUrl(config.fileExplorerServiceBaseUrl); } if (config.httpClient) { this.setHttpClient(config.httpClient); } + if (config.loadBalancerBaseUrl) { + this.setLoadBalancerBaseUrl(config.loadBalancerBaseUrl); + } + + if (config.metadataManagementServiceBaseURl) { + this.setMetadataManagementServiceBaseURl(config.metadataManagementServiceBaseURl); + } + if (config.pathSuffix) { this.pathSuffix = config.pathSuffix; } @@ -269,34 +276,18 @@ export default class HttpServiceBase { return new RestServiceResponse(response.data); } - public setAicsLoadBalancerBaseUrl( - aicsLoadBalancerBaseUrl: string | keyof typeof AicsLoadBalancerBaseUrl - ) { - if (this.aicsLoadBalancerBaseUrl !== aicsLoadBalancerBaseUrl) { - // bust cache when base url changes - this.urlToResponseDataCache.reset(); - } - - this.aicsLoadBalancerBaseUrl = aicsLoadBalancerBaseUrl; - } - public setApplicationVersion(applicationVersion: string) { this.applicationVersion = applicationVersion; this.setHeaders(); } - public setUserName(userName: string) { - this.userName = userName; - this.setHeaders(); - } - - public setBaseUrl(baseUrl: string | keyof typeof FileExplorerServiceBaseUrl) { - if (this.baseUrl !== baseUrl) { + public setFileExplorerServiceBaseUrl(fileExplorerServiceBaseUrl: FESBaseUrl) { + if (this.fileExplorerServiceBaseUrl !== fileExplorerServiceBaseUrl) { // bust cache when base url changes this.urlToResponseDataCache.reset(); } - this.baseUrl = baseUrl; + this.fileExplorerServiceBaseUrl = fileExplorerServiceBaseUrl; } public setHttpClient(client: AxiosInstance) { @@ -319,4 +310,27 @@ export default class HttpServiceBase { delete this.httpClient.defaults.headers.common["X-User-Id"]; } } + + public setLoadBalancerBaseUrl(loadBalancerBaseUrl: LoadBalancerBaseUrl) { + if (this.loadBalancerBaseUrl !== loadBalancerBaseUrl) { + // bust cache when base url changes + this.urlToResponseDataCache.reset(); + } + + this.loadBalancerBaseUrl = loadBalancerBaseUrl; + } + + public setMetadataManagementServiceBaseURl(metadataManagementServiceBaseURl: MMSBaseUrl) { + if (this.metadataManagementServiceBaseURl !== metadataManagementServiceBaseURl) { + // bust cache when base url changes + this.urlToResponseDataCache.reset(); + } + + this.metadataManagementServiceBaseURl = metadataManagementServiceBaseURl; + } + + public setUserName(userName: string) { + this.userName = userName; + this.setHeaders(); + } } diff --git a/packages/core/services/PersistentConfigService/index.ts b/packages/core/services/PersistentConfigService/index.ts index 86a02bc2f..e9a0bc62f 100644 --- a/packages/core/services/PersistentConfigService/index.ts +++ b/packages/core/services/PersistentConfigService/index.ts @@ -1,5 +1,6 @@ import { AnnotationResponse } from "../../entity/Annotation"; import { Query } from "../../state/selection/actions"; +import { Environment } from "../../constants"; /** * Keys for the data saved by this service @@ -13,6 +14,7 @@ export enum PersistedConfigKeys { UserSelectedApplications = "USER_SELECTED_APPLICATIONS", Queries = "QUERIES", RecentAnnotations = "RECENT_ANNOTATIONS", + Environment = "ENVIRONMENT", } export interface UserSelectedApplication { @@ -29,6 +31,7 @@ export interface PersistedConfig { [PersistedConfigKeys.Queries]?: Query[]; [PersistedConfigKeys.RecentAnnotations]?: string[]; [PersistedConfigKeys.UserSelectedApplications]?: UserSelectedApplication[]; + [PersistedConfigKeys.Environment]?: Environment; } /** diff --git a/packages/core/state/interaction/actions.ts b/packages/core/state/interaction/actions.ts index e5f98007a..eca0a8c54 100644 --- a/packages/core/state/interaction/actions.ts +++ b/packages/core/state/interaction/actions.ts @@ -260,10 +260,7 @@ export interface InitializeApp { payload: string; } -export const initializeApp = (payload: { - aicsLoadBalancerBaseUrl: string; - fileExplorerServiceBaseUrl: string; -}) => ({ +export const initializeApp = (payload: { environment: string }) => ({ type: INITIALIZE_APP, payload, }); diff --git a/packages/core/state/interaction/reducer.ts b/packages/core/state/interaction/reducer.ts index f8bea8207..735b86632 100644 --- a/packages/core/state/interaction/reducer.ts +++ b/packages/core/state/interaction/reducer.ts @@ -30,12 +30,12 @@ import { } from "./actions"; import { ContextMenuItem, PositionReference } from "../../components/ContextMenu"; import { ModalType } from "../../components/Modal"; +import { Environment } from "../../constants"; import FileFilter from "../../entity/FileFilter"; import { PlatformDependentServices } from "../../services"; import ApplicationInfoServiceNoop from "../../services/ApplicationInfoService/ApplicationInfoServiceNoop"; import FileDownloadServiceNoop from "../../services/FileDownloadService/FileDownloadServiceNoop"; import FileViewerServiceNoop from "../../services/FileViewerService/FileViewerServiceNoop"; -import { DEFAULT_CONNECTION_CONFIG } from "../../services/HttpServiceBase"; import ExecutionEnvServiceNoop from "../../services/ExecutionEnvService/ExecutionEnvServiceNoop"; import { UserSelectedApplication } from "../../services/PersistentConfigService"; import NotificationServiceNoop from "../../services/NotificationService/NotificationServiceNoop"; @@ -43,7 +43,6 @@ import DatabaseServiceNoop from "../../services/DatabaseService/DatabaseServiceN import PublicDataset from "../../../web/src/entity/PublicDataset"; export interface InteractionStateBranch { - aicsLoadBalancerBaseUrl: string; applicationVersion?: string; contextMenuIsVisible: boolean; contextMenuItems: ContextMenuItem[]; @@ -52,9 +51,9 @@ export interface InteractionStateBranch { csvColumns?: string[]; dataSourceInfoForVisibleModal?: DataSourcePromptInfo; datasetDetailsPanelIsVisible: boolean; - fileExplorerServiceBaseUrl: string; fileTypeForVisibleModal: "csv" | "json" | "parquet"; fileFiltersForVisibleModal: FileFilter[]; + environment: "LOCALHOST" | "STAGING" | "PRODUCTION" | "TEST"; hasDismissedSmallScreenWarning: boolean; hasUsedApplicationBefore: boolean; isAicsEmployee?: boolean; @@ -68,7 +67,7 @@ export interface InteractionStateBranch { } export const initialState: InteractionStateBranch = { - aicsLoadBalancerBaseUrl: DEFAULT_CONNECTION_CONFIG.aicsLoadBalancerBaseUrl, + environment: Environment.PRODUCTION, contextMenuIsVisible: false, contextMenuItems: [], // Passed to `ContextualMenu` as `target`. From the "@fluentui/react" docs: @@ -77,7 +76,6 @@ export const initialState: InteractionStateBranch = { // If a MouseEvent is given, the origin point of the event will be used." contextMenuPositionReference: null, datasetDetailsPanelIsVisible: false, - fileExplorerServiceBaseUrl: DEFAULT_CONNECTION_CONFIG.baseUrl, fileFiltersForVisibleModal: [], fileTypeForVisibleModal: "csv", hasDismissedSmallScreenWarning: false, @@ -168,8 +166,7 @@ export default makeReducer( }), [INITIALIZE_APP]: (state, action) => ({ ...state, - aicsLoadBalancerBaseUrl: action.payload.aicsLoadBalancerBaseUrl, - fileExplorerServiceBaseUrl: action.payload.fileExplorerServiceBaseUrl, + environment: action.payload.environment, }), [SET_VISIBLE_MODAL]: (state, action) => ({ ...state, diff --git a/packages/core/state/interaction/selectors.ts b/packages/core/state/interaction/selectors.ts index 75c852b63..553de3f46 100644 --- a/packages/core/state/interaction/selectors.ts +++ b/packages/core/state/interaction/selectors.ts @@ -14,11 +14,15 @@ import DatabaseFileService from "../../services/FileService/DatabaseFileService" import HttpAnnotationService from "../../services/AnnotationService/HttpAnnotationService"; import HttpFileService from "../../services/FileService/HttpFileService"; import { ModalType } from "../../components/Modal"; -import { AICS_FMS_DATA_SOURCE_NAME } from "../../constants"; +import { + AICS_FMS_DATA_SOURCE_NAME, + FESBaseUrl, + MMSBaseUrl, + LoadBalancerBaseUrl, +} from "../../constants"; // BASIC SELECTORS -export const getAicsLoadBalancerBaseUrl = (state: State) => - state.interaction.aicsLoadBalancerBaseUrl; +export const getEnvironment = (state: State) => state.interaction.environment; export const getContextMenuVisibility = (state: State) => state.interaction.contextMenuIsVisible; export const getContextMenuItems = (state: State) => state.interaction.contextMenuItems; export const getContextMenuPositionReference = (state: State) => @@ -30,8 +34,6 @@ export const getDataSourceInfoForVisibleModal = (state: State) => export const getDatasetDetailsVisibility = (state: State) => state.interaction.datasetDetailsPanelIsVisible; export const getSelectedPublicDataset = (state: State) => state.interaction.selectedPublicDataset; -export const getFileExplorerServiceBaseUrl = (state: State) => - state.interaction.fileExplorerServiceBaseUrl; export const getFileFiltersForVisibleModal = (state: State) => state.interaction.fileFiltersForVisibleModal; export const getFileTypeForVisibleModal = (state: State) => @@ -50,6 +52,22 @@ export const getUserSelectedApplications = (state: State) => export const getVisibleModal = (state: State) => state.interaction.visibleModal; export const isAicsEmployee = (state: State) => state.interaction.isAicsEmployee; +// URL Mapping Selectors +export const getFileExplorerServiceBaseUrl = createSelector( + [getEnvironment], + (environment) => FESBaseUrl[environment] +); + +export const getLoadBalancerBaseUrl = createSelector( + [getEnvironment], + (environment) => LoadBalancerBaseUrl[environment] +); + +export const getMetadataManagementServiceBaseUrl = createSelector( + [getEnvironment], + (environment) => MMSBaseUrl[environment] +); + // COMPOSED SELECTORS export const getApplicationVersion = createSelector( [getPlatformDependentServices], @@ -103,24 +121,27 @@ export const getUserName = createSelector( export const getHttpFileService = createSelector( [ getApplicationVersion, - getUserName, - getAicsLoadBalancerBaseUrl, getFileExplorerServiceBaseUrl, + getLoadBalancerBaseUrl, + getMetadataManagementServiceBaseUrl, + getUserName, getPlatformDependentServices, getRefreshKey, ], ( applicationVersion, + fileExplorerServiceBaseUrl, + loadBalancerBaseUrl, + metadataManagementServiceBaseURL, userName, - aicsLoadBalancerBaseUrl, - fileExplorerBaseUrl, platformDependentServices ) => new HttpFileService({ applicationVersion, + fileExplorerServiceBaseUrl: fileExplorerServiceBaseUrl, + loadBalancerBaseUrl: loadBalancerBaseUrl, + metadataManagementServiceBaseURl: metadataManagementServiceBaseURL, userName, - aicsLoadBalancerBaseUrl: aicsLoadBalancerBaseUrl, - baseUrl: fileExplorerBaseUrl, downloadService: platformDependentServices.fileDownloadService, }) ); @@ -163,7 +184,6 @@ export const getAnnotationService = createSelector( [ getApplicationVersion, getUserName, - getAicsLoadBalancerBaseUrl, getFileExplorerServiceBaseUrl, getSelectedDataSources, getPlatformDependentServices, @@ -172,8 +192,7 @@ export const getAnnotationService = createSelector( ( applicationVersion, userName, - aicsLoadBalancerBaseUrl, - fileExplorerBaseUrl, + fileExplorerServiceBaseUrl, dataSources, platformDependentServices ): AnnotationService => { @@ -186,26 +205,18 @@ export const getAnnotationService = createSelector( return new HttpAnnotationService({ applicationVersion, userName, - aicsLoadBalancerBaseUrl: aicsLoadBalancerBaseUrl, - baseUrl: fileExplorerBaseUrl, + fileExplorerServiceBaseUrl: fileExplorerServiceBaseUrl, }); } ); export const getDatasetService = createSelector( - [ - getApplicationVersion, - getUserName, - getAicsLoadBalancerBaseUrl, - getFileExplorerServiceBaseUrl, - getRefreshKey, - ], - (applicationVersion, userName, aicsLoadBalancerBaseUrl, fileExplorerBaseUrl) => + [getApplicationVersion, getUserName, getFileExplorerServiceBaseUrl, getRefreshKey], + (applicationVersion, userName, fileExplorerServiceBaseUrl) => new DatasetService({ applicationVersion, userName, - aicsLoadBalancerBaseUrl: aicsLoadBalancerBaseUrl, - baseUrl: fileExplorerBaseUrl, + fileExplorerServiceBaseUrl: fileExplorerServiceBaseUrl, }) ); diff --git a/packages/core/state/interaction/test/logics.test.ts b/packages/core/state/interaction/test/logics.test.ts index 688c55321..f9dc58c19 100644 --- a/packages/core/state/interaction/test/logics.test.ts +++ b/packages/core/state/interaction/test/logics.test.ts @@ -24,6 +24,7 @@ import { } from "../../../services/ExecutionEnvService"; import ExecutionEnvServiceNoop from "../../../services/ExecutionEnvService/ExecutionEnvServiceNoop"; import interactionLogics from "../logics"; +import { FESBaseUrl } from "../../../constants"; import Annotation from "../../../entity/Annotation"; import AnnotationName from "../../../entity/Annotation/AnnotationName"; import { AnnotationType } from "../../../entity/AnnotationFormatter"; @@ -206,7 +207,7 @@ describe("Interaction logics", () => { it("doesn't use selected files when given a specific file folder path", async () => { // arrange - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; const filters = [ new FileFilter("Cell Line", "AICS-12"), new FileFilter("Notes", "Hello"), @@ -215,7 +216,6 @@ describe("Interaction logics", () => { const state = mergeState(initialState, { interaction: { fileFiltersForVisibleModal: filters, - fileExplorerServiceBaseUrl: baseUrl, platformDependentServices: { fileDownloadService: new FileDownloadServiceNoop(), }, @@ -232,7 +232,7 @@ describe("Interaction logics", () => { }; const mockHttpClient = createMockHttpClient(responseStub); const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient: mockHttpClient, downloadService: new FileDownloadServiceNoop(), }); @@ -776,12 +776,12 @@ describe("Interaction logics", () => { describe("refresh", () => { const sandbox = createSandbox(); - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; const annotations = annotationsJson.map((annotation) => new Annotation(annotation)); const availableAnnotations = [annotations[1].displayName]; const responseStubs = [ { - when: `${baseUrl}/${HttpAnnotationService.BASE_ANNOTATION_URL}`, + when: `${fileExplorerServiceBaseUrl}/${HttpAnnotationService.BASE_ANNOTATION_URL}`, respondWith: { data: { data: annotations }, }, @@ -798,7 +798,7 @@ describe("Interaction logics", () => { ]; const mockHttpClient = createMockHttpClient(responseStubs); const annotationService = new HttpAnnotationService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient: mockHttpClient, }); @@ -883,7 +883,7 @@ describe("Interaction logics", () => { ], }); } - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; const responseStub = { when: () => true, respondWith: { @@ -892,7 +892,7 @@ describe("Interaction logics", () => { }; const mockHttpClient = createMockHttpClient(responseStub); const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient: mockHttpClient, downloadService: new FileDownloadServiceNoop(), }); @@ -1099,16 +1099,16 @@ describe("Interaction logics", () => { }); } const files = [...csvFiles, ...pngFiles]; - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; const responseStub = { - when: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=101`, + when: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=101`, respondWith: { data: { data: files }, }, }; const mockHttpClient = createMockHttpClient(responseStub); const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient: mockHttpClient, downloadService: new FileDownloadServiceNoop(), }); @@ -1214,16 +1214,16 @@ describe("Interaction logics", () => { for (let i = 0; i <= 100; i++) { files.push({ file_path: `/allen/file_${i}.ext` }); } - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; const responseStub = { - when: `${baseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=101`, + when: `${fileExplorerServiceBaseUrl}/${HttpFileService.BASE_FILES_URL}?from=0&limit=101`, respondWith: { data: { data: files }, }, }; const mockHttpClient = createMockHttpClient(responseStub); const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient: mockHttpClient, downloadService: new FileDownloadServiceNoop(), }); diff --git a/packages/core/state/metadata/test/logics.test.ts b/packages/core/state/metadata/test/logics.test.ts index 9edb3717a..163f2a251 100644 --- a/packages/core/state/metadata/test/logics.test.ts +++ b/packages/core/state/metadata/test/logics.test.ts @@ -19,11 +19,7 @@ describe("Metadata logics", () => { describe("requestAnnotations", () => { it("Fires RECEIVE_ANNOTATIONS action after processing REQUEST_ANNOTATIONS action", async () => { // arrange - const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, - }); + const state = mergeState(initialState, {}); const responseStub = { when: () => true, diff --git a/packages/core/state/selection/test/logics.test.ts b/packages/core/state/selection/test/logics.test.ts index edb8a9412..697ec38a5 100644 --- a/packages/core/state/selection/test/logics.test.ts +++ b/packages/core/state/selection/test/logics.test.ts @@ -27,6 +27,7 @@ import { changeSourceMetadata, } from "../actions"; import { initialState, interaction } from "../../"; +import { FESBaseUrl } from "../../../constants"; import Annotation from "../../../entity/Annotation"; import AnnotationName from "../../../entity/Annotation/AnnotationName"; import FileFilter from "../../../entity/FileFilter"; @@ -330,10 +331,10 @@ describe("Selection logics", () => { }, }, ]; - const baseUrl = "test"; + const fileExplorerServiceBaseUrl = FESBaseUrl.TEST; const mockHttpClient = createMockHttpClient(responseStubs); const fileService = new HttpFileService({ - baseUrl, + fileExplorerServiceBaseUrl, httpClient: mockHttpClient, downloadService: new FileDownloadServiceNoop(), }); @@ -354,9 +355,6 @@ describe("Selection logics", () => { it("selects file above current focused row", async () => { // Arrange const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: baseUrl, - }, selection: { fileSelection: new FileSelection() .select({ @@ -398,9 +396,6 @@ describe("Selection logics", () => { sortOrder: 1, }); const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: baseUrl, - }, selection: { fileSelection: new FileSelection().select({ fileSet, @@ -462,9 +457,6 @@ describe("Selection logics", () => { it("adds a new annotation to the end of the hierarchy", async () => { // setup const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, metadata: { annotations: [...annotations], }, @@ -494,9 +486,6 @@ describe("Selection logics", () => { it("moves an annotation within the hierarchy to a new position", async () => { // setup const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, metadata: { annotations: [...annotations], }, @@ -540,9 +529,6 @@ describe("Selection logics", () => { // ones to test proper comparison using annotationName const annotationHierarchy = annotations.slice(0, 4).map((a) => a.name); const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, metadata: { annotations: [...annotations], }, @@ -580,9 +566,6 @@ describe("Selection logics", () => { new FileFolder(["AICS-0", "false"]), ]; const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, metadata: { annotations: [...annotations], }, @@ -612,9 +595,6 @@ describe("Selection logics", () => { it("determines which paths can still be opened after annotation is added", async () => { // setup const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, metadata: { annotations: [...annotations], }, @@ -647,9 +627,6 @@ describe("Selection logics", () => { it("determines which paths can still be opened after annotation is removed", async () => { // setup const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, metadata: { annotations: [...annotations], }, @@ -711,9 +688,6 @@ describe("Selection logics", () => { it("sets available annotations", async () => { // Arrange const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, metadata: { annotations: [...annotations], }, @@ -752,9 +726,6 @@ describe("Selection logics", () => { it("sets all annotations as available when actual cannot be found", async () => { // Arrange const state = mergeState(initialState, { - interaction: { - fileExplorerServiceBaseUrl: "test", - }, metadata: { annotations: [...annotations], }, diff --git a/packages/core/state/selection/test/reducer.test.ts b/packages/core/state/selection/test/reducer.test.ts index 232e1ca5e..155b83a17 100644 --- a/packages/core/state/selection/test/reducer.test.ts +++ b/packages/core/state/selection/test/reducer.test.ts @@ -17,8 +17,7 @@ describe("Selection reducer", () => { [ selection.actions.setAnnotationHierarchy([]), interaction.actions.initializeApp({ - fileExplorerServiceBaseUrl: "base", - aicsLoadBalancerBaseUrl: "loadBalancerBaseUrl", + environment: "TEST", }), ].forEach((expectedAction) => it(`clears selected file state when ${expectedAction.type} is fired`, () => { diff --git a/packages/desktop/src/main/global.d.ts b/packages/desktop/src/main/global.d.ts index c28d2c8bc..cbf699645 100644 --- a/packages/desktop/src/main/global.d.ts +++ b/packages/desktop/src/main/global.d.ts @@ -1,4 +1,7 @@ /*eslint no-var: "off"*/ -// necessary in order to do: global.fileExplorerServiceBaseUrl = "..." -declare var aicsLoadBalancerBaseUrl: string; -declare var fileExplorerServiceBaseUrl: string; +// necessary in order to do: global.environment = "..." +import { Environment } from "./util/constants"; + +declare global { + var environment: Environment; +} diff --git a/packages/desktop/src/main/menu/data-source.ts b/packages/desktop/src/main/menu/data-source.ts index 9b73a3581..930575fa3 100644 --- a/packages/desktop/src/main/menu/data-source.ts +++ b/packages/desktop/src/main/menu/data-source.ts @@ -1,14 +1,9 @@ import { MenuItemConstructorOptions } from "electron"; -import { - GlobalVariableChannels, - AicsLoadBalancerBaseUrl, - FileExplorerServiceBaseUrl, -} from "../../util/constants"; +import { GlobalVariableChannels, Environment } from "../../util/constants"; // Least effort state management accessible to both the main and renderer processes. -global.aicsLoadBalancerBaseUrl = AicsLoadBalancerBaseUrl.PRODUCTION; -global.fileExplorerServiceBaseUrl = FileExplorerServiceBaseUrl.PRODUCTION; +global.environment = Environment.PRODUCTION; const dataSourceMenu: MenuItemConstructorOptions = { label: "Data Source", @@ -16,16 +11,12 @@ const dataSourceMenu: MenuItemConstructorOptions = { { label: "Localhost", type: "radio", - checked: - global.aicsLoadBalancerBaseUrl === AicsLoadBalancerBaseUrl.LOCALHOST && - global.fileExplorerServiceBaseUrl === FileExplorerServiceBaseUrl.LOCALHOST, + checked: global.environment === Environment.LOCALHOST, click: (_, focusedWindow) => { if (focusedWindow) { - global.aicsLoadBalancerBaseUrl = AicsLoadBalancerBaseUrl.LOCALHOST; - global.fileExplorerServiceBaseUrl = FileExplorerServiceBaseUrl.LOCALHOST; + global.environment = Environment.LOCALHOST; focusedWindow.webContents.send(GlobalVariableChannels.BaseUrl, { - aicsLoadBalancerBaseUrl: AicsLoadBalancerBaseUrl.LOCALHOST, - fileExplorerServiceBaseUrl: FileExplorerServiceBaseUrl.LOCALHOST, + environment: Environment.LOCALHOST, }); } }, @@ -33,16 +24,12 @@ const dataSourceMenu: MenuItemConstructorOptions = { { label: "Staging", type: "radio", - checked: - global.aicsLoadBalancerBaseUrl === AicsLoadBalancerBaseUrl.STAGING && - global.fileExplorerServiceBaseUrl === FileExplorerServiceBaseUrl.STAGING, + checked: global.environment === Environment.STAGING, click: (_, focusedWindow) => { if (focusedWindow) { - global.aicsLoadBalancerBaseUrl = AicsLoadBalancerBaseUrl.STAGING; - global.fileExplorerServiceBaseUrl = FileExplorerServiceBaseUrl.STAGING; + global.environment = Environment.STAGING; focusedWindow.webContents.send(GlobalVariableChannels.BaseUrl, { - aicsLoadBalancerBaseUrl: AicsLoadBalancerBaseUrl.STAGING, - fileExplorerServiceBaseUrl: FileExplorerServiceBaseUrl.STAGING, + environment: Environment.STAGING, }); } }, @@ -50,16 +37,12 @@ const dataSourceMenu: MenuItemConstructorOptions = { { label: "Production", type: "radio", - checked: - global.aicsLoadBalancerBaseUrl === AicsLoadBalancerBaseUrl.PRODUCTION && - global.fileExplorerServiceBaseUrl === FileExplorerServiceBaseUrl.PRODUCTION, + checked: global.environment === Environment.PRODUCTION, click: (_, focusedWindow) => { if (focusedWindow) { - global.aicsLoadBalancerBaseUrl = AicsLoadBalancerBaseUrl.PRODUCTION; - global.fileExplorerServiceBaseUrl = FileExplorerServiceBaseUrl.PRODUCTION; + global.environment = Environment.PRODUCTION; focusedWindow.webContents.send(GlobalVariableChannels.BaseUrl, { - aicsLoadBalancerBaseUrl: AicsLoadBalancerBaseUrl.PRODUCTION, - fileExplorerServiceBaseUrl: FileExplorerServiceBaseUrl.PRODUCTION, + environment: Environment.PRODUCTION, }); } }, diff --git a/packages/desktop/src/renderer/index.tsx b/packages/desktop/src/renderer/index.tsx index 36c27fd64..5ceded4e7 100644 --- a/packages/desktop/src/renderer/index.tsx +++ b/packages/desktop/src/renderer/index.tsx @@ -34,12 +34,20 @@ const KeyDownHandler: React.FC<{ clearStore: () => void }> = ({ clearStore }) => return null; }; -// Function to clear the persistent store +// Clears the persistent store but retains `Environment` to prevent misalignment +// between the data source and the selected menu item in the app. const clearPersistentStore = () => { + const currentEnvironment = global.environment; persistentConfigService.clear(); + persistentConfigService.persist({ [PersistedConfigKeys.Environment]: currentEnvironment }); window.location.reload(); }; +const initializeEnvironment = () => { + const savedEnvironment = persistentConfigService.get(PersistedConfigKeys.Environment); + global.environment = savedEnvironment || "PRODUCTION"; +}; + // Application analytics/metrics const frontendInsights = new FrontendInsights( { @@ -120,10 +128,7 @@ function renderFmsFileExplorer() { - + , document.getElementById(APP_ID) @@ -131,13 +136,11 @@ function renderFmsFileExplorer() { } // Listen for IPC updates to global variables -ipcRenderer.addListener( - GlobalVariableChannels.BaseUrl, - (_, { aicsLoadBalancerBaseUrl, fileExplorerServiceBaseUrl }) => { - global.aicsLoadBalancerBaseUrl = aicsLoadBalancerBaseUrl; - global.fileExplorerServiceBaseUrl = fileExplorerServiceBaseUrl; - renderFmsFileExplorer(); - } -); +ipcRenderer.addListener(GlobalVariableChannels.BaseUrl, (_, { environment }) => { + global.environment = environment; + persistentConfigService.persist({ [PersistedConfigKeys.Environment]: environment }); + renderFmsFileExplorer(); +}); +initializeEnvironment(); renderFmsFileExplorer(); diff --git a/packages/desktop/src/services/test/PersistentConfigServiceElectron.test.ts b/packages/desktop/src/services/test/PersistentConfigServiceElectron.test.ts index 7d1c8efa3..c547a758f 100644 --- a/packages/desktop/src/services/test/PersistentConfigServiceElectron.test.ts +++ b/packages/desktop/src/services/test/PersistentConfigServiceElectron.test.ts @@ -1,7 +1,7 @@ import { expect } from "chai"; import { PersistedConfigKeys } from "../../../../core/services"; -import { RUN_IN_RENDERER } from "../../util/constants"; +import { Environment, RUN_IN_RENDERER } from "../../util/constants"; import PersistentConfigServiceElectron from "../PersistentConfigServiceElectron"; describe(`${RUN_IN_RENDERER} PersistentConfigServiceElectron`, () => { @@ -61,6 +61,7 @@ describe(`${RUN_IN_RENDERER} PersistentConfigServiceElectron`, () => { units: "string", }, ]; + const expectedEnvironment = Environment.TEST; service.persist(PersistedConfigKeys.AllenMountPoint, expectedAllenMountPoint); service.persist(PersistedConfigKeys.CsvColumns, expectedCsvColumns); @@ -73,6 +74,7 @@ describe(`${RUN_IN_RENDERER} PersistentConfigServiceElectron`, () => { service.persist(PersistedConfigKeys.UserSelectedApplications, expectedUserSelectedApps); service.persist(PersistedConfigKeys.DisplayAnnotations, expectedDisplayAnnotations); service.persist(PersistedConfigKeys.RecentAnnotations, expectedRecentAnnotations); + service.persist(PersistedConfigKeys.Environment, expectedEnvironment); const expectedConfig = { [PersistedConfigKeys.AllenMountPoint]: expectedAllenMountPoint, @@ -83,6 +85,7 @@ describe(`${RUN_IN_RENDERER} PersistentConfigServiceElectron`, () => { [PersistedConfigKeys.UserSelectedApplications]: expectedUserSelectedApps, [PersistedConfigKeys.DisplayAnnotations]: expectedDisplayAnnotations, [PersistedConfigKeys.RecentAnnotations]: expectedRecentAnnotations, + [PersistedConfigKeys.Environment]: expectedEnvironment, }; // Act @@ -120,6 +123,7 @@ describe(`${RUN_IN_RENDERER} PersistentConfigServiceElectron`, () => { units: "string", }, ], + [PersistedConfigKeys.Environment]: Environment.TEST, }; // Act @@ -159,10 +163,13 @@ describe(`${RUN_IN_RENDERER} PersistentConfigServiceElectron`, () => { service.persist(PersistedConfigKeys.CsvColumns, ["Cell Line"]); service.persist(PersistedConfigKeys.CsvColumns, expected); service.persist(PersistedConfigKeys.AllenMountPoint, "/my/path/allen"); + service.persist(PersistedConfigKeys.Environment, Environment.TEST); // Assert const actual = service.get(PersistedConfigKeys.CsvColumns); + const actualEnvironment = service.get(PersistedConfigKeys.Environment); expect(actual).to.be.deep.equal(expected); + expect(actualEnvironment).to.equal(Environment.TEST); }); }); }); diff --git a/packages/desktop/src/util/constants.ts b/packages/desktop/src/util/constants.ts index 0edb80235..bda836ed7 100644 --- a/packages/desktop/src/util/constants.ts +++ b/packages/desktop/src/util/constants.ts @@ -3,16 +3,11 @@ // pattern used in the npm script used to invoke electron-mocha. export const RUN_IN_RENDERER = "@renderer"; -export enum AicsLoadBalancerBaseUrl { - LOCALHOST = "http://localhost:8080", - STAGING = "http://stg-aics.corp.alleninstitute.org", - PRODUCTION = "http://aics.corp.alleninstitute.org", -} - -export enum FileExplorerServiceBaseUrl { - LOCALHOST = "http://localhost:9081", - STAGING = "https://staging.int.allencell.org", - PRODUCTION = "https://production.int.allencell.org", +export enum Environment { + LOCALHOST = "LOCALHOST", + STAGING = "STAGING", + PRODUCTION = "PRODUCTION", + TEST = "TEST", } // Channels global variables can be modified on / listen to