Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add better column control #337

Merged
merged 10 commits into from
Nov 22, 2024
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 query.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe 'for this query'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof will there ever be a day I don't have a typo

</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
Loading