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

add context menu for libraries list #6909

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions frontend/src/components/context-menu/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,27 @@ export function showMenu(opts = {}, target) {
export function hideMenu(opts = {}, target) {
dispatchGlobalEvent(MENU_HIDE, assign({}, opts, { type: MENU_HIDE }), target);
}

export function handleContextClick(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);

hideMenu();

let showMenuConfig = {
id: id,
position: { x, y },
target: event.target,
currentObject: currentObject,
menuList: menuList,
};

if (menuList.length === 0) {
return;
}

showMenu(showMenuConfig);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ const propTypes = {
onItemUnshare: PropTypes.func.isRequired,
onItemRename: PropTypes.func,
onItemDelete: PropTypes.func,
onMonitorRepo: PropTypes.func
onMonitorRepo: PropTypes.func,
onContextMenu: PropTypes.func.isRequired,
};

class SharedRepoListItem extends React.Component {
Expand Down Expand Up @@ -157,7 +158,7 @@ class SharedRepoListItem extends React.Component {
};

onMenuItemClick = (e) => {
let operation = e.target.dataset.toggle;
let operation = e.target.dataset.toggle || e.target.dataset.operation;
switch (operation) {
case 'Rename':
this.onItemRenameToggle();
Expand Down Expand Up @@ -616,6 +617,10 @@ class SharedRepoListItem extends React.Component {
}
};

handleContextMenu = (e) => {
this.props.onContextMenu(e, this.props.repo);
};

renderPCUI = () => {
const { isStarred } = this.state;
let { iconUrl, iconTitle, libPath } = this.getRepoComputeParams();
Expand All @@ -627,6 +632,7 @@ class SharedRepoListItem extends React.Component {
onMouseOver={this.onMouseOver}
onMouseLeave={this.onMouseLeave}
onFocus={this.onMouseEnter}
onContextMenu={this.handleContextMenu}
>
<td className="text-center">
<i
Expand Down Expand Up @@ -659,6 +665,7 @@ class SharedRepoListItem extends React.Component {
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onFocus={this.onMouseEnter}
onContextMenu={this.handleContextMenu}
>
<div className="d-flex align-items-center text-truncate">
<img src={iconUrl} title={iconTitle} alt={iconTitle} width="36" className="mr-2" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import toaster from '../toast';
import LibsMobileThead from '../libs-mobile-thead';
import Loading from '../loading';
import { LIST_MODE } from '../dir-view-mode/constants';
import ContextMenu from '../context-menu/context-menu';
import { hideMenu, handleContextClick } from '../context-menu/actions';

const propTypes = {
currentViewMode: PropTypes.string,
Expand All @@ -33,6 +35,7 @@ class SharedRepoListView extends React.Component {
this.state = {
isItemFreezed: false,
};
this.repoItems = [];
}

sortByName = (e) => {
Expand Down Expand Up @@ -86,13 +89,41 @@ class SharedRepoListView extends React.Component {
this.props.onItemRename(repo, newName);
};

setRepoItemRef = (index) => item => {
this.repoItems[index] = item;
};

getRepoIndex = (repo) => {
return this.props.repoList.findIndex(item => {
return item.repo_id === repo.repo_id;
});
};

onMenuItemClick = (operation, currentObject, event) => {
const index = this.getRepoIndex(currentObject);
if (this.repoItems[index]) {
this.repoItems[index].onMenuItemClick(event);
}
hideMenu();
};

onContextMenu = (event, repo) => {
event.preventDefault();
const { libraryType, currentGroup } = this.props;
const isPublic = libraryType === 'public';
const id = isPublic ? 'shared-repo-item-menu' : `shared-repo-item-menu-${currentGroup.id}`;
const menuList = Utils.getSharedRepoOperationList(repo, currentGroup, isPublic);
handleContextClick(event, id, menuList, repo);
};

renderRepoListView = () => {
const { currentViewMode = LIST_MODE } = this.props;
const { currentViewMode = LIST_MODE, currentGroup, libraryType } = this.props;
return (
<Fragment>
{this.props.repoList.map(repo => {
{this.props.repoList.map((repo, index) => {
return (
<SharedRepoListItem
ref={this.setRepoItemRef(index)}
key={repo.repo_id}
repo={repo}
libraryType={this.props.libraryType}
Expand All @@ -105,9 +136,14 @@ class SharedRepoListView extends React.Component {
onItemRename={this.props.onItemRename}
onMonitorRepo={this.props.onMonitorRepo}
currentViewMode={currentViewMode}
onContextMenu={this.onContextMenu}
/>
);
})}
<ContextMenu
id={`${libraryType === 'public' ? 'shared-repo-item-menu' : `shared-repo-item-menu-${currentGroup.id}`}`}
onMenuItemClick={this.onMenuItemClick}
/>
</Fragment>
);
};
Expand All @@ -117,22 +153,24 @@ class SharedRepoListView extends React.Component {
const { sortByName, sortByTime, sortBySize, sortIcon } = this.getSortMetaData();

return currentViewMode == LIST_MODE ? (
<table className={theadHidden ? 'table-thead-hidden' : ''}>
<thead>
<tr>
<th width="4%"></th>
<th width="3%"><span className="sr-only">{gettext('Library Type')}</span></th>
<th width="35%"><a className="d-block table-sort-op" href="#" onClick={this.sortByName}>{gettext('Name')} {sortByName && sortIcon}</a></th>
<th width="10%"><span className="sr-only">{gettext('Actions')}</span></th>
<th width="14%"><a className="d-block table-sort-op" href="#" onClick={this.sortBySize}>{gettext('Size')} {sortBySize && sortIcon}</a></th>
<th width="17%"><a className="d-block table-sort-op" href="#" onClick={this.sortByTime}>{gettext('Last Update')} {sortByTime && sortIcon}</a></th>
<th width="17%">{gettext('Owner')}</th>
</tr>
</thead>
<tbody>
{this.renderRepoListView()}
</tbody>
</table>
<>
<table className={theadHidden ? 'table-thead-hidden' : ''}>
<thead>
<tr>
<th width="4%"></th>
<th width="3%"><span className="sr-only">{gettext('Library Type')}</span></th>
<th width="35%"><a className="d-block table-sort-op" href="#" onClick={this.sortByName}>{gettext('Name')} {sortByName && sortIcon}</a></th>
<th width="10%"><span className="sr-only">{gettext('Actions')}</span></th>
<th width="14%"><a className="d-block table-sort-op" href="#" onClick={this.sortBySize}>{gettext('Size')} {sortBySize && sortIcon}</a></th>
<th width="17%"><a className="d-block table-sort-op" href="#" onClick={this.sortByTime}>{gettext('Last Update')} {sortByTime && sortIcon}</a></th>
<th width="17%">{gettext('Owner')}</th>
</tr>
</thead>
<tbody>
{this.renderRepoListView()}
</tbody>
</table>
</>
) : (
<div className="d-flex justify-content-between flex-wrap">
{this.renderRepoListView()}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/pages/groups/group-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ class GroupItem extends React.Component {
{group.repos.length === 0 ?
emptyTip :
<SharedRepoListView
key={`group-${group.id}`}
inAllLibs={inAllLibs}
theadHidden={true}
isShowRepoOwner={false}
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/pages/my-libs/mylib-repo-list-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const propTypes = {
onDeleteRepo: PropTypes.func.isRequired,
onTransferRepo: PropTypes.func.isRequired,
onMonitorRepo: PropTypes.func.isRequired,
onContextMenu: PropTypes.func.isRequired,
};

class MylibRepoListItem extends React.Component {
Expand Down Expand Up @@ -303,6 +304,10 @@ class MylibRepoListItem extends React.Component {
});
};

handleContextMenu = (event) => {
this.props.onContextMenu(event, this.props.repo);
};

renderPCUI = () => {
const { isStarred } = this.state;
const { repo, currentViewMode = LIST_MODE } = this.props;
Expand All @@ -311,7 +316,7 @@ class MylibRepoListItem extends React.Component {
let iconTitle = Utils.getLibIconTitle(repo);
let repoURL = `${siteRoot}library/${repo.repo_id}/${Utils.encodePath(repo.repo_name)}/`;
return currentViewMode == LIST_MODE ? (
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onFocus={this.onFocus}>
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} onFocus={this.onFocus} onContextMenu={this.handleContextMenu}>
<td className="text-center">
<i
role="button"
Expand Down Expand Up @@ -366,6 +371,7 @@ class MylibRepoListItem extends React.Component {
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onFocus={this.onFocus}
onContextMenu={this.handleContextMenu}
>
<div className="d-flex align-items-center text-truncate">
<img src={iconUrl} title={iconTitle} alt={iconTitle} width="36" className="mr-2" />
Expand Down
36 changes: 35 additions & 1 deletion frontend/src/pages/my-libs/mylib-repo-list-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { gettext, storages } from '../../utils/constants';
import MylibRepoListItem from './mylib-repo-list-item';
import LibsMobileThead from '../../components/libs-mobile-thead';
import { LIST_MODE } from '../../components/dir-view-mode/constants';
import ContextMenu from '../../components/context-menu/context-menu';
import { Utils } from '../../utils/utils';
import { hideMenu, handleContextClick } from '../../components/context-menu/actions';

const propTypes = {
sortBy: PropTypes.string.isRequired,
Expand All @@ -26,6 +29,7 @@ class MylibRepoListView extends React.Component {
this.state = {
isItemFreezed: false,
};
this.repoItems = [];
}

onFreezedItem = () => {
Expand Down Expand Up @@ -57,12 +61,37 @@ class MylibRepoListView extends React.Component {
this.props.sortRepoList(sortBy, sortOrder);
};

onContextMenu = (event, repo) => {
event.preventDefault();
const id = 'mylib-repo-item-menu';
const menuList = Utils.getRepoOperationList(repo);
handleContextClick(event, id, menuList, repo);
};

setRepoItemRef = (index) => item => {
this.repoItems[index] = item;
};

getRepoIndex = (repo) => {
return this.props.repoList.findIndex(item => {
return item.repo_id === repo.repo_id;
});
};

onMenuItemClick = (operation, currentObject) => {
const index = this.getRepoIndex(currentObject);
this.repoItems[index].onMenuItemClick(operation);

hideMenu();
};

renderRepoListView = () => {
return (
<Fragment>
{this.props.repoList.map(item => {
{this.props.repoList.map((item, index) => {
return (
<MylibRepoListItem
ref={this.setRepoItemRef(index)}
key={item.repo_id}
repo={item}
isItemFreezed={this.state.isItemFreezed}
Expand All @@ -73,6 +102,7 @@ class MylibRepoListView extends React.Component {
onTransferRepo={this.props.onTransferRepo}
onMonitorRepo={this.props.onMonitorRepo}
currentViewMode={this.props.currentViewMode}
onContextMenu={this.onContextMenu}
/>
);
})}
Expand Down Expand Up @@ -130,6 +160,10 @@ class MylibRepoListView extends React.Component {
<MediaQuery query="(max-width: 767.8px)">
{this.renderMobileUI()}
</MediaQuery>
<ContextMenu
id="mylib-repo-item-menu"
onMenuItemClick={this.onMenuItemClick}
/>
</Fragment>
);
}
Expand Down
Loading
Loading