Skip to content

Commit

Permalink
Add context menu on commits in the HistorySidebar with add tag command (
Browse files Browse the repository at this point in the history
#1277)

* add context menu on commits in the HistorySidebar with add tag command

* remove additional comments

* hide filter div when adding tag from context menu

* add integration test for adding a tag from context menu
  • Loading branch information
DenisaCG authored Oct 23, 2023
1 parent 507fdb3 commit 924be51
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 24 deletions.
95 changes: 94 additions & 1 deletion src/commandsAndMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { ContextMenu, DockPanel, Menu, Panel, Widget } from '@lumino/widgets';
import * as React from 'react';
import { CancelledError } from './cancelledError';
import { BranchPicker } from './components/BranchPicker';
import { NewTagDialogBox } from './components/NewTagDialog';
import { DiffModel } from './components/diff/model';
import { createPlainTextDiff } from './components/diff/PlainTextDiff';
import { PreviewMainAreaWidget } from './components/diff/PreviewMainAreaWidget';
Expand All @@ -39,7 +40,8 @@ import {
gitIcon,
historyIcon,
openIcon,
removeIcon
removeIcon,
tagIcon
} from './style/icons';
import {
CommandIDs,
Expand Down Expand Up @@ -102,6 +104,9 @@ export namespace CommandArguments {
export interface IGitContextAction {
files: Git.IStatusFile[];
}
export interface IGitCommitInfo {
commit: Git.ISingleCommitInfo;
}
}

function pluralizedContextLabel(singular: string, plural: string) {
Expand Down Expand Up @@ -1537,6 +1542,79 @@ export function addCommands(
isEnabled: () => false,
execute: () => void 0
});

commands.addCommand(ContextCommandIDs.gitTagAdd, {
label: trans.__('Add Tag'),
caption: trans.__('Add tag pointing to selected commit'),
execute: async args => {
const commit = args as any as CommandArguments.IGitCommitInfo;

const widgetId = 'git-dialog-AddTag';
let anchor = document.querySelector<HTMLDivElement>(`#${widgetId}`);
if (!anchor) {
anchor = document.createElement('div');
anchor.id = widgetId;
document.body.appendChild(anchor);
}

const tagDialog = true;
const isSingleCommit = true;

const waitForDialog = new PromiseDelegate<string | null>();
const dialog = ReactWidget.create(
<NewTagDialogBox
pastCommits={[commit.commit]}
logger={logger}
model={gitModel}
trans={trans}
open={tagDialog}
onClose={(tagName?: string) => {
dialog.dispose();
waitForDialog.resolve(tagName ?? null);
}}
isSingleCommit={isSingleCommit}
/>
);

Widget.attach(dialog, anchor);

const tagName = await waitForDialog.promise;

if (tagName) {
logger.log({
level: Level.RUNNING,
message: trans.__(
"Create tag pointing to '%1'...",
commit.commit.commit_msg
)
});
try {
await gitModel.setTag(tagName, commit.commit.commit);
} catch (err) {
logger.log({
level: Level.ERROR,
message: trans.__(
"Failed to create tag '%1' poining to '%2'.",
tagName,
commit
),
error: err as Error
});
return;
}

logger.log({
level: Level.SUCCESS,
message: trans.__(
"Created tag '%1' pointing to '%2'.",
tagName,
commit
)
});
}
},
icon: tagIcon.bindprops({ stylesheet: 'menuItem' })
});
}

/**
Expand Down Expand Up @@ -1639,6 +1717,21 @@ export function addMenuItems(
});
}

export function addHistoryMenuItems(
commands: ContextCommandIDs[],
contextMenu: Menu,
selectedCommit: Git.ISingleCommitInfo
): void {
commands.forEach(command => {
contextMenu.addItem({
command,
args: {
commit: selectedCommit
} as CommandArguments.IGitCommitInfo as any
});
});
}

/**
* Populate Git context submenu depending on the selected files.
*/
Expand Down
26 changes: 25 additions & 1 deletion src/components/HistorySideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { TranslationBundle } from '@jupyterlab/translation';
import { closeIcon } from '@jupyterlab/ui-components';
import { CommandRegistry } from '@lumino/commands';
import { Menu } from '@lumino/widgets';
import { addHistoryMenuItems } from '../commandsAndMenu';
import * as React from 'react';
import { GitExtension } from '../model';
import { hiddenButtonStyle } from '../style/ActionButtonStyle';
Expand All @@ -10,7 +12,7 @@ import {
selectedHistoryFileStyle,
historySideBarWrapperStyle
} from '../style/HistorySideBarStyle';
import { Git } from '../tokens';
import { ContextCommandIDs, Git } from '../tokens';
import { openFileDiff } from '../utils';
import { ActionButton } from './ActionButton';
import { FileItem } from './FileItem';
Expand Down Expand Up @@ -79,6 +81,8 @@ export interface IHistorySideBarProps {
) => (event: React.MouseEvent<HTMLElement, MouseEvent>) => Promise<void>;
}

export const CONTEXT_COMMANDS = [ContextCommandIDs.gitTagAdd];

/**
* Returns a React component for displaying commit history.
*
Expand Down Expand Up @@ -145,6 +149,25 @@ export const HistorySideBar: React.FunctionComponent<IHistorySideBarProps> = (
return () => resizeObserver.disconnect();
}, [props.commits]);

/**
* Open the context menu on the advanced view
*
* @param selectedCommit The commit on which the context menu is opened
* @param event The click event
*/
const openContextMenu = (
selectedCommit: Git.ISingleCommitInfo,
event: React.MouseEvent
): void => {
event.preventDefault();

const contextMenu = new Menu({ commands: props.commands });
const commands = [ContextCommandIDs.gitTagAdd];
addHistoryMenuItems(commands, contextMenu, selectedCommit);

contextMenu.open(event.clientX, event.clientY);
};

return (
<div className={historySideBarWrapperStyle}>
{!props.model.selectedHistoryFile && (
Expand Down Expand Up @@ -232,6 +255,7 @@ export const HistorySideBar: React.FunctionComponent<IHistorySideBarProps> = (
}
})
}
contextMenu={openContextMenu}
>
{!props.model.selectedHistoryFile && (
<SinglePastCommitInfo
Expand Down
59 changes: 38 additions & 21 deletions src/components/NewTagDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export interface INewTagDialogProps {
pastCommits: Git.ISingleCommitInfo[];

/**
* Extension logger
* Extension logger.
*/
logger: Logger;

Expand All @@ -69,6 +69,11 @@ export interface INewTagDialogProps {
* The application language translator.
*/
trans: TranslationBundle;

/**
* Dialog box open from the context menu?
*/
isSingleCommit: boolean;
}

/**
Expand Down Expand Up @@ -109,6 +114,11 @@ export interface IDialogBoxCommitGraphProps {
* Update function for baseCommitId.
*/
updateBaseCommitId: React.Dispatch<React.SetStateAction<string>>;

/**
* Dialog box open from the context menu.
*/
isSingleCommit: boolean;
}

/**
Expand Down Expand Up @@ -185,6 +195,10 @@ export const DialogBoxCommitGraph: React.FunctionComponent<
isFilter = true;
}

if (props.isSingleCommit === true) {
isFilter = false;
}

return (
<div className={historyDialogBoxWrapperStyle}>
{isFilter && (
Expand Down Expand Up @@ -427,27 +441,29 @@ export const NewTagDialogBox: React.FunctionComponent<INewTagDialogProps> = (
title={props.trans.__('Enter a tag name')}
/>
<p>{props.trans.__('Create tag pointing to…')}</p>
<div className={filterWrapperClass}>
<div className={filterClass}>
<input
className={filterInputClass}
type="text"
onChange={onFilterChange}
value={filterState}
placeholder={props.trans.__('Filter by commit message')}
title={props.trans.__('Filter history of commits menu')}
/>
{filterState ? (
<button className={filterClearClass}>
<ClearIcon
titleAccess={props.trans.__('Clear the current filter')}
fontSize="small"
onClick={resetFilter}
/>
</button>
) : null}
{props.isSingleCommit ? null : (
<div className={filterWrapperClass}>
<div className={filterClass}>
<input
className={filterInputClass}
type="text"
onChange={onFilterChange}
value={filterState}
placeholder={props.trans.__('Filter by commit message')}
title={props.trans.__('Filter history of commits menu')}
/>
{filterState ? (
<button className={filterClearClass}>
<ClearIcon
titleAccess={props.trans.__('Clear the current filter')}
fontSize="small"
onClick={resetFilter}
/>
</button>
) : null}
</div>
</div>
</div>
)}
{
<DialogBoxCommitGraph
pastCommits={props.pastCommits}
Expand All @@ -457,6 +473,7 @@ export const NewTagDialogBox: React.FunctionComponent<INewTagDialogProps> = (
filter={filterState}
baseCommitId={baseCommitIdState}
updateBaseCommitId={setBaseCommitIdState}
isSingleCommit={props.isSingleCommit}
/>
}
</div>
Expand Down
14 changes: 14 additions & 0 deletions src/components/PastCommitNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ export interface IPastCommitNodeProps {
* @param el the <li> element representing a past commit
*/
setRef: (el: HTMLLIElement) => void;

/**
* Callback to open a context menu on the commit
*/
contextMenu?: (
commit: Git.ISingleCommitInfo,
event: React.MouseEvent
) => void;
}

/**
Expand Down Expand Up @@ -162,6 +170,12 @@ export class PastCommitNode extends React.Component<
: this.props.trans.__('View file changes')
}
onClick={event => this._onCommitClick(event, this.props.commit.commit)}
onContextMenu={
this.props.contextMenu &&
(event => {
this.props.contextMenu(this.props.commit, event);
})
}
>
<div className={commitHeaderClass}>
<span className={commitHeaderItemClass}>
Expand Down
2 changes: 2 additions & 0 deletions src/components/TagMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ export class TagMenu extends React.Component<ITagMenuProps, ITagMenuState> {
* @returns React element
*/
private _renderNewTagDialog(): React.ReactElement {
const isSingleCommit = false;
return (
<NewTagDialogBox
pastCommits={this.props.pastCommits}
Expand All @@ -273,6 +274,7 @@ export class TagMenu extends React.Component<ITagMenuProps, ITagMenuState> {
trans={this.props.trans}
open={this.state.tagDialog}
onClose={this._onNewTagDialogClose}
isSingleCommit={isSingleCommit}
/>
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1373,7 +1373,8 @@ export enum ContextCommandIDs {
gitIgnoreExtension = 'git:context-ignoreExtension',
gitNoAction = 'git:no-action',
openFileFromDiff = 'git:open-file-from-diff',
gitFileStashPop = 'git:context-stash-pop'
gitFileStashPop = 'git:context-stash-pop',
gitTagAdd = 'git:context-tag-add'
}

/**
Expand Down
Loading

0 comments on commit 924be51

Please sign in to comment.