Skip to content

Commit

Permalink
Address review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
mattrunyon committed Mar 15, 2023
1 parent e38ebbf commit e1fcc6b
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 138 deletions.
4 changes: 3 additions & 1 deletion packages/components/src/DateTimeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ function fixIncompleteValue(value: string): string {
return value;
}

const removeSeparators = (value: string) => value.replace(/\u200B/g, '');
function removeSeparators(value: string): string {
return value.replace(/\u200B/g, '');
}

const EXAMPLES = [addSeparators(DEFAULT_VALUE_STRING)];

Expand Down
131 changes: 4 additions & 127 deletions packages/file-explorer/src/FileList.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import {
ItemList,
Range,
RenderItemProps,
Tooltip,
} from '@deephaven/components';
import { dhPython, vsCode, vsFolder, vsFolderOpened } from '@deephaven/icons';
import { ItemList, Range } from '@deephaven/components';
import Log from '@deephaven/log';
import { RangeUtils } from '@deephaven/utils';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
import classNames from 'classnames';
import React, {
useCallback,
Expand All @@ -19,12 +11,8 @@ import React, {
} from 'react';
import { FileStorageItem, FileStorageTable, isDirectory } from './FileStorage';
import './FileList.scss';
import FileUtils, { MIME_TYPE } from './FileUtils';
import {
DEFAULT_ROW_HEIGHT,
getMoveOperation,
getPathFromItem,
} from './FileListUtils';
import { DEFAULT_ROW_HEIGHT, getMoveOperation } from './FileListUtils';
import { FileListItem, FileListRenderItemProps } from './FileListItem';

const log = Log.module('FileList');

Expand All @@ -39,19 +27,6 @@ export type ListViewport = {
bottom: number;
};

export type FileListRenderItemProps = RenderItemProps<FileStorageItem> & {
children?: JSX.Element;
dropTargetItem?: FileStorageItem;
draggedItems?: FileStorageItem[];
isDragInProgress: boolean;
isDropTargetValid: boolean;

onDragStart(index: number, e: React.DragEvent<HTMLDivElement>): void;
onDragOver(index: number, e: React.DragEvent<HTMLDivElement>): void;
onDragEnd(index: number, e: React.DragEvent<HTMLDivElement>): void;
onDrop(index: number, e: React.DragEvent<HTMLDivElement>): void;
};

export interface FileListProps {
table: FileStorageTable;

Expand All @@ -76,104 +51,6 @@ const DRAG_HOVER_TIMEOUT = 500;

const ITEM_LIST_CLASS_NAME = 'item-list-scroll-pane';

export function RenderFileListItem(
props: FileListRenderItemProps
): JSX.Element {
const {
children,
draggedItems,
isDragInProgress,
isDropTargetValid,
isSelected,
item,
itemIndex,
dropTargetItem,
onDragStart,
onDragOver,
onDragEnd,
onDrop,
} = props;

const isDragged =
draggedItems?.some(draggedItem => draggedItem.id === item.id) ?? false;
const itemPath = getPathFromItem(item);
const dropTargetPath =
isDragInProgress && dropTargetItem ? getPathFromItem(dropTargetItem) : null;

const isExactDropTarget =
isDragInProgress &&
isDropTargetValid &&
isDirectory(item) &&
dropTargetPath === itemPath;
const isInDropTarget =
isDragInProgress && isDropTargetValid && dropTargetPath === itemPath;
const isInvalidDropTarget =
isDragInProgress && !isDropTargetValid && dropTargetPath === itemPath;

const icon = getItemIcon(item);
const depth = FileUtils.getDepth(item.filename);
const depthLines = Array(depth)
.fill(null)
.map((value, index) => (
// eslint-disable-next-line react/no-array-index-key
<span className="file-list-depth-line" key={index} />
));

return (
<div
className={classNames(
'd-flex w-100 align-items-center',
'file-list-item',
{
'is-dragged': isDragged,
'is-exact-drop-target': isExactDropTarget,
'is-in-drop-target': isInDropTarget,
'is-invalid-drop-target': isInvalidDropTarget,
'is-selected': isSelected,
}
)}
onDragStart={e => onDragStart(itemIndex, e)}
onDragOver={e => onDragOver(itemIndex, e)}
onDragEnd={e => onDragEnd(itemIndex, e)}
onDrop={e => onDrop(itemIndex, e)}
draggable
role="presentation"
aria-label={item.basename}
>
{depthLines}{' '}
<FontAwesomeIcon icon={icon} className="item-icon" fixedWidth />{' '}
<span className="truncation-wrapper">
{children ?? item.basename}
<Tooltip
options={{
placement: 'left',
}}
>
{children ?? item.basename}
</Tooltip>
</span>
</div>
);
}

/**
* Get the icon definition for a file or folder item
* @param item Item to get the icon for
* @returns Icon definition to pass in the FontAwesomeIcon icon prop
*/
function getItemIcon(item: FileStorageItem): IconDefinition {
if (isDirectory(item)) {
return item.isExpanded ? vsFolderOpened : vsFolder;
}
const mimeType = FileUtils.getMimeType(item.basename);
switch (mimeType) {
case MIME_TYPE.PYTHON:
return dhPython;
default:
return vsCode;
}
}

/**
* Component that displays and allows interaction with the file system in the provided FileStorageTable.
*/
Expand All @@ -185,7 +62,7 @@ export function FileList(props: FileListProps): JSX.Element {
onMove,
onSelect,
onSelectionChange = () => undefined,
renderItem = RenderFileListItem,
renderItem = FileListItem,
rowHeight = DEFAULT_ROW_HEIGHT,
overscanCount = ItemList.DEFAULT_OVERSCAN,
} = props;
Expand Down
19 changes: 9 additions & 10 deletions packages/file-explorer/src/FileListContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { ContextAction, ContextActions } from '@deephaven/components';
import { assertNotNull } from '@deephaven/utils';
import React, { useCallback, useMemo, useState } from 'react';
import FileList, {
RenderFileListItem,
FileListRenderItemProps,
} from './FileList';
import FileList from './FileList';
import { FileListItem, FileListRenderItemProps } from './FileListItem';
import { DEFAULT_ROW_HEIGHT } from './FileListUtils';
import { FileStorageItem, FileStorageTable, isDirectory } from './FileStorage';
import SHORTCUTS from './FileExplorerShortcuts';
Expand Down Expand Up @@ -191,19 +189,20 @@ export function FileListContainer(props: FileListContainerProps): JSX.Element {
(itemProps: FileListRenderItemProps): JSX.Element => {
const { item } = itemProps;
if (renameItem && renameItem.filename === item.filename) {
return RenderFileListItem({
...itemProps,
children: (
return (
// eslint-disable-next-line react/jsx-props-no-spreading
<FileListItem {...itemProps}>
<FileListItemEditor
item={item}
validate={validateRenameItem}
onSubmit={handleRenameSubmit}
onCancel={handleRenameCancel}
/>
),
});
</FileListItem>
);
}
return RenderFileListItem(itemProps);
// eslint-disable-next-line react/jsx-props-no-spreading
return <FileListItem {...itemProps} />;
},
[handleRenameCancel, handleRenameSubmit, renameItem, validateRenameItem]
);
Expand Down
121 changes: 121 additions & 0 deletions packages/file-explorer/src/FileListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React from 'react';
import { Tooltip, RenderItemProps } from '@deephaven/components';
import { dhPython, vsCode, vsFolder, vsFolderOpened } from '@deephaven/icons';
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import classNames from 'classnames';
import { FileStorageItem, isDirectory } from './FileStorage';
import './FileList.scss';
import FileUtils, { MIME_TYPE } from './FileUtils';
import { getPathFromItem } from './FileListUtils';

/**
* Get the icon definition for a file or folder item
* @param item Item to get the icon for
* @returns Icon definition to pass in the FontAwesomeIcon icon prop
*/
function getItemIcon(item: FileStorageItem): IconDefinition {
if (isDirectory(item)) {
return item.isExpanded ? vsFolderOpened : vsFolder;
}
const mimeType = FileUtils.getMimeType(item.basename);
switch (mimeType) {
case MIME_TYPE.PYTHON:
return dhPython;
default:
return vsCode;
}
}

export type FileListRenderItemProps = RenderItemProps<FileStorageItem> & {
children?: JSX.Element;
dropTargetItem?: FileStorageItem;
draggedItems?: FileStorageItem[];
isDragInProgress: boolean;
isDropTargetValid: boolean;

onDragStart(index: number, e: React.DragEvent<HTMLDivElement>): void;
onDragOver(index: number, e: React.DragEvent<HTMLDivElement>): void;
onDragEnd(index: number, e: React.DragEvent<HTMLDivElement>): void;
onDrop(index: number, e: React.DragEvent<HTMLDivElement>): void;
};

export function FileListItem(props: FileListRenderItemProps): JSX.Element {
const {
children,
draggedItems,
isDragInProgress,
isDropTargetValid,
isSelected,
item,
itemIndex,
dropTargetItem,
onDragStart,
onDragOver,
onDragEnd,
onDrop,
} = props;

const isDragged =
draggedItems?.some(draggedItem => draggedItem.id === item.id) ?? false;
const itemPath = getPathFromItem(item);
const dropTargetPath =
isDragInProgress && dropTargetItem ? getPathFromItem(dropTargetItem) : null;

const isExactDropTarget =
isDragInProgress &&
isDropTargetValid &&
isDirectory(item) &&
dropTargetPath === itemPath;
const isInDropTarget =
isDragInProgress && isDropTargetValid && dropTargetPath === itemPath;
const isInvalidDropTarget =
isDragInProgress && !isDropTargetValid && dropTargetPath === itemPath;

const icon = getItemIcon(item);
const depth = FileUtils.getDepth(item.filename);
const depthLines = Array(depth)
.fill(null)
.map((value, index) => (
// eslint-disable-next-line react/no-array-index-key
<span className="file-list-depth-line" key={index} />
));

return (
<div
className={classNames(
'd-flex w-100 align-items-center',
'file-list-item',
{
'is-dragged': isDragged,
'is-exact-drop-target': isExactDropTarget,
'is-in-drop-target': isInDropTarget,
'is-invalid-drop-target': isInvalidDropTarget,
'is-selected': isSelected,
}
)}
onDragStart={e => onDragStart(itemIndex, e)}
onDragOver={e => onDragOver(itemIndex, e)}
onDragEnd={e => onDragEnd(itemIndex, e)}
onDrop={e => onDrop(itemIndex, e)}
draggable
role="presentation"
aria-label={item.basename}
>
{depthLines}{' '}
<FontAwesomeIcon icon={icon} className="item-icon" fixedWidth />{' '}
<span className="truncation-wrapper">
{children ?? item.basename}
<Tooltip
options={{
placement: 'left',
}}
>
{children ?? item.basename}
</Tooltip>
</span>
</div>
);
}

export default FileListItem;
1 change: 1 addition & 0 deletions packages/file-explorer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import FileExplorer from './FileExplorer';
export * from './FileExplorer';
export * from './FileListContainer';
export * from './FileList';
export * from './FileListItem';
export * from './FileListUtils';
export * from './FileStorage';
export { default as FileExistsError } from './FileExistsError';
Expand Down

0 comments on commit e1fcc6b

Please sign in to comment.