Skip to content

Commit

Permalink
implement context menu component for metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
Aries-0331 committed Aug 7, 2024
1 parent 59700b2 commit 009f721
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.context-menu {
position: fixed;
min-width: 12rem;
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 0.875rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 40, 100, 0.12);
border-radius: 3px;
box-shadow: 0 0 5px #ccc;
z-index: 1000;
}

.context-menu .context-menu-item {
line-height: 1.5;
cursor: pointer;
min-height: 28px;
font-weight: 400;
color: #373a3c;
text-align: inherit;
white-space: nowrap;
background: 0 0;
border: 0;
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
}

.context-menu .context-menu-item:hover {
color: #fff;
background-color: #20a0ff;
border-color: #20a0ff;
text-decoration: none;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import './context-menu.css';

const ContextMenu = ({ position, options, onOptionClick, visible, onCloseContextMenu }) => {
const menuRef = useRef(null);

useEffect(() => {
const handleCloseContextMenu = (event) => {
if (menuRef.current && !menuRef.current.contains(event.target)) {
onCloseContextMenu();
}
};

if (visible) {
document.addEventListener('mousedown', handleCloseContextMenu);
}

return () => {
document.removeEventListener('mousedown', handleCloseContextMenu);
};
}, [visible, onCloseContextMenu]);

if (!visible) return null;

return (
<ul
ref={menuRef}
className='context-menu'
style={{
top: position.y,
left: position.x,
}}
>
{options.map((option, index) => (
<li
key={index}
className='context-menu-item'
onClick={(event) => onOptionClick(event, option)}
>
{option.label}
</li>
))}
</ul>
);
};

ContextMenu.propTypes = {
position: PropTypes.shape({
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired,
}).isRequired,
options: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
})
).isRequired,
onOptionClick: PropTypes.func.isRequired,
visible: PropTypes.bool.isRequired,
};

export default ContextMenu;
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ class RecordsBody extends Component {
onCellMouseMove: this.onCellMouseMove,
onDragEnter: this.handleDragEnter,
modifyRecord: this.props.modifyRecord,
onContextMenu: this.props.onFileNameContextMenu
onContextMenu: this.props.onContextMenu
};
return this.cellMetaData;
};
Expand Down Expand Up @@ -601,7 +601,7 @@ RecordsBody.propTypes = {
openDownloadFilesDialog: PropTypes.func,
cacheDownloadFilesProps: PropTypes.func,
onRowExpand: PropTypes.func,
onFileNameContextMenu: PropTypes.func,
onContextMenu: PropTypes.func,
};

export default RecordsBody;
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@ import RecordMetrics from '../../../../utils/record-metrics';
import { isShiftKeyDown } from '../../../../utils/keyboard-utils';
import { getVisibleBoundaries } from '../../../../utils/viewport';
import { getColOverScanEndIdx, getColOverScanStartIdx } from '../../../../utils/grid';
import { hideMenu, showMenu } from '../../../../../../components/context-menu/actions';
import ContextMenu from '../../../../../../components/context-menu/context-menu';
import TextTranslation from '../../../../../../utils/text-translation';
import { Utils } from '../../../../../../utils/utils';
import { siteRoot } from '../../../../../../utils/constants';

const METADATA_RECORD_CONTEXT_MENU = 'metadata-record-context-menu';
import ContextMenu from '../../../context-menu/context-menu';

class Records extends Component {

Expand All @@ -46,11 +43,17 @@ class Records extends Component {
bottomRight: this.initPosition,
},
selectedPosition: this.initPosition,
contextMenuPosition: { x: 0, y: 0 },
isContextMenuVisible: false,
...initHorizontalScrollState,
};
this.isWindows = isWindowsBrowser();
this.isWebkit = isWebkitBrowser();
this.baseURI = '';
this.contextMenuOptions = [
{ label: TextTranslation.OPEN_FILE_IN_NEW_TAB.value, value: 'openFileInNewTab' },
{ label: TextTranslation.OPEN_PARENT_FOLDER.value, value: 'openParentFolder' },
];
}

componentDidMount() {
Expand Down Expand Up @@ -603,18 +606,14 @@ class Records extends Component {
const record = this.props.recordGetter(rowIdx);
const repoID = window.sfMetadataStore.repoId;

let url;
if (record._is_dir) {
let url;
if (record._parent_dir === '/') {
url = this.baseURI + record._parent_dir + record._name;
} else {
url = this.baseURI + record._parent_dir + '/' + record._name;
}
window.open(url, '_blank');
url = `${this.baseURI}${record._parent_dir === '/' ? '' : record._parent_dir + '/'}${record._name}`;
} else {
const url = siteRoot + 'lib/' + repoID + '/file' + Utils.encodePath(record._parent_dir + '/' + record._name);
window.open(url, '_blank');
url = `${siteRoot}lib/${repoID}/file${Utils.encodePath(record._parent_dir + '/' + record._name)}`;
}

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

onOpenParentFolder = (event) => {
Expand All @@ -628,73 +627,46 @@ class Records extends Component {
location.href = url;
};

onMenuItemClick = (operation, obj, event) => {
hideMenu();
switch (operation) {
case 'Open file in new tab':
this.onOpenInNewTab(event);
return;
case 'Open parent folder':
this.onOpenParentFolder(event);
return;
default:
return;
}
};

getMenuList = () => {
const { OPEN_FILE_IN_NEW_TAB, OPEN_PARENT_FOLDER } = TextTranslation;
return [OPEN_FILE_IN_NEW_TAB, OPEN_PARENT_FOLDER];
};

handleContextMenu = (event, id, menuList, currentObject = null) => {
event.preventDefault();
event.stopPropagation();

let x = event.clientX || (event.touches && event.touches[0].pageX);
let y = event.clientY || (event.touches && event.touches[0].pageY);

if (this.props.posX) {
x -= this.props.posX;
}
if (this.props.posY) {
y -= this.props.posY;
}

hideMenu();
onOptionClick = (event, option) => {
this.setState({
isContextMenuVisible: false,
});

this.setState({ activeDirent: currentObject });
const handlers = {
openFileInNewTab: this.onOpenInNewTab.bind(this),
openParentFolder: this.onOpenParentFolder.bind(this),
};

if (menuList.length === 0) {
return;
const handler = handlers[option.value];
if (handler) {
handler(event);
}
};

showMenu({
id: id,
position: { x, y },
target: event.target,
currentObject: currentObject,
menuList: menuList,
});
onCloseContextMenu = () => {
this.setState({ isContextMenuVisible: false });
};

onFileNameContextMenu = (event, cell) => {
onContextMenu = (event, cell) => {
const record = this.props.recordGetter(cell.rowIdx);
if (record._is_dir) {
return;
}

this.baseURI = event.target.baseURI;
this.setState({ selectedPosition: cell });
this.handleContextMenu(event, METADATA_RECORD_CONTEXT_MENU, this.getMenuList());
};
const { clientX, clientY, touches, target } = event;

getMenuContainerSize = () => {
if (this.resultContainerRef) {
const { offsetWidth: width, offsetHeight: height } = this.resultContainerRef;
return { width, height };
}
return { width: 0, height: 0 };
// Calculate x and y coordinates
const x = (clientX || touches?.[0]?.pageX) - this.resultContainerRef.getBoundingClientRect().left - (this.props.posX || 0);
const y = (clientY || touches?.[0]?.pageY) - this.resultContainerRef.getBoundingClientRect().top - (this.props.posY || 0);

const position = { x, y };

this.baseURI = target.baseURI;
this.setState({
selectedPosition: cell,
isContextMenuVisible: true,
contextMenuPosition: position
});
};

renderRecordsBody = ({ containerWidth }) => {
Expand All @@ -716,7 +688,7 @@ class Records extends Component {
setRecordsScrollLeft: this.setScrollLeft,
hasSelectedCell: this.hasSelectedCell,
cacheScrollTop: this.storeScrollTop,
onFileNameContextMenu: this.onFileNameContextMenu,
onContextMenu: this.onContextMenu,
};
if (this.props.isGroupView) {
return (
Expand Down Expand Up @@ -779,9 +751,11 @@ class Records extends Component {
{this.renderRecordsBody({ containerWidth })}
</div>
<ContextMenu
id={METADATA_RECORD_CONTEXT_MENU}
onMenuItemClick={this.onMenuItemClick}
getMenuContainerSize={this.getMenuContainerSize}
position={this.state.contextMenuPosition}
options={this.contextMenuOptions}
onOptionClick={this.onOptionClick}
visible={this.state.isContextMenuVisible}
onCloseContextMenu={this.onCloseContextMenu}
/>
</div>
{this.isWindows && this.isWebkit && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ const Cell = React.memo(({
}, []);

const onContextMenu = useCallback((event) => {
event.preventDefault();
event.stopPropagation();
if (column.idx !== 0) return;
const cell = { idx: column.idx, groupRecordIndex, rowIdx: recordIndex };

Expand Down

0 comments on commit 009f721

Please sign in to comment.