mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-19 17:22:48 -05:00
Add validation to model view components (#1356)
This commit is contained in:
@@ -11,9 +11,11 @@ import { ModelViewContent } from 'sql/parts/modelComponents/modelViewContent.com
|
||||
import { BootstrapParams } from 'sql/services/bootstrap/bootstrapParams';
|
||||
import { BOOTSTRAP_SERVICE_ID, IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { ComponentEventType } from '../../parts/modelComponents/interfaces';
|
||||
|
||||
export interface DialogComponentParams extends BootstrapParams {
|
||||
modelViewId: string;
|
||||
validityChangedCallback: (valid: boolean) => void;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@@ -27,16 +29,23 @@ export interface DialogComponentParams extends BootstrapParams {
|
||||
export class DialogContainer implements AfterContentInit {
|
||||
private _onResize = new Emitter<void>();
|
||||
public readonly onResize: Event<void> = this._onResize.event;
|
||||
private _params: DialogComponentParams;
|
||||
|
||||
public modelViewId: string;
|
||||
@ViewChild(ModelViewContent) private _modelViewContent: ModelViewContent;
|
||||
constructor(
|
||||
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
|
||||
@Inject(BOOTSTRAP_SERVICE_ID) bootstrapService: IBootstrapService) {
|
||||
this.modelViewId = (bootstrapService.getBootstrapParams(el.nativeElement.tagName) as DialogComponentParams).modelViewId;
|
||||
this._params = bootstrapService.getBootstrapParams(el.nativeElement.tagName) as DialogComponentParams;
|
||||
this.modelViewId = this._params.modelViewId;
|
||||
}
|
||||
|
||||
ngAfterContentInit(): void {
|
||||
this._modelViewContent.onEvent(event => {
|
||||
if (event.eventType === ComponentEventType.validityChanged) {
|
||||
this._params.validityChangedCallback(event.args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public layout(): void {
|
||||
|
||||
@@ -21,6 +21,8 @@ import { attachButtonStyler } from 'vs/platform/theme/common/styler';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { localize } from 'vs/nls';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
|
||||
export class DialogModal extends Modal {
|
||||
private _dialogPane: DialogPane;
|
||||
@@ -102,8 +104,10 @@ export class DialogModal extends Modal {
|
||||
}
|
||||
|
||||
public done(): void {
|
||||
this.dispose();
|
||||
this.hide();
|
||||
if (this._dialog.okButton.enabled) {
|
||||
this.dispose();
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
public cancel(): void {
|
||||
@@ -119,6 +123,20 @@ export class DialogModal extends Modal {
|
||||
super.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridable to change behavior of escape key
|
||||
*/
|
||||
protected onClose(e: StandardKeyboardEvent) {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridable to change behavior of enter key
|
||||
*/
|
||||
protected onAccept(e: StandardKeyboardEvent) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
this._dialogPane.dispose();
|
||||
|
||||
@@ -16,12 +16,16 @@ import { DialogComponentParams } from 'sql/platform/dialog/dialogContainer.compo
|
||||
import { Builder } from 'vs/base/browser/builder';
|
||||
import { IThemable } from 'vs/platform/theme/common/styler';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export class DialogPane extends Disposable implements IThemable {
|
||||
private _activeTabIndex: number;
|
||||
private _tabbedPanel: TabbedPanel;
|
||||
private _moduleRef: NgModuleRef<{}>;
|
||||
|
||||
// Validation
|
||||
private _modelViewValidityMap = new Map<string, boolean>();
|
||||
|
||||
// HTML Elements
|
||||
private _body: HTMLElement;
|
||||
private _tabBar: HTMLElement;
|
||||
@@ -46,12 +50,20 @@ export class DialogPane extends Disposable implements IThemable {
|
||||
} else {
|
||||
this._tabbedPanel = new TabbedPanel(this._body);
|
||||
this._dialog.content.forEach((tab, tabIndex) => {
|
||||
let tabContainer = document.createElement('div');
|
||||
tabContainer.style.display = 'none';
|
||||
this._body.appendChild(tabContainer);
|
||||
this.initializeModelViewContainer(tabContainer, tab.content);
|
||||
this._tabbedPanel.pushTab({
|
||||
title: tab.title,
|
||||
identifier: 'dialogPane.' + this._dialog.title + '.' + tabIndex,
|
||||
view: {
|
||||
render: (container) => {
|
||||
this.initializeModelViewContainer(container, tab.content);
|
||||
if (tabContainer.parentElement === this._body) {
|
||||
this._body.removeChild(tabContainer);
|
||||
}
|
||||
container.appendChild(tabContainer);
|
||||
tabContainer.style.display = 'block';
|
||||
},
|
||||
layout: (dimension) => { }
|
||||
} as IPanelView
|
||||
@@ -72,7 +84,10 @@ export class DialogPane extends Disposable implements IThemable {
|
||||
DialogModule,
|
||||
bodyContainer,
|
||||
'dialog-modelview-container',
|
||||
{ modelViewId: modelViewId } as DialogComponentParams,
|
||||
{
|
||||
modelViewId: modelViewId,
|
||||
validityChangedCallback: (valid: boolean) => this._setValidity(modelViewId, valid)
|
||||
} as DialogComponentParams,
|
||||
undefined,
|
||||
(moduleRef) => this._moduleRef = moduleRef);
|
||||
}
|
||||
@@ -93,6 +108,21 @@ export class DialogPane extends Disposable implements IThemable {
|
||||
this._body.style.color = styles.dialogForeground ? styles.dialogForeground.toString() : undefined;
|
||||
}
|
||||
|
||||
private _setValidity(modelViewId: string, valid: boolean) {
|
||||
let oldValidity = this.isValid();
|
||||
this._modelViewValidityMap.set(modelViewId, valid);
|
||||
let newValidity = this.isValid();
|
||||
if (newValidity !== oldValidity) {
|
||||
this._dialog.notifyValidityChanged(newValidity);
|
||||
}
|
||||
}
|
||||
|
||||
private isValid(): boolean {
|
||||
let valid = true;
|
||||
this._modelViewValidityMap.forEach(value => valid = valid && value);
|
||||
return valid;
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
super.dispose();
|
||||
this._moduleRef.destroy();
|
||||
|
||||
@@ -28,11 +28,24 @@ export class Dialog implements sqlops.window.modelviewdialog.Dialog {
|
||||
public cancelButton: DialogButton = new DialogButton(Dialog.CANCEL_BUTTON_LABEL, true);
|
||||
public customButtons: DialogButton[];
|
||||
|
||||
private _valid: boolean = true;
|
||||
private _validityChangedEmitter = new Emitter<boolean>();
|
||||
public readonly onValidityChanged = this._validityChangedEmitter.event;
|
||||
|
||||
constructor(public title: string, content?: string | DialogTab[]) {
|
||||
if (content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
||||
public get valid(): boolean {
|
||||
return this._valid;
|
||||
}
|
||||
|
||||
public notifyValidityChanged(valid: boolean) {
|
||||
this._valid = valid;
|
||||
this._validityChangedEmitter.fire(valid);
|
||||
}
|
||||
}
|
||||
|
||||
export class DialogButton implements sqlops.window.modelviewdialog.Button {
|
||||
|
||||
Reference in New Issue
Block a user