More layering and strictness (#9004)

* move handling generated files to the serilization classes

* remove unneeded methods

* add more folders to strictire compile, add more strict compile options

* update ci

* wip

* add more layering and fix issues

* add more strictness

* remove unnecessary assertion

* add missing checks

* fix indentation

* wip

* remove jsdoc

* fix layering

* fix compile

* fix compile errors

* wip

* wip

* finish layering

* fix css

* more layering

* remove no longer good parts

* fix issues with startup

* another try

* fix startup
This commit is contained in:
Anthony Dresser
2020-02-11 00:47:17 -06:00
committed by GitHub
parent 3a8b74a311
commit 0f934081e1
97 changed files with 489 additions and 214 deletions

View File

@@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import DivContainer from 'sql/workbench/browser/modelComponents/divContainer.component';
import FlexContainer from 'sql/workbench/browser/modelComponents/flexContainer.component';
import FormContainer from 'sql/workbench/browser/modelComponents/formContainer.component';
import ToolbarContainer from 'sql/workbench/browser/modelComponents/toolbarContainer.component';
import GroupContainer from 'sql/workbench/browser/modelComponents/groupContainer.component';
import CardComponent from 'sql/workbench/browser/modelComponents/card.component';
import InputBoxComponent from 'sql/workbench/browser/modelComponents/inputbox.component';
import DropDownComponent from 'sql/workbench/browser/modelComponents/dropdown.component';
import DeclarativeTableComponent from 'sql/workbench/browser/modelComponents/declarativeTable.component';
import ListBoxComponent from 'sql/workbench/browser/modelComponents/listbox.component';
import ButtonComponent from 'sql/workbench/browser/modelComponents/button.component';
import CheckBoxComponent from 'sql/workbench/browser/modelComponents/checkbox.component';
import TreeComponent from 'sql/workbench/browser/modelComponents/tree.component';
import RadioButtonComponent from 'sql/workbench/browser/modelComponents/radioButton.component';
import WebViewComponent from 'sql/workbench/contrib/modelView/browser/webview.component';
import TableComponent from 'sql/workbench/browser/modelComponents/table.component';
import TextComponent from 'sql/workbench/browser/modelComponents/text.component';
import ImageComponent from 'sql/workbench/browser/modelComponents/image.component';
import LoadingComponent from 'sql/workbench/browser/modelComponents/loadingComponent.component';
import FileBrowserTreeComponent from 'sql/workbench/browser/modelComponents/fileBrowserTree.component';
import EditorComponent from 'sql/workbench/browser/modelComponents/editor.component';
import DiffEditorComponent from 'sql/workbench/browser/modelComponents/diffeditor.component';
import DomComponent from 'sql/workbench/browser/modelComponents/dom.component';
import { registerComponentType } from 'sql/platform/dashboard/browser/modelComponentRegistry';
import HyperlinkComponent from 'sql/workbench/browser/modelComponents/hyperlink.component';
import SplitViewContainer from 'sql/workbench/browser/modelComponents/splitviewContainer.component';
import RadioCardGroup from 'sql/workbench/browser/modelComponents/radioCardGroup.component';
import { ModelComponentTypes } from 'sql/platform/dashboard/browser/interfaces';
export const DIV_CONTAINER = 'div-container';
registerComponentType(DIV_CONTAINER, ModelComponentTypes.DivContainer, DivContainer);
export const FLEX_CONTAINER = 'flex-container';
registerComponentType(FLEX_CONTAINER, ModelComponentTypes.FlexContainer, FlexContainer);
export const SPLITVIEW_CONTAINER = 'splitView-container';
registerComponentType(SPLITVIEW_CONTAINER, ModelComponentTypes.SplitViewContainer, SplitViewContainer);
export const FORM_CONTAINER = 'form-container';
registerComponentType(FORM_CONTAINER, ModelComponentTypes.Form, FormContainer);
export const TOOLBAR_CONTAINER = 'toolbar-container';
registerComponentType(TOOLBAR_CONTAINER, ModelComponentTypes.Toolbar, ToolbarContainer);
export const GROUP_CONTAINER = 'group-container';
registerComponentType(GROUP_CONTAINER, ModelComponentTypes.Group, GroupContainer);
export const CARD_COMPONENT = 'card-component';
registerComponentType(CARD_COMPONENT, ModelComponentTypes.Card, CardComponent);
export const INPUTBOX_COMPONENT = 'inputbox-component';
registerComponentType(INPUTBOX_COMPONENT, ModelComponentTypes.InputBox, InputBoxComponent);
export const DROPDOWN_COMPONENT = 'dropdown-component';
registerComponentType(DROPDOWN_COMPONENT, ModelComponentTypes.DropDown, DropDownComponent);
export const DECLARATIVETABLE_COMPONENT = 'declarativeTable-component';
registerComponentType(DECLARATIVETABLE_COMPONENT, ModelComponentTypes.DeclarativeTable, DeclarativeTableComponent);
export const LISTBOX_COMPONENT = 'lisbox-component';
registerComponentType(LISTBOX_COMPONENT, ModelComponentTypes.ListBox, ListBoxComponent);
export const BUTTON_COMPONENT = 'button-component';
registerComponentType(BUTTON_COMPONENT, ModelComponentTypes.Button, ButtonComponent);
export const CHECKBOX_COMPONENT = 'checkbox-component';
registerComponentType(CHECKBOX_COMPONENT, ModelComponentTypes.CheckBox, CheckBoxComponent);
export const RADIOBUTTON_COMPONENT = 'radiobutton-component';
registerComponentType(RADIOBUTTON_COMPONENT, ModelComponentTypes.RadioButton, RadioButtonComponent);
export const WEBVIEW_COMPONENT = 'webview-component';
registerComponentType(WEBVIEW_COMPONENT, ModelComponentTypes.WebView, WebViewComponent);
export const TEXT_COMPONENT = 'text-component';
registerComponentType(TEXT_COMPONENT, ModelComponentTypes.Text, TextComponent);
export const IMAGE_COMPONENT = 'image-component';
registerComponentType(IMAGE_COMPONENT, ModelComponentTypes.Image, ImageComponent);
export const TABLE_COMPONENT = 'table-component';
registerComponentType(TABLE_COMPONENT, ModelComponentTypes.Table, TableComponent);
export const LOADING_COMPONENT = 'loading-component';
registerComponentType(LOADING_COMPONENT, ModelComponentTypes.LoadingComponent, LoadingComponent);
export const TREE_COMPONENT = 'tree-component';
registerComponentType(TREE_COMPONENT, ModelComponentTypes.TreeComponent, TreeComponent);
export const FILEBROWSERTREE_COMPONENT = 'filebrowsertree-component';
registerComponentType(FILEBROWSERTREE_COMPONENT, ModelComponentTypes.FileBrowserTree, FileBrowserTreeComponent);
export const EDITOR_COMPONENT = 'editor-component';
registerComponentType(EDITOR_COMPONENT, ModelComponentTypes.Editor, EditorComponent);
export const DIFF_EDITOR_COMPONENT = 'diff-editor-component';
registerComponentType(DIFF_EDITOR_COMPONENT, ModelComponentTypes.DiffEditor, DiffEditorComponent);
export const DOM_COMPONENT = 'dom-component';
registerComponentType(DOM_COMPONENT, ModelComponentTypes.Dom, DomComponent);
export const HYPERLINK_COMPONENT = 'hyperlink-component';
registerComponentType(HYPERLINK_COMPONENT, ModelComponentTypes.Hyperlink, HyperlinkComponent);
export const RADIOCARDGROUP_COMPONENT = 'radiocardgroup-component';
registerComponentType(RADIOCARDGROUP_COMPONENT, ModelComponentTypes.RadioCardGroup, RadioCardGroup);

View File

@@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
modelview-webview-component {
height: 100%;
width : 100%;
display: block;
}

View File

@@ -0,0 +1,221 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/webview';
import {
Component, Input, Inject, ChangeDetectorRef, forwardRef, ElementRef, OnDestroy
} from '@angular/core';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { WebviewContentOptions, IWebviewService, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
import { generateUuid } from 'vs/base/common/uuid';
import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase';
import { ComponentEventType, IModelStore, IComponentDescriptor, IComponent } from 'sql/platform/dashboard/browser/interfaces';
function reviveWebviewOptions(options: vscode.WebviewOptions): vscode.WebviewOptions {
return {
...options,
localResourceRoots: Array.isArray(options.localResourceRoots) ? options.localResourceRoots.map(URI.revive) : undefined
};
}
@Component({
template: '',
selector: 'modelview-webview-component'
})
export default class WebViewComponent extends ComponentBase implements IComponent, OnDestroy {
@Input() descriptor: IComponentDescriptor;
@Input() modelStore: IModelStore;
private static readonly standardSupportedLinkSchemes = ['http', 'https', 'mailto'];
private _webview: WebviewElement;
private _renderedHtml: string;
private _extensionLocationUri: URI;
private _ready: Promise<void>;
protected contextKey: IContextKey<boolean>;
protected findInputFocusContextKey: IContextKey<boolean>;
private readonly id = generateUuid();
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
@Inject(IOpenerService) private readonly _openerService: IOpenerService,
@Inject(IWorkspaceContextService) private readonly _contextService: IWorkspaceContextService,
@Inject(IWebviewService) private readonly webviewService: IWebviewService
) {
super(changeRef, el);
}
ngOnInit(): void {
this.baseInit();
this._createWebview();
this._register(addDisposableListener(window, EventType.RESIZE, e => {
this.layout();
}));
}
private _createWebview(): void {
this._webview = this.webviewService.createWebview(this.id,
{},
{
allowScripts: true
});
this._webview.mountTo(this._el.nativeElement);
this._ready = new Promise(resolve => {
let webview = (<any>this._webview)._webview;
const subscription = this._register(addDisposableListener(webview, 'ipc-message', (event) => {
if (event.channel === 'webview-ready') {
subscription.dispose();
resolve();
}
}));
});
this._ready.then(() => {
this._register(this._webview.onDidClickLink(link => this.onDidClickLink(URI.parse(link))));
this._register(this._webview.onMessage(e => {
this.fireEvent({
eventType: ComponentEventType.onMessage,
args: e
});
}));
this.setHtml();
});
}
ngOnDestroy(): void {
this.baseDestroy();
}
/// Webview Functions
private setHtml(): void {
if (this._webview && this.html) {
this._renderedHtml = this.html;
this._webview.html = this._renderedHtml;
}
}
private sendMessage(): void {
if (this._webview && this.message) {
this._webview.sendMessage(this.message);
}
}
private onDidClickLink(link: URI): any {
if (!link) {
return;
}
if (WebViewComponent.standardSupportedLinkSchemes.indexOf(link.scheme) >= 0 || this.enableCommandUris && link.scheme === 'command') {
this._openerService.open(link);
}
}
private get enableCommandUris(): boolean {
if (this.options && this.options.enableCommandUris) {
return true;
}
return false;
}
/// IComponent implementation
public layout(): void {
if (this._ready) {
this._ready.then(() => {
let element = <HTMLElement>this._el.nativeElement;
element.style.position = this.position;
});
}
}
public setLayout(layout: any): void {
// TODO allow configuring the look and feel
this.layout();
}
public setProperties(properties: { [key: string]: any; }): void {
if (this._ready) {
this._ready.then(() => {
super.setProperties(properties);
if (this.options) {
this._webview.contentOptions = this.getExtendedOptions();
}
if (this.html !== this._renderedHtml) {
this.setHtml();
}
if (this.extensionLocation) {
this._extensionLocationUri = URI.revive(this.extensionLocation);
}
this.sendMessage();
});
}
}
// CSS-bound properties
public get message(): any {
return this.getPropertyOrDefault<azdata.WebViewProperties, any>((props) => props.message, undefined);
}
public set message(newValue: any) {
this.setPropertyFromUI<azdata.WebViewProperties, any>((properties, message) => { properties.message = message; }, newValue);
}
public get html(): string {
return this.getPropertyOrDefault<azdata.WebViewProperties, string>((props) => props.html, undefined);
}
public set html(newValue: string) {
this.setPropertyFromUI<azdata.WebViewProperties, string>((properties, html) => { properties.html = html; }, newValue);
}
public get options(): vscode.WebviewOptions {
return this.getPropertyOrDefault<azdata.WebViewProperties, vscode.WebviewOptions>((props) => props.options, undefined);
}
public get extensionLocation(): UriComponents {
return this.getPropertyOrDefault<azdata.WebViewProperties, UriComponents>((props) => props.extensionLocation, undefined);
}
private get extensionLocationUri(): URI {
if (!this._extensionLocationUri && this.extensionLocation) {
this._extensionLocationUri = URI.revive(this.extensionLocation);
}
return this._extensionLocationUri;
}
private getExtendedOptions(): WebviewContentOptions {
let options = this.options || { enableScripts: true };
options = reviveWebviewOptions(options);
return {
allowScripts: options.enableScripts,
localResourceRoots: options.localResourceRoots || this.getDefaultLocalResourceRoots()
};
}
private getDefaultLocalResourceRoots(): URI[] {
const rootPaths = this._contextService.getWorkspace().folders.map(x => x.uri);
if (this.extensionLocationUri) {
rootPaths.push(this.extensionLocationUri);
}
return rootPaths;
}
}