diff --git a/src/sql/workbench/contrib/notebook/browser/cellToolbarActions.ts b/src/sql/workbench/contrib/notebook/browser/cellToolbarActions.ts index 8b9ff9d209..89a66f05c9 100644 --- a/src/sql/workbench/contrib/notebook/browser/cellToolbarActions.ts +++ b/src/sql/workbench/contrib/notebook/browser/cellToolbarActions.ts @@ -6,20 +6,22 @@ import { localize } from 'vs/nls'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { Action, IAction, Separator } from 'vs/base/common/actions'; -import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; +import { Action, IAction, IActionRunner, Separator } from 'vs/base/common/actions'; import { CellActionBase, CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions'; import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell'; import { CellTypes, CellType } from 'sql/workbench/services/notebook/common/contracts'; -import { ToggleableAction } from 'sql/workbench/contrib/notebook/browser/notebookActions'; +import { AddCodeCellAction, AddTextCellAction, ToggleableAction } from 'sql/workbench/contrib/notebook/browser/notebookActions'; import { getErrorMessage } from 'vs/base/common/errors'; import Severity from 'vs/base/common/severity'; import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { CellEditModes, MoveDirection } from 'sql/workbench/services/notebook/browser/models/modelInterfaces'; import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys'; -const moreActionsLabel = localize('moreActionsLabel', "More"); +import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem'; +import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; +import { moreActionsLabel } from 'sql/workbench/contrib/notebook/common/notebookLoc'; + +const addCellLabel = localize('addCellLabel', "Add cell"); export class EditCellAction extends ToggleableAction { // Constants @@ -147,49 +149,6 @@ export class DeleteCellAction extends CellActionBase { } } -export class CellToggleMoreActions { - private _actions: (Action | CellActionBase)[] = []; - private _moreActions: ActionBar; - private _moreActionsElement: HTMLElement; - constructor( - @IInstantiationService private instantiationService: IInstantiationService - ) { - this._actions.push( - instantiationService.createInstance(ConvertCellAction, 'convertCell', localize('convertCell', "Convert Cell")), - new Separator(), - instantiationService.createInstance(RunCellsAction, 'runAllAbove', localize('runAllAbove', "Run Cells Above"), false), - instantiationService.createInstance(RunCellsAction, 'runAllBelow', localize('runAllBelow', "Run Cells Below"), true), - new Separator(), - instantiationService.createInstance(AddCellFromContextAction, 'codeAbove', localize('codeAbove', "Insert Code Above"), CellTypes.Code, false), - instantiationService.createInstance(AddCellFromContextAction, 'codeBelow', localize('codeBelow', "Insert Code Below"), CellTypes.Code, true), - new Separator(), - instantiationService.createInstance(AddCellFromContextAction, 'markdownAbove', localize('markdownAbove', "Insert Text Above"), CellTypes.Markdown, false), - instantiationService.createInstance(AddCellFromContextAction, 'markdownBelow', localize('markdownBelow', "Insert Text Below"), CellTypes.Markdown, true), - new Separator(), - instantiationService.createInstance(CollapseCellAction, 'collapseCell', localize('collapseCell', "Collapse Cell"), true), - instantiationService.createInstance(CollapseCellAction, 'expandCell', localize('expandCell', "Expand Cell"), false), - new Separator(), - instantiationService.createInstance(ParametersCellAction, 'makeParameterCell', localize('makeParameterCell', "Make parameter cell"), true), - instantiationService.createInstance(ParametersCellAction, 'removeParameterCell', localize('RemoveParameterCell', "Remove parameter cell"), false), - new Separator(), - instantiationService.createInstance(ClearCellOutputAction, 'clear', localize('clear', "Clear Result")), - ); - } - - public onInit(elementRef: HTMLElement, context: CellContext) { - this._moreActionsElement = elementRef; - this._moreActionsElement.setAttribute('aria-haspopup', 'menu'); - if (this._moreActionsElement.childNodes.length > 0) { - this._moreActionsElement.removeChild(this._moreActionsElement.childNodes[0]); - } - this._moreActions = new ActionBar(this._moreActionsElement, { orientation: ActionsOrientation.VERTICAL, ariaLabel: moreActionsLabel }); - this._moreActions.context = { target: this._moreActionsElement }; - let validActions = this._actions.filter(a => a instanceof Separator || a instanceof CellActionBase && a.canRun(context)); - removeDuplicatedAndStartingSeparators(validActions); - this._moreActions.push(this.instantiationService.createInstance(ToggleMoreActions, validActions, context), { icon: true, label: false }); - } -} - export function removeDuplicatedAndStartingSeparators(actions: (Action | CellActionBase)[]): void { let indexesToRemove: number[] = []; for (let i = 0; i < actions.length; i++) { @@ -368,26 +327,104 @@ export class CollapseCellAction extends CellActionBase { } } -export class ToggleMoreActions extends Action { +export class ToggleAddCellDropdownAction extends Action { - private static readonly ID = 'toggleMore'; - private static readonly LABEL = moreActionsLabel; - private static readonly ICON = 'masked-icon more'; + public static readonly ID = 'notebook.toggleAddCell'; + public static readonly LABEL = addCellLabel; + public static readonly ICON = 'codicon masked-icon new'; constructor( - private readonly _actions: Array, - private readonly _context: CellContext, - @IContextMenuService private readonly _contextMenuService: IContextMenuService + ) { - super(ToggleMoreActions.ID, ToggleMoreActions.LABEL, ToggleMoreActions.ICON); + super(ToggleAddCellDropdownAction.ID); + this.tooltip = ToggleAddCellDropdownAction.LABEL; + } +} + +export class ToggleAddCellActionViewItem extends DropdownMenuActionViewItem { + constructor( + action: IAction, + actionRunner: IActionRunner, + cellContext: CellContext, + @IContextMenuService contextMenuService: IContextMenuService, + @IInstantiationService instantiationService: IInstantiationService + ) { + super(action, + [ + instantiationService.createInstance(AddCodeCellAction), + instantiationService.createInstance(AddTextCellAction) + ], + contextMenuService, + { + actionRunner, + classNames: ToggleAddCellDropdownAction.ICON, + anchorAlignmentProvider: () => AnchorAlignment.RIGHT + }); + this.setActionContext(cellContext); + } +} + +export class CellToggleMoreAction extends Action { + public static readonly ID = 'notebook.toggleMore'; + public static readonly LABEL = moreActionsLabel; + public static readonly ICON = 'codicon masked-icon more'; + + constructor() { + super(CellToggleMoreAction.ID); + this.tooltip = CellToggleMoreAction.LABEL; + } +} + +export class CellToggleMoreActionViewItem extends DropdownMenuActionViewItem { + private _actions: (Action | CellActionBase)[]; + constructor( + action: IAction, + actionRunner: IActionRunner, + private _cellContext: CellContext, + @IContextMenuService contextMenuService: IContextMenuService, + @IInstantiationService instantiationService: IInstantiationService + ) { + super(action, + { + getActions: () => { return this.getValidActions(); } + }, + contextMenuService, + { + actionRunner, + classNames: CellToggleMoreAction.ICON, + anchorAlignmentProvider: () => AnchorAlignment.RIGHT + }); + this.setActionContext(this._cellContext); + this._actions = [ + instantiationService.createInstance(ConvertCellAction, 'convertCell', localize('convertCell', "Convert Cell")), + new Separator(), + instantiationService.createInstance(RunCellsAction, 'runAllAbove', localize('runAllAbove', "Run Cells Above"), false), + instantiationService.createInstance(RunCellsAction, 'runAllBelow', localize('runAllBelow', "Run Cells Below"), true), + new Separator(), + instantiationService.createInstance(AddCellFromContextAction, 'codeAbove', localize('codeAbove', "Insert Code Above"), CellTypes.Code, false), + instantiationService.createInstance(AddCellFromContextAction, 'codeBelow', localize('codeBelow', "Insert Code Below"), CellTypes.Code, true), + new Separator(), + instantiationService.createInstance(AddCellFromContextAction, 'markdownAbove', localize('markdownAbove', "Insert Text Above"), CellTypes.Markdown, false), + instantiationService.createInstance(AddCellFromContextAction, 'markdownBelow', localize('markdownBelow', "Insert Text Below"), CellTypes.Markdown, true), + new Separator(), + instantiationService.createInstance(CollapseCellAction, 'collapseCell', localize('collapseCell', "Collapse Cell"), true), + instantiationService.createInstance(CollapseCellAction, 'expandCell', localize('expandCell', "Expand Cell"), false), + new Separator(), + instantiationService.createInstance(ParametersCellAction, 'makeParameterCell', localize('makeParameterCell', "Make parameter cell"), true), + instantiationService.createInstance(ParametersCellAction, 'removeParameterCell', localize('RemoveParameterCell', "Remove parameter cell"), false), + new Separator(), + instantiationService.createInstance(ClearCellOutputAction, 'clear', localize('clear', "Clear Result")), + ]; } - override async run(context: StandardKeyboardEvent): Promise { - this._contextMenuService.showContextMenu({ - getAnchor: () => context.target, - getActions: () => this._actions, - getActionsContext: () => this._context - }); + /** + * Gets the actions that are valid for the current cell context + * @returns The list of valid actions + */ + public getValidActions(): readonly IAction[] { + const validActions = this._actions.filter(a => a instanceof Separator || a instanceof CellActionBase && a.canRun(this._cellContext)); + removeDuplicatedAndStartingSeparators(validActions); + return validActions; } } diff --git a/src/sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component.ts b/src/sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component.ts index a1abf1d088..d7e7cc30ff 100644 --- a/src/sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component.ts @@ -4,16 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./cellToolbar'; -import * as DOM from 'vs/base/browser/dom'; import { Component, Inject, ViewChild, ElementRef, Input } from '@angular/core'; import { localize } from 'vs/nls'; import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar'; -import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { DeleteCellAction, EditCellAction, CellToggleMoreActions, MoveCellAction, SplitCellAction } from 'sql/workbench/contrib/notebook/browser/cellToolbarActions'; -import { AddCodeCellAction, AddTextCellAction, ToggleAddCellDropdownAction } from 'sql/workbench/contrib/notebook/browser/notebookActions'; +import { DeleteCellAction, EditCellAction, CellToggleMoreActionViewItem, MoveCellAction, SplitCellAction, CellToggleMoreAction, ToggleAddCellDropdownAction, ToggleAddCellActionViewItem } from 'sql/workbench/contrib/notebook/browser/cellToolbarActions'; import { CellTypes } from 'sql/workbench/services/notebook/common/contracts'; -import { DropdownMenuActionViewItem } from 'sql/base/browser/ui/buttonMenu/buttonMenu'; import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces'; import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel'; import { CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions'; @@ -44,13 +40,10 @@ export class CellToolbarComponent { private _editCellAction: EditCellAction; private _cellContext: CellContext; private _typeChangedListener: IDisposable; - public _cellToggleMoreActions: CellToggleMoreActions; constructor( - @Inject(IInstantiationService) private instantiationService: IInstantiationService, - @Inject(IContextMenuService) private contextMenuService: IContextMenuService + @Inject(IInstantiationService) private instantiationService: IInstantiationService ) { - this._cellToggleMoreActions = this.instantiationService.createInstance(CellToggleMoreActions); this._disposableActions = new DisposableStore(); } @@ -70,7 +63,16 @@ export class CellToolbarComponent { protected initActionBar(): void { this._cellContext = new CellContext(this.model, this.cellModel); let taskbar = this.celltoolbar.nativeElement; - this._actionBar = new Taskbar(taskbar); + this._actionBar = new Taskbar(taskbar, { + actionViewItemProvider: action => { + if (action.id === ToggleAddCellDropdownAction.ID) { + return this.instantiationService.createInstance(ToggleAddCellActionViewItem, action, this._actionBar.actionRunner, this._cellContext); + } else if (action.id === CellToggleMoreAction.ID) { + return this.instantiationService.createInstance(CellToggleMoreActionViewItem, action, this._actionBar.actionRunner, this._cellContext); + } + return undefined; + } + }); this._actionBar.context = this._cellContext; this.setupActions(); @@ -79,67 +81,36 @@ export class CellToolbarComponent { private setupActions(): void { this._disposableActions.clear(); - let toggleAddCellDropdown = this.instantiationService.createInstance(ToggleAddCellDropdownAction); - this._disposableActions.add(toggleAddCellDropdown); + const toggleAddCellDropdownAction = this._disposableActions.add(this.instantiationService.createInstance(ToggleAddCellDropdownAction)); - let addCodeCellAction = this.instantiationService.createInstance(AddCodeCellAction); - addCodeCellAction.cellType = CellTypes.Code; - this._disposableActions.add(addCodeCellAction); + const moveCellDownAction = this._disposableActions.add(this.instantiationService.createInstance(MoveCellAction, 'notebook.MoveCellDown', 'masked-icon move-down', this.buttonMoveDown)); + const moveCellUpAction = this._disposableActions.add(this.instantiationService.createInstance(MoveCellAction, 'notebook.MoveCellUp', 'masked-icon move-up', this.buttonMoveUp)); - let addTextCellAction = this.instantiationService.createInstance(AddTextCellAction); - addTextCellAction.cellType = CellTypes.Markdown; - this._disposableActions.add(addTextCellAction); - - let moveCellDownAction = this.instantiationService.createInstance(MoveCellAction, 'notebook.MoveCellDown', 'masked-icon move-down', this.buttonMoveDown); - let moveCellUpAction = this.instantiationService.createInstance(MoveCellAction, 'notebook.MoveCellUp', 'masked-icon move-up', this.buttonMoveUp); - this._disposableActions.add(moveCellDownAction); - this._disposableActions.add(moveCellUpAction); - - let splitCellAction = this.instantiationService.createInstance(SplitCellAction, 'notebook.SplitCellAtCursor', this.buttonSplitCell, 'masked-icon icon-split-cell'); + const splitCellAction = this._disposableActions.add(this.instantiationService.createInstance(SplitCellAction, 'notebook.SplitCellAtCursor', this.buttonSplitCell, 'masked-icon icon-split-cell')); splitCellAction.setListener(this._cellContext); splitCellAction.enabled = this.cellModel.cellType !== 'markdown'; - this._disposableActions.add(splitCellAction); - let deleteAction = this.instantiationService.createInstance(DeleteCellAction, 'notebook.DeleteCell', 'masked-icon delete', this.buttonDelete); - this._disposableActions.add(deleteAction); + const deleteAction = this._disposableActions.add(this.instantiationService.createInstance(DeleteCellAction, 'notebook.DeleteCell', 'masked-icon delete', this.buttonDelete)); - let moreActionsContainer = DOM.$('li.action-item'); - this._cellToggleMoreActions = this.instantiationService.createInstance(CellToggleMoreActions); - this._cellToggleMoreActions.onInit(moreActionsContainer, this._cellContext); - - this._editCellAction = this.instantiationService.createInstance(EditCellAction, 'notebook.EditCell', true, this.cellModel.isEditMode); + this._editCellAction = this._disposableActions.add(this.instantiationService.createInstance(EditCellAction, 'notebook.EditCell', true, this.cellModel.isEditMode)); this._editCellAction.enabled = true; - this._disposableActions.add(this._editCellAction); - let addCellDropdownContainer = DOM.$('li.action-item'); - addCellDropdownContainer.setAttribute('role', 'presentation'); - let dropdownMenuActionViewItem = new DropdownMenuActionViewItem( - toggleAddCellDropdown, - [addCodeCellAction, addTextCellAction], - this.contextMenuService, - undefined, - this._actionBar.actionRunner, - undefined, - 'codicon masked-icon new', - '', - undefined - ); - dropdownMenuActionViewItem.render(addCellDropdownContainer); - dropdownMenuActionViewItem.setActionContext(this._cellContext); + const moreAction = this._disposableActions.add(this.instantiationService.createInstance(CellToggleMoreAction)); - let taskbarContent: ITaskbarContent[] = []; + const taskbarContent: ITaskbarContent[] = []; if (this.cellModel.cellType === CellTypes.Markdown) { taskbarContent.push( { action: this._editCellAction } ); } taskbarContent.push( - { element: addCellDropdownContainer }, + { action: toggleAddCellDropdownAction }, { action: moveCellDownAction }, { action: moveCellUpAction }, { action: splitCellAction }, { action: deleteAction }, - { element: moreActionsContainer }); + { action: moreAction } + ); this._actionBar.setContent(taskbarContent); } diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts index e14c822b86..1161d4e84f 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts @@ -27,7 +27,7 @@ import { INotebookService, INotebookParams, INotebookEditor, INotebookSection, I import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel'; import { Deferred } from 'sql/base/common/promise'; import { ITaskbarContent, Taskbar } from 'sql/base/browser/ui/taskbar/taskbar'; -import { KernelsDropdown, AttachToDropdown, TrustedAction, RunAllCellsAction, ClearAllOutputsAction, CollapseCellsAction, RunParametersAction, NotebookViewsActionProvider, AddCodeCellAction, AddTextCellAction, ToggleAddCellDropdownAction } from 'sql/workbench/contrib/notebook/browser/notebookActions'; +import { KernelsDropdown, AttachToDropdown, TrustedAction, RunAllCellsAction, ClearAllOutputsAction, CollapseCellsAction, RunParametersAction, NotebookViewsActionProvider, AddCodeCellAction, AddTextCellAction } from 'sql/workbench/contrib/notebook/browser/notebookActions'; import { DropdownMenuActionViewItem } from 'sql/base/browser/ui/buttonMenu/buttonMenu'; import { INotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes'; import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService'; @@ -58,6 +58,7 @@ import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { debounce } from 'vs/base/common/decorators'; +import { ToggleAddCellDropdownAction } from 'sql/workbench/contrib/notebook/browser/cellToolbarActions'; export const NOTEBOOK_SELECTOR: string = 'notebook-component'; const PRIORITY = 105; diff --git a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts index 08a2bb2aa8..420826d5e3 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts @@ -59,12 +59,6 @@ export const noParameterCell: string = localize('noParametersCell', "This notebo export const noParametersInCell: string = localize('noParametersInCell', "This notebook cannot run with parameters until there are parameters added to the parameter cell. [Learn more](https://docs.microsoft.com/sql/azure-data-studio/notebooks/notebooks-parameterization)."); export const untitledNotSupported: string = localize('untitledNotSupported', "Run with parameters is not supported for Untitled notebooks. Please save the notebook before continuing. [Learn more](https://docs.microsoft.com/sql/azure-data-studio/notebooks/notebooks-parameterization)."); -export class ToggleAddCellDropdownAction extends Action { - constructor() { - super('notebook.toggleAddCell', localize('codeCellsPreview', "Add cell")) - } -} - export abstract class AddCellAction extends Action { public cellType: CellType; diff --git a/src/sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsActions.ts b/src/sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsActions.ts index 1cc982b782..2cd0368914 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsActions.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsActions.ts @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Action } from 'vs/base/common/actions'; +import { Action, IAction, IActionRunner } from 'vs/base/common/actions'; import { ViewOptionsModal } from 'sql/workbench/contrib/notebook/browser/notebookViews/viewOptionsModal'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { localize } from 'vs/nls'; @@ -19,11 +19,12 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ILogService } from 'vs/platform/log/common/log'; import { getErrorMessage } from 'vs/base/common/errors'; import * as types from 'vs/base/common/types'; -import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; -import { Separator } from 'sql/base/browser/ui/separator/separator'; -import { ToggleMoreActions } from 'sql/workbench/contrib/notebook/browser/cellToolbarActions'; import { NotebookViewsExtension } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension'; import { INotebookView } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViews'; +import { moreActionsLabel } from 'sql/workbench/contrib/notebook/common/notebookLoc'; +import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; export class ViewSettingsAction extends Action { private static readonly ID = 'notebookView.viewSettings'; @@ -216,27 +217,35 @@ export class ViewCellInNotebook extends CellActionBase { } } -export class ViewCellToggleMoreActions { - private _actions: (Action | CellActionBase)[] = []; - private _moreActions: ActionBar; - private _moreActionsElement: HTMLElement; - constructor( - @IInstantiationService private instantiationService: IInstantiationService - ) { - this._actions.push( - instantiationService.createInstance(ViewCellInNotebook, 'viewCellInNotebook', localize('viewCellInNotebook', "View Cell In Notebook")), - ); - } +export class ViewCellToggleMoreAction extends Action { + public static readonly ID = 'notebook.viewToggleMore'; + public static readonly LABEL = moreActionsLabel; + public static readonly ICON = 'codicon masked-icon more'; - public onInit(elementRef: HTMLElement, context: CellContext) { - this._moreActionsElement = elementRef; - this._moreActionsElement.setAttribute('aria-haspopup', 'menu'); - if (this._moreActionsElement.childNodes.length > 0) { - this._moreActionsElement.removeChild(this._moreActionsElement.childNodes[0]); - } - this._moreActions = new ActionBar(this._moreActionsElement, { orientation: ActionsOrientation.VERTICAL, ariaLabel: localize('moreActionsLabel', "More") }); - this._moreActions.context = { target: this._moreActionsElement }; - let validActions = this._actions.filter(a => a instanceof Separator || a instanceof CellActionBase && a.canRun(context)); - this._moreActions.push(this.instantiationService.createInstance(ToggleMoreActions, validActions, context), { icon: true, label: false }); + constructor() { + super(ViewCellToggleMoreAction.ID); + this.tooltip = ViewCellToggleMoreAction.LABEL; + } +} + +export class ViewCellToggleMoreActionViewItem extends DropdownMenuActionViewItem { + constructor( + action: IAction, + actionRunner: IActionRunner, + private _cellContext: CellContext, + @IContextMenuService contextMenuService: IContextMenuService, + @IInstantiationService instantiationService: IInstantiationService + ) { + super(action, + [ + instantiationService.createInstance(ViewCellInNotebook, 'viewCellInNotebook', localize('viewCellInNotebook', "View Cell In Notebook")) + ], + contextMenuService, + { + actionRunner, + classNames: ViewCellToggleMoreAction.ICON, + anchorAlignmentProvider: () => AnchorAlignment.RIGHT + }); + this.setActionContext(this._cellContext); } } diff --git a/src/sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsCard.component.ts b/src/sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsCard.component.ts index 8e2fe4665a..98982ddbb0 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsCard.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsCard.component.ts @@ -3,7 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import 'vs/css!./cellToolbar'; -import * as DOM from 'vs/base/browser/dom'; import { Component, OnInit, Input, ViewChild, TemplateRef, ElementRef, Inject, Output, EventEmitter, ChangeDetectorRef, forwardRef, SimpleChange } from '@angular/core'; import { CellExecutionState, ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces'; import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel'; @@ -11,7 +10,7 @@ import { DEFAULT_VIEW_CARD_HEIGHT, DEFAULT_VIEW_CARD_WIDTH, ViewsTab } from 'sql import { CellChangeEventType, INotebookView, INotebookViewCard } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViews'; import { ITaskbarContent, Taskbar } from 'sql/base/browser/ui/taskbar/taskbar'; import { CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions'; -import { RunCellAction, HideCellAction, ViewCellToggleMoreActions } from 'sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsActions'; +import { RunCellAction, HideCellAction, ViewCellToggleMoreAction, ViewCellToggleMoreActionViewItem } from 'sql/workbench/contrib/notebook/browser/notebookViews/notebookViewsActions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { CellTypes } from 'sql/workbench/services/notebook/common/contracts'; import { AngularDisposable } from 'sql/base/browser/lifecycle'; @@ -31,8 +30,6 @@ export class NotebookViewsCardComponent extends AngularDisposable implements OnI private _executionState: CellExecutionState; private _pendingReinitialize: boolean = false; - public _cellToggleMoreActions: ViewCellToggleMoreActions; - @Input() card: INotebookViewCard; @Input() cells: ICellModel[]; @Input() model: NotebookModel; @@ -121,7 +118,14 @@ export class NotebookViewsCardComponent extends AngularDisposable implements OnI this._actionbar.dispose(); } - this._actionbar = new Taskbar(this._actionbarRef.nativeElement); + this._actionbar = new Taskbar(this._actionbarRef.nativeElement, { + actionViewItemProvider: action => { + if (action.id === ViewCellToggleMoreAction.ID) { + return this._instantiationService.createInstance(ViewCellToggleMoreActionViewItem, action, this._actionbar.actionRunner, context); + } + return undefined; + } + }); this._actionbar.context = { target: this._actionbarRef.nativeElement }; if (this.cell.cellType === CellTypes.Code) { @@ -132,10 +136,8 @@ export class NotebookViewsCardComponent extends AngularDisposable implements OnI let hideButton = new HideCellAction(this.hide, this); taskbarContent.push({ action: hideButton }); - let moreActionsContainer = DOM.$('li.action-item'); - this._cellToggleMoreActions = this._instantiationService.createInstance(ViewCellToggleMoreActions); - this._cellToggleMoreActions.onInit(moreActionsContainer, context); - taskbarContent.push({ element: moreActionsContainer }); + const viewCellToggleMoreAction = this._instantiationService.createInstance(ViewCellToggleMoreAction); + taskbarContent.push({ action: viewCellToggleMoreAction }); this._actionbar.setContent(taskbarContent); } diff --git a/src/sql/workbench/contrib/notebook/common/notebookLoc.ts b/src/sql/workbench/contrib/notebook/common/notebookLoc.ts new file mode 100644 index 0000000000..15c9c78a99 --- /dev/null +++ b/src/sql/workbench/contrib/notebook/common/notebookLoc.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; + +export const moreActionsLabel = localize('moreActionsLabel', "More"); diff --git a/src/sql/workbench/contrib/notebook/test/browser/cellToolbarActions.test.ts b/src/sql/workbench/contrib/notebook/test/browser/cellToolbarActions.test.ts index 2fd418e6ed..a2e7e49142 100644 --- a/src/sql/workbench/contrib/notebook/test/browser/cellToolbarActions.test.ts +++ b/src/sql/workbench/contrib/notebook/test/browser/cellToolbarActions.test.ts @@ -5,7 +5,7 @@ import * as TypeMoq from 'typemoq'; import * as assert from 'assert'; -import { CellToggleMoreActions, RunCellsAction, removeDuplicatedAndStartingSeparators, AddCellFromContextAction, CollapseCellAction, ConvertCellAction } from 'sql/workbench/contrib/notebook/browser/cellToolbarActions'; +import { CellToggleMoreActionViewItem, RunCellsAction, removeDuplicatedAndStartingSeparators, AddCellFromContextAction, CollapseCellAction, ConvertCellAction, CellToggleMoreAction } from 'sql/workbench/contrib/notebook/browser/cellToolbarActions'; import { NotebookService } from 'sql/workbench/services/notebook/browser/notebookServiceImpl'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; @@ -16,7 +16,6 @@ import { NullAdsTelemetryService } from 'sql/platform/telemetry/common/adsTeleme import { CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions'; import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService'; import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; -import * as DOM from 'vs/base/browser/dom'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService'; import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell'; @@ -147,21 +146,16 @@ suite('CellToolbarActions', function (): void { instantiationService.stub(IContextMenuService, TypeMoq.Mock.ofType(ContextMenuService).object); }); - test('CellToggleMoreActions with Code CellType', function (): void { - const testContainer = DOM.$('div'); + test('CellToggleMoreActionViewItem with Code CellType displays correct number of actions', function (): void { cellModelMock.setup(x => x.cellType).returns(() => 'code'); - const action = new CellToggleMoreActions(instantiationService); - action.onInit(testContainer, contextMock.object); - assert.strictEqual(action['_moreActions']['viewItems'][0]['_action']['_actions'].length, 18, 'Unexpected number of valid elements'); + const action = new CellToggleMoreActionViewItem(new CellToggleMoreAction(), undefined, contextMock.object, undefined, instantiationService); + assert.equal(action.getValidActions().length, 18); }); - test('CellToggleMoreActions with Markdown CellType', function (): void { - const testContainer = DOM.$('div'); + test('CellToggleMoreActionViewItem with Markdown CellType displays correct number of actions', function (): void { cellModelMock.setup(x => x.cellType).returns(() => 'markdown'); - const action = new CellToggleMoreActions(instantiationService); - action.onInit(testContainer, contextMock.object); - // Markdown elements don't show the code-cell related actions such as Run Cell - assert.strictEqual(action['_moreActions']['viewItems'][0]['_action']['_actions'].length, 7, 'Unexpected number of valid elements'); + const action = new CellToggleMoreActionViewItem(new CellToggleMoreAction(), undefined, contextMock.object, undefined, instantiationService); + assert.equal(action.getValidActions().length, 7); }); });