Added clear output to ToggleMoreAction and added it to markdown preview (#3535)

* Added toggleMoreActions to Markdown Preview only.
When it is in editor mode, only editor display ToggleMoreActions.

* Added clear output back
This commit is contained in:
Yurong He
2018-12-10 11:17:35 -08:00
committed by GitHub
parent 568f95e7a3
commit ded073edd9
9 changed files with 171 additions and 102 deletions

View File

@@ -0,0 +1,127 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ElementRef } from '@angular/core';
import { nb } from 'sqlops';
import { localize } from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { getErrorMessage } from 'vs/base/common/errors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { CellContext, CellActionBase } from 'sql/parts/notebook/cellViews/codeActions';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
import { ToggleMoreWidgetAction } from 'sql/parts/dashboard/common/actions';
import { CellTypes, CellType } from 'sql/parts/notebook/models/contracts';
import { CellModel } from 'sql/parts/notebook/models/cell';
export class CellToggleMoreActions {
private _actions: Action[] = [];
private _moreActions: ActionBar;
constructor(
@IInstantiationService private instantiationService: IInstantiationService) {
this._actions.push(
instantiationService.createInstance(DeleteCellAction, 'delete', localize('delete', 'Delete')),
instantiationService.createInstance(AddCellFromContextAction,'codeBefore', localize('codeBefore', 'Insert Code before'), CellTypes.Code, false),
instantiationService.createInstance(AddCellFromContextAction, 'codeAfter', localize('codeAfter', 'Insert Code after'), CellTypes.Code, true),
instantiationService.createInstance(AddCellFromContextAction, 'markdownBefore', localize('markdownBefore', 'Insert Markdown before'), CellTypes.Markdown, false),
instantiationService.createInstance(AddCellFromContextAction, 'markdownAfter', localize('markdownAfter', 'Insert Markdown after'), CellTypes.Markdown, true),
instantiationService.createInstance(ClearCellOutputAction, 'clear', localize('clear', 'Clear output'))
);
}
public toggle(showIcon: boolean, elementRef: ElementRef, model: NotebookModel, cellModel: ICellModel) {
let context = new CellContext(model,cellModel);
let moreActionsElement = <HTMLElement>elementRef.nativeElement;
if (showIcon) {
if (moreActionsElement.childNodes.length > 0) {
moreActionsElement.removeChild(moreActionsElement.childNodes[0]);
}
this._moreActions = new ActionBar(moreActionsElement, { orientation: ActionsOrientation.VERTICAL });
this._moreActions.context = { target: moreActionsElement };
this._moreActions.push(this.instantiationService.createInstance(ToggleMoreWidgetAction, this._actions, context), { icon: showIcon, label: false });
}
else if (moreActionsElement.childNodes.length > 0) {
moreActionsElement.removeChild(moreActionsElement.childNodes[0]);
}
}
}
export class AddCellFromContextAction extends CellActionBase {
constructor(
id: string, label: string, private cellType: CellType, private isAfter: boolean,
@INotificationService notificationService: INotificationService
) {
super(id, label, undefined, notificationService);
}
runCellAction(context: CellContext): Promise<void> {
try {
let model = context.model;
let index = model.cells.findIndex((cell) => cell.id === context.cell.id);
if (index !== undefined && this.isAfter) {
index += 1;
}
model.addCell(this.cellType, index);
} catch (error) {
let message = getErrorMessage(error);
this.notificationService.notify({
severity: Severity.Error,
message: message
});
}
return Promise.resolve();
}
}
export class DeleteCellAction extends CellActionBase {
constructor(id: string, label: string,
@INotificationService notificationService: INotificationService
) {
super(id, label, undefined, notificationService);
}
runCellAction(context: CellContext): Promise<void> {
try {
context.model.deleteCell(context.cell);
} catch (error) {
let message = getErrorMessage(error);
this.notificationService.notify({
severity: Severity.Error,
message: message
});
}
return Promise.resolve();
}
}
export class ClearCellOutputAction extends CellActionBase {
constructor(id: string, label: string,
@INotificationService notificationService: INotificationService
) {
super(id, label, undefined, notificationService);
}
runCellAction(context: CellContext): Promise<void> {
try {
(context.model.activeCell as CellModel).clearOutputs();
} catch (error) {
let message = getErrorMessage(error);
this.notificationService.notify({
severity: Severity.Error,
message: message
});
}
return Promise.resolve();
}
}

View File

@@ -9,6 +9,6 @@
</div>
<div #editor class="editor" style="flex: 1 1 auto; overflow: hidden;">
</div>
<div #moreactions class="toolbar" style="flex: 0 0 auto; display: flex; flex-flow:column; width: 20px; min-height: 20px; max-height: 20px; padding-top: 0px; orientation: portrait">
<div #moreactions class="moreActions" style="flex: 0 0 auto; display: flex; flex-flow:column;width: 20px; min-height: 20px; max-height: 20px; padding-top: 0px; orientation: portrait">
</div>
</div>

View File

@@ -4,11 +4,16 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./code';
import { OnInit, Component, Input, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, Output, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
import { OnInit, Component, Input, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, Output, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { AngularDisposable } from 'sql/base/common/lifecycle';
import { QueryTextEditor } from 'sql/parts/modelComponents/queryTextEditor';
import { CellToggleMoreActions } from 'sql/parts/notebook/cellToggleMoreActions';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { RunCellAction, CellContext } from 'sql/parts/notebook/cellViews/codeActions';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import * as themeColors from 'vs/workbench/common/theme';
@@ -19,20 +24,11 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { ITextModel } from 'vs/editor/common/model';
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
import URI from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { Schemas } from 'vs/base/common/network';
import * as DOM from 'vs/base/browser/dom';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { RunCellAction, DeleteCellAction, AddCellAction, CellContext } from 'sql/parts/notebook/cellViews/codeActions';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
import { ToggleMoreWidgetAction } from 'sql/parts/dashboard/common/actions';
import { CellTypes } from 'sql/parts/notebook/models/contracts';
import { INotificationService } from 'vs/platform/notification/common/notification';
export const CODE_SELECTOR: string = 'code-component';
@@ -59,15 +55,14 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
}
protected _actionBar: Taskbar;
protected _moreActions: ActionBar;
private readonly _minimumHeight = 30;
private _editor: QueryTextEditor;
private _editorInput: UntitledEditorInput;
private _editorModel: ITextModel;
private _uri: string;
private _model: NotebookModel;
private _actions: Action[] = [];
private _activeCellId: string;
private _cellToggleMoreActions: CellToggleMoreActions;
constructor(
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrapService: CommonServiceInterface,
@@ -81,13 +76,7 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
@Inject(INotificationService) private notificationService: INotificationService,
) {
super();
this._actions.push(
this._instantiationService.createInstance(AddCellAction, 'codeBefore', localize('codeBefore', 'Insert Code before'), CellTypes.Code, false),
this._instantiationService.createInstance(AddCellAction, 'codeAfter', localize('codeAfter', 'Insert Code after'), CellTypes.Code, true),
this._instantiationService.createInstance(AddCellAction, 'markdownBefore', localize('markdownBefore', 'Insert Markdown before'), CellTypes.Markdown, false),
this._instantiationService.createInstance(AddCellAction, 'markdownAfter', localize('markdownAfter', 'Insert Markdown after'), CellTypes.Markdown, true),
this._instantiationService.createInstance(DeleteCellAction, 'delete', localize('delete', 'Delete'))
);
this._cellToggleMoreActions = this._instantiationService.createInstance(CellToggleMoreActions);
}
ngOnInit() {
@@ -105,10 +94,10 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
if (propName === 'activeCellId') {
let changedProp = changes[propName];
if (this.cellModel.id === changedProp.currentValue) {
this.toggleMoreActions(true);
this._cellToggleMoreActions.toggle(true, this.moreActionsElementRef, this.model, this.cellModel);
}
else {
this.toggleMoreActions(false);
this._cellToggleMoreActions.toggle(false, this.moreActionsElementRef, this.model, this.cellModel);
}
break;
}
@@ -173,21 +162,6 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
]);
}
private toggleMoreActions(showIcon: boolean) {
let context = new CellContext(this.model, this.cellModel);
let moreActionsElement = <HTMLElement>this.moreActionsElementRef.nativeElement;
if (showIcon) {
if (moreActionsElement.childNodes.length > 0) {
moreActionsElement.removeChild(moreActionsElement.childNodes[0]);
}
this._moreActions = new ActionBar(moreActionsElement, { orientation: ActionsOrientation.VERTICAL });
this._moreActions.context = { target: moreActionsElement };
this._moreActions.push(this._instantiationService.createInstance(ToggleMoreWidgetAction, this._actions, context), { icon: showIcon, label: false });
}
else if (moreActionsElement.childNodes.length > 0) {
moreActionsElement.removeChild(moreActionsElement.childNodes[0]);
}
}
private createUri(): URI {
let uri = URI.from({ scheme: Schemas.untitled, path: `notebook-editor-${this.cellModel.id}` });

View File

@@ -45,10 +45,6 @@ code-component .carbon-taskbar .icon {
width: 40px;
}
code-component .action-label.icon.toggle-more {
height: 20px;
width: 20px;
}
code-component .carbon-taskbar.monaco-toolbar .monaco-action-bar.animated .actions-container
{

View File

@@ -40,7 +40,7 @@ export class CellContext {
}
}
abstract class CellActionBase extends Action {
export abstract class CellActionBase extends Action {
constructor(id: string, label: string, icon: string, protected notificationService: INotificationService) {
super(id, label, icon);
@@ -135,53 +135,3 @@ export class RunCellAction extends ToggleableAction {
return clientSession.kernel;
}
}
export class AddCellAction extends CellActionBase {
constructor(
id: string, label: string, private cellType: CellType, private isAfter: boolean,
@INotificationService notificationService: INotificationService
) {
super(id, label, undefined, notificationService);
}
runCellAction(context: CellContext): Promise<void> {
try {
let model = context.model;
let index = model.cells.findIndex((cell) => cell.id === context.cell.id);
if (index !== undefined && this.isAfter) {
index += 1;
}
model.addCell(this.cellType, index);
} catch (error) {
let message = getErrorMessage(error);
this.notificationService.notify({
severity: Severity.Error,
message: message
});
}
return Promise.resolve();
}
}
export class DeleteCellAction extends CellActionBase {
constructor(id: string, label: string,
@INotificationService notificationService: INotificationService
) {
super(id, label, undefined, notificationService);
}
runCellAction(context: CellContext): Promise<void> {
try {
context.model.deleteCell(context.cell);
} catch (error) {
let message = getErrorMessage(error);
this.notificationService.notify({
severity: Severity.Error,
message: message
});
}
return Promise.resolve();
}
}

View File

@@ -10,6 +10,10 @@
<code-component *ngIf="isEditMode" [cellModel]="cellModel" (onContentChanged)="handleContentChanged()" [model]="model" [activeCellId]="activeCellId" [hideVerticalToolbar]=true>
</code-component>
</div>
<div #preview style="flex: 0 0 auto; user-select: initial;" (dblclick)="toggleEditMode()">
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: row">
<div #preview style="flex: 1 1 auto; user-select: initial;" (dblclick)="toggleEditMode()">
</div>
<div #moreactions class="moreActions" style="flex: 0 0 auto; display: flex; flex-flow:column;width: 20px; min-height: 20px; max-height: 20px; padding-top: 0px; orientation: portrait">
</div>
</div>
</div>

View File

@@ -6,20 +6,22 @@ import 'vs/css!./textCell';
import { OnInit, Component, Input, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, OnChanges, SimpleChange } from '@angular/core';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { CellView } from 'sql/parts/notebook/cellViews/interfaces';
import { localize } from 'vs/nls';
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import * as themeColors from 'vs/workbench/common/theme';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { ISanitizer, defaultSanitizer } from 'sql/parts/notebook/outputs/sanitizer';
import { localize } from 'vs/nls';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Emitter } from 'vs/base/common/event';
import URI from 'vs/base/common/uri';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { CellView } from 'sql/parts/notebook/cellViews/interfaces';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { ISanitizer, defaultSanitizer } from 'sql/parts/notebook/outputs/sanitizer';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
import { CellToggleMoreActions } from 'sql/parts/notebook/cellToggleMoreActions';
export const TEXT_SELECTOR: string = 'text-cell-component';
@Component({
@@ -28,6 +30,7 @@ export const TEXT_SELECTOR: string = 'text-cell-component';
})
export class TextCellComponent extends CellView implements OnInit, OnChanges {
@ViewChild('preview', { read: ElementRef }) private output: ElementRef;
@ViewChild('moreactions', { read: ElementRef }) private moreActionsElementRef: ElementRef;
@Input() cellModel: ICellModel;
@Input() set model(value: NotebookModel) {
@@ -46,10 +49,12 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
private readonly _onDidClickLink = this._register(new Emitter<URI>());
public readonly onDidClickLink = this._onDidClickLink.event;
protected isLoading: boolean;
private _cellToggleMoreActions: CellToggleMoreActions;
constructor(
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrapService: CommonServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(IInstantiationService) private _instantiationService: IInstantiationService,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(ICommandService) private _commandService: ICommandService,
@Inject(IOpenerService) private readonly openerService: IOpenerService,
@@ -57,6 +62,7 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
super();
this.isEditMode = false;
this.isLoading = true;
this._cellToggleMoreActions = this._instantiationService.createInstance(CellToggleMoreActions);
}
//Gets sanitizer from ISanitizer interface
@@ -137,6 +143,9 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
private updateTheme(theme: IColorTheme): void {
let outputElement = <HTMLElement>this.output.nativeElement;
outputElement.style.borderTopColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
let moreActionsEl = <HTMLElement>this.moreActionsElementRef.nativeElement;
moreActionsEl.style.borderRightColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
}
public handleContentChanged(): void {
@@ -145,7 +154,12 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
public toggleEditMode(editMode?: boolean): void {
this.isEditMode = editMode !== undefined? editMode : !this.isEditMode;
if (!this.isEditMode && this.cellModel.id === this._activeCellId) {
this._cellToggleMoreActions.toggle(true, this.moreActionsElementRef, this.model, this.cellModel);
}
else {
this._cellToggleMoreActions.toggle(false, this.moreActionsElementRef, this.model, this.cellModel);
}
this.updatePreview();
this._changeRef.detectChanges();
}

View File

@@ -74,4 +74,9 @@
.vs-dark .notebookEditor .notebook-button.icon-save,
.hc-black .notebookEditor .notebook-button.icon-save{
background-image: url("./media/dark/save_inverse.svg");
}
.moreActions .action-label.icon.toggle-more {
height: 20px;
width: 20px;
}

View File

@@ -26,7 +26,6 @@ const attachToLabel: string = localize('AttachTo', 'Attach to: ');
const msgLoadingContexts = localize('loadingContexts', 'Loading contexts...');
const msgAddNewConnection = localize('addNewConnection', 'Add new connection');
const msgSelectConnection = localize('selectConnection', 'Select connection');
const msgConnectionNotApplicable = localize('connectionNotSupported', 'n/a');
const msgLocalHost = localize('localhost', 'Localhost');
// Action to add a cell to notebook based on cell type(code/markdown).