Skip to content

Commit

Permalink
Merge pull request #337 from AllenInstitute/feature/add-better-column…
Browse files Browse the repository at this point in the history
…-control

Feature/add better column control
  • Loading branch information
SeanLeRoy authored Nov 22, 2024
2 parents 1262c2c + fb8357e commit 0c4a83f
Show file tree
Hide file tree
Showing 30 changed files with 440 additions and 429 deletions.
5 changes: 0 additions & 5 deletions packages/core/App.module.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
.light-theme {
/* placeholder for until / if we do a light theme for the app */
color: orange;
}

.absolute {
position: absolute;
}
Expand Down
2 changes: 0 additions & 2 deletions packages/core/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export default function App(props: AppProps) {
const dispatch = useDispatch();
const hasQuerySelected = useSelector(selection.selectors.hasQuerySelected);
const requiresDataSourceReload = useSelector(selection.selectors.getRequiresDataSourceReload);
const isDarkTheme = useSelector(selection.selectors.getIsDarkTheme);
const shouldDisplaySmallFont = useSelector(selection.selectors.getShouldDisplaySmallFont);
const platformDependentServices = useSelector(
interaction.selectors.getPlatformDependentServices
Expand Down Expand Up @@ -97,7 +96,6 @@ export default function App(props: AppProps) {
<div
id={ROOT_ELEMENT_ID}
className={classNames(styles.root, props.className, {
[styles.lightTheme]: !isDarkTheme,
[styles.smallFont]: shouldDisplaySmallFont,
})}
ref={measuredNodeRef}
Expand Down
12 changes: 0 additions & 12 deletions packages/core/components/DirectoryTree/DirectoryTree.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,6 @@
position: relative;
}

.container::after {
background-image: linear-gradient(to right, transparent, var(--secondary-background-color));
bottom: 0;
content: " ";
height: 100%;
right: 0;
position: absolute;
pointer-events: none;
width: 60px;
z-index: 11;
}

.filter-display-bar {
flex-shrink: 0;
width: 100%;
Expand Down
16 changes: 14 additions & 2 deletions packages/core/components/DirectoryTree/test/DirectoryTree.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,18 @@ describe("<DirectoryTree />", () => {
(a) => a.name === AnnotationName.FILE_NAME
);
const state = mergeState(initialState, {
metadata: {
annotations: [...baseDisplayAnnotations, fooAnnotation, barAnnotation],
},
interaction: {
fileExplorerServiceBaseUrl: baseUrl,
},
selection: {
annotationHierarchy: [fooAnnotation.name, barAnnotation.name],
displayAnnotations: [...baseDisplayAnnotations, fooAnnotation, barAnnotation],
columns: [...baseDisplayAnnotations, fooAnnotation, barAnnotation].map((a) => ({
name: a.name,
width: 0.1,
})),
},
});

Expand Down Expand Up @@ -353,12 +359,18 @@ describe("<DirectoryTree />", () => {

it("only includes one filter value per annotation for an annotation within the hierarchy", async () => {
const oneAnnotationDeepState = mergeState(initialState, {
metadata: {
annotations: [...baseDisplayAnnotations, fooAnnotation, barAnnotation],
},
interaction: {
fileExplorerServiceBaseUrl: baseUrl,
},
selection: {
annotationHierarchy: [fooAnnotation.name],
displayAnnotations: [...baseDisplayAnnotations, fooAnnotation, barAnnotation],
columns: [...baseDisplayAnnotations, fooAnnotation, barAnnotation].map((a) => ({
name: a.name,
width: 0.1,
})),
},
});

Expand Down
8 changes: 4 additions & 4 deletions packages/core/components/EmptyFileListMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ export default function EmptyFileListMessage() {
<div className={styles.emptyFileListContainer}>
<div className={styles.emptyFileListMessage}>
<Icon className={styles.emptySearchIcon} iconName="SearchIssue" />
<h2>Sorry! No files found</h2>
<h2>No files match your query</h2>
<br />
<div>We couldn&apos;t find any files matching your request.</div>
<div>Double check your filters for any issues.</div>
<br />
<div>
Double check your filters for any issues and then contact the software team via
Contact us via
<a
className={styles.link}
href="https://github.com/AllenInstitute/biofile-finder/issues"
Expand All @@ -22,7 +22,7 @@ export default function EmptyFileListMessage() {
>
&nbsp;GitHub&nbsp;
</a>
if you still expect there to be matches present.
if you expect there should be matches present for this query.
</div>
</div>
</div>
Expand Down
32 changes: 17 additions & 15 deletions packages/core/components/FileList/ColumnPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,33 @@ import * as React from "react";
import { useSelector, useDispatch } from "react-redux";

import AnnotationPicker from "../AnnotationPicker";
import { metadata, selection } from "../../state";
import { selection } from "../../state";

/**
* Picker for selecting which columns to display in the file list.
*/
export default function ColumnPicker() {
const dispatch = useDispatch();
const annotations = useSelector(metadata.selectors.getAnnotations);
const columnAnnotations = useSelector(selection.selectors.getAnnotationsToDisplay);
const columns = useSelector(selection.selectors.getColumns);
const columnNames = useSelector(selection.selectors.getColumnNames);

return (
<AnnotationPicker
title="Select metadata to display as columns"
selections={columnAnnotations.map((c) => c.name)}
setSelections={(selectedAnnotations) => {
// Prevent de-selecting all columns
if (!selectedAnnotations.length) {
dispatch(selection.actions.setDisplayAnnotations([columnAnnotations[0]]));
} else {
dispatch(
selection.actions.setDisplayAnnotations(
annotations.filter((a) => selectedAnnotations.includes(a.name))
)
);
}
selections={columnNames}
setSelections={(selectedColumns) => {
const adjustedColumns = columns.filter((column) =>
selectedColumns.includes(column.name)
);
selectedColumns.forEach((selectedColumn) => {
if (!columnNames.includes(selectedColumn)) {
adjustedColumns.push({
name: selectedColumn,
width: 0.25, // Default width of 25%
});
}
});
dispatch(selection.actions.setColumns(adjustedColumns));
}}
/>
);
Expand Down
12 changes: 12 additions & 0 deletions packages/core/components/FileList/FileList.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@
height: calc(100% - 3px);
}

.horizontal-overflow::after {
background-image: linear-gradient(to right, transparent, var(--secondary-background-color));
bottom: 0;
content: " ";
height: 100%;
right: 0;
position: absolute;
pointer-events: none;
width: 60px;
z-index: 11;
}

.row-count-display {
color: var(--secondary-text-color);
opacity: 0.8;
Expand Down
59 changes: 28 additions & 31 deletions packages/core/components/FileList/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,37 @@ function Header(
const annotationNameToAnnotationMap = useSelector(
metadata.selectors.getAnnotationNameToAnnotationMap
);
const columnAnnotations = useSelector(selection.selectors.getAnnotationsToDisplay);
const columnWidths = useSelector(selection.selectors.getColumnWidths);
const columns = useSelector(selection.selectors.getColumns);
const sortColumn = useSelector(selection.selectors.getSortColumn);

const onResize = (columnKey: string, nextWidthPercent?: number) => {
if (nextWidthPercent) {
dispatch(selection.actions.resizeColumn(columnKey, nextWidthPercent));
} else {
dispatch(selection.actions.resetColumnWidth(columnKey));
}
const onResize = (name: string, width?: number) => {
// Default to 0.25 if width is undefined
// which resets the column width to the default
dispatch(selection.actions.resizeColumn({ name, width: width || 0.25 }));
};
const headerCells: CellConfig[] = map(columnAnnotations, (annotation) => {
const isSortedColumn = sortColumn?.annotationName === annotation.name;
return {
columnKey: annotation.name, // needs to match the value used to produce `column`s passed to the `useResizableColumns` hook
displayValue: (
<span
className={styles.headerCell}
onClick={() => dispatch(selection.actions.sortColumn(annotation.name))}
>
<Tooltip content={annotationNameToAnnotationMap[annotation.name]?.description}>
<span className={styles.headerTitle}>{annotation.displayName}</span>
</Tooltip>
{isSortedColumn &&
(sortColumn?.order === SortOrder.DESC ? (
<Icon className={styles.sortIcon} iconName="ChevronDown" />
) : (
<Icon className={styles.sortIcon} iconName="ChevronUp" />
))}
</span>
),
width: columnWidths[annotation.name] || 1 / columnAnnotations.length,
};
});
const headerCells: CellConfig[] = map(columns, (column) => ({
// needs to match the value used to produce `column`s passed to the `useResizableColumns` hook
columnKey: column.name,
displayValue: (
<span
className={styles.headerCell}
onClick={() => dispatch(selection.actions.sortColumn(column.name))}
>
<Tooltip content={annotationNameToAnnotationMap[column.name]?.description}>
<span className={styles.headerTitle}>
{annotationNameToAnnotationMap[column.name]?.displayName}
</span>
</Tooltip>
{sortColumn?.annotationName === column.name &&
(sortColumn?.order === SortOrder.DESC ? (
<Icon className={styles.sortIcon} iconName="ChevronDown" />
) : (
<Icon className={styles.sortIcon} iconName="ChevronUp" />
))}
</span>
),
width: column.width,
}));

const onHeaderColumnContextMenu = (evt: React.MouseEvent) => {
evt.preventDefault();
Expand Down
16 changes: 9 additions & 7 deletions packages/core/components/FileList/LazilyRenderedRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useSelector } from "react-redux";

import FileRow from "../../components/FileRow";
import FileSet from "../../entity/FileSet";
import { selection } from "../../state";
import { metadata, selection } from "../../state";
import { OnSelect } from "./useFileSelector";

import styles from "./LazilyRenderedRow.module.css";
Expand Down Expand Up @@ -39,9 +39,11 @@ export default function LazilyRenderedRow(props: LazilyRenderedRowProps) {
style,
} = props;

const columns = useSelector(selection.selectors.getColumns);
const isSmallFont = useSelector(selection.selectors.getShouldDisplaySmallFont);
const annotations = useSelector(selection.selectors.getAnnotationsToDisplay);
const columnWidths = useSelector(selection.selectors.getColumnWidths);
const annotationNameToAnnotationMap = useSelector(
metadata.selectors.getAnnotationNameToAnnotationMap
);
const fileSelection = useSelector(selection.selectors.getFileSelection);

const file = fileSet.getFileByIndex(index);
Expand All @@ -62,10 +64,10 @@ export default function LazilyRenderedRow(props: LazilyRenderedRowProps) {
if (file) {
content = (
<FileRow
cells={map(annotations, (annotation) => ({
columnKey: annotation.name,
displayValue: annotation.extractFromFile(file),
width: columnWidths[annotation.name] || 1 / annotations.length,
cells={map(columns, (column) => ({
columnKey: column.name,
displayValue: annotationNameToAnnotationMap[column.name]?.extractFromFile(file),
width: column.width,
}))}
rowIdentifier={{ index, id: file.uid }}
onSelect={onSelect}
Expand Down
12 changes: 6 additions & 6 deletions packages/core/components/FileList/LazilyRenderedThumbnail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { useSelector } from "react-redux";

import { OnSelect } from "./useFileSelector";
import Tooltip from "../Tooltip";
import FileSet from "../../entity/FileSet";
import FileThumbnail from "../../components/FileThumbnail";
import { THUMBNAIL_SIZE_TO_NUM_COLUMNS } from "../../constants";
import { FileView } from "../../entity/FileExplorerURL";
import FileSet from "../../entity/FileSet";
import { selection } from "../../state";

import styles from "./LazilyRenderedThumbnail.module.css";
Expand Down Expand Up @@ -48,7 +48,8 @@ export default function LazilyRenderedThumbnail(props: LazilyRenderedThumbnailPr

const shouldDisplaySmallFont = useSelector(selection.selectors.getShouldDisplaySmallFont);
const fileSelection = useSelector(selection.selectors.getFileSelection);
const fileGridColCount = useSelector(selection.selectors.getFileGridColumnCount);
const fileView = useSelector(selection.selectors.getFileView);
const fileGridColCount = useSelector(selection.selectors.getFileGridColCount);
const overallIndex = fileGridColCount * rowIndex + columnIndex;
const file = fileSet.getFileByIndex(overallIndex);
const thumbnailSize = measuredWidth / fileGridColCount - 2 * MARGIN;
Expand Down Expand Up @@ -92,7 +93,7 @@ export default function LazilyRenderedThumbnail(props: LazilyRenderedThumbnailPr

// Display the start of the file name and at least part of the file type
const clipFileName = (filename: string) => {
if (fileGridColCount === THUMBNAIL_SIZE_TO_NUM_COLUMNS.SMALL && filename.length > 15) {
if (fileView === FileView.SMALL_THUMBNAIL && filename.length > 15) {
return filename.slice(0, 6) + "..." + filename.slice(-4);
} else if (filename.length > 20) {
return filename.slice(0, 9) + "..." + filename.slice(-8);
Expand Down Expand Up @@ -123,8 +124,7 @@ export default function LazilyRenderedThumbnail(props: LazilyRenderedThumbnailPr
<div
className={classNames(styles.thumbnailLabel, {
[styles.smallFont]:
shouldDisplaySmallFont ||
fileGridColCount === THUMBNAIL_SIZE_TO_NUM_COLUMNS.SMALL,
shouldDisplaySmallFont || fileView === FileView.SMALL_THUMBNAIL,
})}
>
{filenameForRender}
Expand Down
Loading

0 comments on commit 0c4a83f

Please sign in to comment.