Skip to content

Commit

Permalink
optimize code
Browse files Browse the repository at this point in the history
  • Loading branch information
zhouwenxuan authored and zhouwenxuan committed Dec 13, 2024
1 parent e385ec6 commit 3622729
Show file tree
Hide file tree
Showing 13 changed files with 189 additions and 326 deletions.
Original file line number Diff line number Diff line change
@@ -1,50 +1,18 @@
import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import React, { useState, useRef, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import { gettext } from '../../../../utils/constants';
import './index.css';

const OPERATION = {
DOWNLOAD: 'download',
DELETE: 'delete',
};

const ContextMenu = ({ getContentRect, getContainerRect, onDownload, onDelete }) => {
const ContextMenu = ({ options, getContainerRect, getContentRect, onOptionClick, validTargets }) => {
const menuRef = useRef(null);
const [visible, setVisible] = useState(false);
const [position, setPosition] = useState({ top: 0, left: 0 });

const options = useMemo(() => {
if (!visible) return [];
return [
{ value: OPERATION.DOWNLOAD, label: gettext('Download') },
{ value: OPERATION.DELETE, label: gettext('Delete') }
];
}, [visible]);

const handleHide = useCallback((event) => {
if (menuRef.current && !menuRef.current.contains(event.target)) {
setVisible(false);
}
}, [menuRef]);

const handleOptionClick = useCallback((event, option) => {
event.stopPropagation();
switch (option.value) {
case OPERATION.DOWNLOAD: {
onDownload && onDownload();
break;
}
case OPERATION.DELETE: {
onDelete && onDelete();
break;
}
default: {
break;
}
}
setVisible(false);
}, [onDownload, onDelete]);

const getMenuPosition = useCallback((x = 0, y = 0) => {
let menuStyles = {
top: y,
Expand Down Expand Up @@ -72,17 +40,22 @@ const ContextMenu = ({ getContentRect, getContainerRect, onDownload, onDelete })
return menuStyles;
}, [getContentRect, getContainerRect]);

const handleOptionClick = useCallback((event, option) => {
event.stopPropagation();
onOptionClick(option);
setVisible(false);
}, [onOptionClick]);

useEffect(() => {
const handleShow = (event) => {
event.preventDefault();
if (menuRef.current && menuRef.current.contains(event.target)) return;

if (event.target.tagName.toLowerCase() !== 'img') {
if (validTargets && !validTargets.some(target => event.target.closest(target))) {
return;
}

setVisible(true);

const position = getMenuPosition(event.clientX, event.clientY);
setPosition(position);
};
Expand All @@ -92,8 +65,7 @@ const ContextMenu = ({ getContentRect, getContainerRect, onDownload, onDelete })
return () => {
document.removeEventListener('contextmenu', handleShow);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [getMenuPosition, validTargets]);

useEffect(() => {
if (visible) {
Expand All @@ -113,14 +85,14 @@ const ContextMenu = ({ getContentRect, getContainerRect, onDownload, onDelete })
return (
<div
ref={menuRef}
className='dropdown-menu sf-metadata-contextmenu'
className="dropdown-menu sf-metadata-contextmenu"
style={position}
>
{options.map((option, index) => (
<button
key={index}
className='dropdown-item sf-metadata-contextmenu-item'
onClick={(event) => handleOptionClick(event, option)}
className="dropdown-item sf-metadata-contextmenu-item"
onClick={(e) => handleOptionClick(e, option)}
>
{option.label}
</button>
Expand All @@ -130,10 +102,14 @@ const ContextMenu = ({ getContentRect, getContainerRect, onDownload, onDelete })
};

ContextMenu.propTypes = {
getContentRect: PropTypes.func.isRequired,
options: PropTypes.arrayOf(PropTypes.shape({
value: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
})).isRequired,
getContainerRect: PropTypes.func.isRequired,
onDownload: PropTypes.func,
onDelete: PropTypes.func,
getContentRect: PropTypes.func.isRequired,
onOptionClick: PropTypes.func.isRequired,
validTargets: PropTypes.array,
};

export default ContextMenu;
31 changes: 30 additions & 1 deletion frontend/src/metadata/utils/row/core.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { siteRoot } from '../../../utils/constants';
import { Utils } from '../../../utils/utils';
import { PRIVATE_COLUMN_KEY } from '../../constants';
import { getFileNameFromRecord, getParentDirFromRecord } from '../cell';
import { getTableById } from '../table';

/**
Expand Down Expand Up @@ -26,7 +29,7 @@ const updateTableRowsWithRowsData = (tables, tableId, recordsData = []) => {
});
};

export const checkIsDir = (record) => {
const checkIsDir = (record) => {
if (!record) return false;
const isDir = record[PRIVATE_COLUMN_KEY.IS_DIR];
if (typeof isDir === 'string') {
Expand All @@ -35,7 +38,33 @@ export const checkIsDir = (record) => {
return isDir;
};

const openInNewTab = (record) => {
const repoID = window.sfMetadataStore.repoId;
const isDir = checkIsDir(record);
const parentDir = getParentDirFromRecord(record);
const name = getFileNameFromRecord(record);
const url = isDir
? window.location.origin + window.location.pathname + Utils.encodePath(Utils.joinPath(parentDir, name))
: `${siteRoot}lib/${repoID}/file${Utils.encodePath(Utils.joinPath(parentDir, name))}`;

window.open(url, '_blank');
};

const openParentFolder = (record) => {
let parentDir = getParentDirFromRecord(record);

if (window.location.pathname.endsWith('/')) {
parentDir = parentDir.slice(1);
}

const url = window.location.origin + window.location.pathname + Utils.encodePath(parentDir);
window.open(url, '_blank');
};

export {
isTableRows,
updateTableRowsWithRowsData,
checkIsDir,
openInNewTab,
openParentFolder,
};
2 changes: 2 additions & 0 deletions frontend/src/metadata/utils/row/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ export {
checkIsDir,
isTableRows,
updateTableRowsWithRowsData,
openInNewTab,
openParentFolder,
} from './core';
41 changes: 35 additions & 6 deletions frontend/src/metadata/views/gallery/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ import metadataAPI from '../../api';
import URLDecorator from '../../../utils/url-decorator';
import toaster from '../../../components/toast';
import Content from './content';
import ContextMenu from './context-menu';
import ImageDialog from '../../../components/dialog/image-dialog';
import ZipDownloadDialog from '../../../components/dialog/zip-download-dialog';
import ModalPortal from '../../../components/modal-portal';
import { useMetadataView } from '../../hooks/metadata-view';
import { Utils } from '../../../utils/utils';
import { getDateDisplayString, getFileNameFromRecord, getParentDirFromRecord } from '../../utils/cell';
import { siteRoot, fileServerRoot, useGoFileserver, thumbnailSizeForGrid, thumbnailSizeForOriginal } from '../../../utils/constants';
import { siteRoot, fileServerRoot, useGoFileserver, thumbnailSizeForGrid, thumbnailSizeForOriginal, gettext } from '../../../utils/constants';
import { EVENT_BUS_TYPE, PRIVATE_COLUMN_KEY, GALLERY_DATE_MODE, DATE_TAG_HEIGHT, GALLERY_IMAGE_GAP } from '../../constants';
import { getRowById } from '../../utils/table';
import { getEventClassName } from '../../utils/common';
import ContextMenu from '../../components/context-menu';

import './index.css';

Expand Down Expand Up @@ -340,6 +340,34 @@ const Main = ({ isLoadingMore, metadata, onDelete, onLoadMore }) => {
}
}, [handleImageSelection, updateSelectedImage]);

const options = useMemo(() => {
return [
{ value: 'download', label: gettext('Download') },
{ value: 'delete', label: gettext('Delete') }
];
}, []);

const handleOptionClick = useCallback(option => {
switch (option.value) {
case 'download':
handleDownload();
break;
case 'delete':
handleDelete();
break;
default:
break;
}
}, [handleDownload, handleDelete]);

const getContainerRect = useCallback(() => {
return containerRef.current.getBoundingClientRect();
}, []);

const getContentRect = useCallback(() => {
return containerRef.current.getBoundingClientRect();
}, []);

return (
<>
<div
Expand Down Expand Up @@ -372,10 +400,11 @@ const Main = ({ isLoadingMore, metadata, onDelete, onLoadMore }) => {
)}
</div>
<ContextMenu
getContentRect={() => containerRef.current.getBoundingClientRect()}
getContainerRect={() => containerRef.current.getBoundingClientRect()}
onDownload={handleDownload}
onDelete={handleDelete}
options={options}
onOptionClick={handleOptionClick}
getContainerRect={getContainerRect}
getContentRect={getContentRect}
validTargets={['.metadata-gallery-image-item', '.metadata-gallery-grid-image']}
/>
{isImagePopupOpen && (
<ModalPortal>
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/metadata/views/kanban/boards/board/card/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const Card = ({
displayColumns,
onOpenFile,
onSelectCard,
onRightClick,
onContextMenu,
}) => {
const titleValue = getCellValueByColumn(record, titleColumn);

Expand All @@ -42,7 +42,7 @@ const Card = ({
data-id={record._id}
className={classnames('sf-metadata-kanban-card', { 'selected': isSelected })}
onClick={handleClickCard}
onContextMenu={onRightClick}
onContextMenu={onContextMenu}
>
{titleColumn && (
<div className="sf-metadata-kanban-card-header" onClick={handleClickFilename}>
Expand Down Expand Up @@ -84,7 +84,7 @@ Card.propTypes = {
displayColumns: PropTypes.array,
onOpenFile: PropTypes.func.isRequired,
onSelectCard: PropTypes.func.isRequired,
onRightClick: PropTypes.func.isRequired,
onContextMenu: PropTypes.func.isRequired,
};

export default Card;
6 changes: 3 additions & 3 deletions frontend/src/metadata/views/kanban/boards/board/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Board = ({
onOpenFile,
onSelectCard,
updateDragging,
onRightClick,
onContextMenu,
}) => {
const [isDraggingOver, setDraggingOver] = useState(false);
const boardName = useMemo(() => `sf_metadata_kanban_board_${board.key}`, [board]);
Expand Down Expand Up @@ -94,7 +94,7 @@ const Board = ({
displayColumns={displayColumns}
onOpenFile={onOpenFile}
onSelectCard={onSelectCard}
onRightClick={(e) => onRightClick(e, recordId)}
onContextMenu={(e) => onContextMenu(e, recordId)}
/>
);
if (readonly) return CardElement;
Expand Down Expand Up @@ -127,7 +127,7 @@ Board.propTypes = {
onOpenFile: PropTypes.func.isRequired,
onSelectCard: PropTypes.func.isRequired,
updateDragging: PropTypes.func.isRequired,
onRightClick: PropTypes.func,
onContextMenu: PropTypes.func,
};

export default Board;
Loading

0 comments on commit 3622729

Please sign in to comment.