Skip to content

Commit

Permalink
Merge pull request #83 from AllenInstitute/feature/use-csv-as-data-so…
Browse files Browse the repository at this point in the history
…urce

Feature/use csv as data source
  • Loading branch information
SeanLeRoy authored May 7, 2024
2 parents 784f172 + ce2207e commit 008ec55
Show file tree
Hide file tree
Showing 229 changed files with 7,431 additions and 8,336 deletions.
1,808 changes: 1,692 additions & 116 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "root",
"version": "6.5.1",
"license": "2-clause BSD license plus a third clause that prohibits redistribution and use for commercial purposes without further permission.",
"engines": {
"node": "16.x",
Expand Down
81 changes: 31 additions & 50 deletions packages/core/App.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.light-theme {
/* placeholder for until / if we do a light theme for the app */
color: orange;
}

.absolute {
position: absolute;
}
Expand All @@ -7,22 +12,10 @@
}

.root {
--annotation-hierarchy-max-width: 350px;
--blue: steelblue;
--grey: #c8c8c8;
--white: #ffffff;
--url-bar-height: 40px;
--file-details-width: 20%;
--margin: 12px;
--transition-duration: 0.5s;
--smaller-font-size: small;
/* AICS brand colors pulled from AICS style guide */
--primary-brand-dark-blue: #003057;
--primary-brand-purple: #827aa3;
--primary-brand-grey: #7c7d7f;
--secondary-brand-purple: #bab5c9;
--brand-error: #c23030;
--global-button-row-height: 40px;

background-color: var(--secondary-background-color);
color: var(--secondary-text-color);
composes: relative;
margin: 0;
border: 0;
Expand All @@ -32,81 +25,69 @@
overflow: hidden; /* TODO; should be unnecessary */
}

.small-font {
font-size: smaller;
}

/* Globally remove the ability to select text. Individual elements that need this should opt-in. */
.root * {
user-select: none;
}

.content {
display: flex;
flex-direction: column;
height: 100%;
}

.header-ribbon {
display: block;
width: 100%;
}

.everything-except-header-ribbon {
.core-and-file-details {
composes: relative;
display: flex;
flex: auto;
margin: var(--margin);
height: 100%;
/* margin: var(--margin); */
overflow: hidden;
width: calc(100% - (2 * var(--margin)));
}

.core {
.query-sidebar-and-center {
margin-right: var(--margin);
width: calc(80% - var(--margin));
height: 100%;
display: flex;

/* flex child */
flex: 1 0 auto;
transition: flex var(--transition-duration);

/* flex parent */
display: flex;
flex-direction: column;
}

.everything-except-header-ribbon .core .file-details{
margin-right: 0;
width: 100%;
}

.url-bar {
width: 100%;
height: var(--url-bar-height);
margin-bottom: var(--margin);
.query-sidebar {
height: 100%;
width: 30%;
max-width: var(--query-sidebar-max-width);
}

.annotation-hierarchy-and-file-list {
display: flex;
width: 100%;
height: calc(100% - var(--url-bar-height) - var(--margin));
.center {
flex: auto;
height: 100%;
margin: var(--margin) 0 var(--margin) var(--margin);
width: calc(70% - var(--margin));
}

.annotation-hierarchy {
height: 100%;
width: 30%;
max-width: var(--annotation-hierarchy-max-width);
.global-button-row {
height: var(--global-button-row-height);
}

.file-list {
display: flex;
flex-direction: column;
flex: auto;
height: 100%;
width: calc(70% - var(--margin));
margin-left: var(--margin);
height: calc(100% - var(--global-button-row-height));
}

.file-details {
height: 100%;
transition: flex var(--transition-duration);
width: 100%;

/* flex child */
flex: 0 0 var(--file-details-width);
margin: var(--margin) 0 var(--margin) 0;
}
33 changes: 19 additions & 14 deletions packages/core/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import "normalize.css";
import { initializeIcons, loadTheme } from "@fluentui/react";
import classNames from "classnames";
import * as React from "react";
import { batch, useDispatch, useSelector } from "react-redux";

import AnnotationSidebar from "./components/AnnotationSidebar";
import ContextMenu from "./components/ContextMenu";
import Modal from "./components/Modal";
import DirectoryTree from "./components/DirectoryTree";
import FileDetails from "./components/FileDetails";
import FileExplorerURLBar from "./components/FileExplorerURLBar";
import HeaderRibbon from "./components/HeaderRibbon";
import GlobalActionButtonRow from "./components/GlobalActionButtonRow";
import StatusMessage from "./components/StatusMessage";
import TutorialTooltip from "./components/TutorialTooltip";
import QuerySidebar from "./components/QuerySidebar";
import { FileExplorerServiceBaseUrl } from "./constants";
import { interaction, metadata, selection } from "./state";
import { PlatformDependentServices } from "./state/interaction/actions";
Expand Down Expand Up @@ -48,6 +48,8 @@ export default function App(props: AppProps) {
} = props;

const dispatch = useDispatch();
const isDarkTheme = useSelector(selection.selectors.getIsDarkTheme);
const shouldDisplaySmallFont = useSelector(selection.selectors.getShouldDisplaySmallFont);

// Set platform-dependent services in state
React.useEffect(() => {
Expand All @@ -66,19 +68,22 @@ export default function App(props: AppProps) {
}, [dispatch, fileExplorerServiceBaseUrl]);

return (
<div id={ROOT_ELEMENT_ID} className={styles.root}>
<div className={styles.content}>
<HeaderRibbon className={styles.headerRibbon} />
<div className={styles.everythingExceptHeaderRibbon}>
<div className={styles.core}>
<FileExplorerURLBar className={styles.urlBar} />
<div className={styles.annotationHierarchyAndFileList}>
<AnnotationSidebar className={styles.annotationHierarchy} />
<DirectoryTree className={styles.fileList} />
</div>
<div
id={ROOT_ELEMENT_ID}
className={classNames(styles.root, {
[styles.lightTheme]: !isDarkTheme,
[styles.smallFont]: shouldDisplaySmallFont,
})}
>
<div className={styles.coreAndFileDetails}>
<div className={styles.querySidebarAndCenter}>
<QuerySidebar className={styles.querySidebar} />
<div className={styles.center}>
<GlobalActionButtonRow className={styles.globalButtonRow} />
<DirectoryTree className={styles.fileList} />
</div>
<FileDetails className={styles.fileDetails} />
</div>
<FileDetails className={styles.fileDetails} />
</div>
<ContextMenu key={useSelector(interaction.selectors.getContextMenuKey)} />
<StatusMessage />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.container {
background: var(--secondary-brand-purple);
background: var(--primary-background-color);
opacity: 0.90;
border-radius: 3px;
/* Allow the element to be fixed to the bottom of the file list */
position: fixed;
bottom: 10px;
Expand Down
34 changes: 19 additions & 15 deletions packages/core/components/AggregateInfoBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import styles from "./AggregateInfoBox.module.css";

interface AggregateData {
count: number;
size: string;
size?: string;
}

/**
Expand Down Expand Up @@ -42,7 +42,7 @@ export default function AggregateInfoBox() {
fileSelection
);
if (!ignoreResponse) {
setAggregateData({ count, size: filesize(size) });
setAggregateData({ count, size: size ? filesize(size) : undefined });
setLoading(false);
setError(undefined);
}
Expand Down Expand Up @@ -96,19 +96,23 @@ export default function AggregateInfoBox() {
</h6>
</div>
<div className={styles.column}>
<div className={styles.columnData}>
{!isLoading && aggregateData ? (
aggregateData.size
) : (
<Spinner
size={SpinnerSize.small}
data-testid="aggregate-info-box-spinner"
/>
)}
</div>
<h6 className={styles.label}>
Total File <br /> Size
</h6>
{aggregateData?.size && (
<>
<div className={styles.columnData}>
{!isLoading && aggregateData ? (
aggregateData.size
) : (
<Spinner
size={SpinnerSize.small}
data-testid="aggregate-info-box-spinner"
/>
)}
</div>
<h6 className={styles.label}>
Total File <br /> Size
</h6>
</>
)}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,24 @@
import {
configureMockStore,
createMockHttpClient,
mergeState,
ResponseStub,
} from "@aics/redux-utils";
import { configureMockStore, mergeState } from "@aics/redux-utils";
import { render } from "@testing-library/react";
import { expect } from "chai";
import { get as _get } from "lodash";
import React from "react";
import { Provider } from "react-redux";
import { createSandbox } from "sinon";

import FileSelection from "../../../entity/FileSelection";
import FileSet from "../../../entity/FileSet";
import NumericRange from "../../../entity/NumericRange";
import FileService from "../../../services/FileService";
import { SelectionAggregationResult } from "../../../services/FileService";
import FileServiceNoop from "../../../services/FileService/FileServiceNoop";
import { initialState, interaction } from "../../../state";

import AggregateInfoBox from "..";

describe("<AggregateInfoBox />", () => {
const sandbox = createSandbox();
const baseUrl = "test";
const uniqueFileCount = 3413;
const responseStubs: ResponseStub[] = [
{
when: (config) => _get(config, "url", "").includes(FileService.SELECTION_AGGREGATE_URL),
respondWith: {
data: { data: [{ count: uniqueFileCount, size: 3 }] },
},
},
];
const mockHttpClient = createMockHttpClient(responseStubs);
const fileService = new FileService({ baseUrl, httpClient: mockHttpClient });

before(() => {
sandbox.stub(interaction.selectors, "getFileService").returns(fileService);
});

afterEach(() => {
sandbox.resetHistory();
});

after(() => {
sandbox.restore();
});

Expand All @@ -62,6 +38,9 @@ describe("<AggregateInfoBox />", () => {
state: initialState,
});

const mockFileService = new FileServiceNoop();
sandbox.stub(interaction.selectors, "getFileService").returns(mockFileService);

const { getByText, getAllByTestId } = render(
<Provider store={store}>
<AggregateInfoBox />
Expand All @@ -79,6 +58,9 @@ describe("<AggregateInfoBox />", () => {
state,
});

const mockFileService = new FileServiceNoop();
sandbox.stub(interaction.selectors, "getFileService").returns(mockFileService);

const { getAllByTestId } = render(
<Provider store={store}>
<AggregateInfoBox />
Expand All @@ -95,6 +77,14 @@ describe("<AggregateInfoBox />", () => {
state,
});

class MockFileService extends FileServiceNoop {
public async getAggregateInformation(): Promise<SelectionAggregationResult> {
return { size: 3, count: uniqueFileCount };
}
}
const mockFileService = new MockFileService();
sandbox.stub(interaction.selectors, "getFileService").returns(mockFileService);

const { findByText } = render(
<Provider store={store}>
<AggregateInfoBox />
Expand All @@ -112,6 +102,14 @@ describe("<AggregateInfoBox />", () => {
state,
});

class MockFileService extends FileServiceNoop {
public async getAggregateInformation(): Promise<SelectionAggregationResult> {
return { size: 1, count: uniqueFileCount };
}
}
const mockFileService = new MockFileService();
sandbox.stub(interaction.selectors, "getFileService").returns(mockFileService);

const { findByText, findAllByText } = render(
<Provider store={store}>
<AggregateInfoBox />
Expand All @@ -129,6 +127,14 @@ describe("<AggregateInfoBox />", () => {
state,
});

class MockFileService extends FileServiceNoop {
public async getAggregateInformation(): Promise<SelectionAggregationResult> {
return { size: 4, count: uniqueFileCount };
}
}
const mockFileService = new MockFileService();
sandbox.stub(interaction.selectors, "getFileService").returns(mockFileService);

const { findByText } = render(
<Provider store={store}>
<AggregateInfoBox />
Expand Down
Loading

0 comments on commit 008ec55

Please sign in to comment.