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 on commits in the HistorySidebar with add tag command #1277

Merged
merged 4 commits into from
Oct 23, 2023
Merged
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
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