diff --git a/extensions/machine-learning-services/src/test/views/utils.ts b/extensions/machine-learning-services/src/test/views/utils.ts index b3b4ece492..3264e86a89 100644 --- a/extensions/machine-learning-services/src/test/views/utils.ts +++ b/extensions/machine-learning-services/src/test/views/utils.ts @@ -228,7 +228,8 @@ export function createViewContext(): ViewTestContext { fileBrowserTree: undefined!, hyperlink: () => hyperLinkBuilder, tabbedPanel: undefined!, - separator: undefined! + separator: undefined!, + propertiesContainer: undefined! } }; let tab: azdata.window.DialogTab = { diff --git a/extensions/notebook/src/test/managePackages/managePackagesDialog.test.ts b/extensions/notebook/src/test/managePackages/managePackagesDialog.test.ts index 46e5df1798..45ad130a0a 100644 --- a/extensions/notebook/src/test/managePackages/managePackagesDialog.test.ts +++ b/extensions/notebook/src/test/managePackages/managePackagesDialog.test.ts @@ -281,7 +281,8 @@ describe('Manage Package Dialog', () => { fileBrowserTree: undefined!, hyperlink: undefined!, tabbedPanel: undefined!, - separator: undefined! + separator: undefined!, + propertiesContainer: undefined! } }; diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index 99a6db0f29..2f6443ad99 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -129,6 +129,7 @@ declare module 'azdata' { radioCardGroup(): ComponentBuilder; tabbedPanel(): TabbedPanelComponentBuilder; separator(): ComponentBuilder; + propertiesContainer(): ComponentBuilder; } export interface RadioCard { @@ -305,6 +306,41 @@ declare module 'azdata' { required?: boolean; } + /** + * A property to be displayed in the PropertiesContainerComponent + */ + export interface PropertiesContainerItem { + /** + * The name of the property to display + */ + displayName: string; + /** + * The value of the property to display + */ + value: string; + } + + /** + * Component to display a list of property values. + */ + export interface PropertiesContainerComponent extends Component, PropertiesContainerComponentProperties { + + } + + /** + * Properties for configuring a PropertiesContainerComponent + */ + export interface PropertiesContainerComponentProperties { + /** + * The properties to display + */ + propertyItems?: PropertiesContainerItem[]; + /** + * Whether the component is currently loading + */ + loading?: boolean; + } + export namespace nb { /** * An event that is emitted when the active Notebook editor is changed. diff --git a/src/sql/platform/dashboard/browser/interfaces.ts b/src/sql/platform/dashboard/browser/interfaces.ts index b619a69f74..ffa897709c 100644 --- a/src/sql/platform/dashboard/browser/interfaces.ts +++ b/src/sql/platform/dashboard/browser/interfaces.ts @@ -127,5 +127,6 @@ export enum ModelComponentTypes { Image, RadioCardGroup, TabbedPanel, - Separator + Separator, + PropertiesContainer } diff --git a/src/sql/workbench/api/common/extHostModelView.ts b/src/sql/workbench/api/common/extHostModelView.ts index ebde4907a6..8f84f624b4 100644 --- a/src/sql/workbench/api/common/extHostModelView.ts +++ b/src/sql/workbench/api/common/extHostModelView.ts @@ -256,6 +256,14 @@ class ModelBuilderImpl implements azdata.ModelBuilder { return builder; } + propertiesContainer(): azdata.ComponentBuilder { + let id = this.getNextComponentId(); + let builder: ComponentBuilderImpl = this.getComponentBuilder(new PropertiesContainerComponentWrapper(this._proxy, this._handle, id), id); + + this._componentBuilders.set(id, builder); + return builder; + } + getComponentBuilder(component: ComponentWrapper, id: string): ComponentBuilderImpl { let componentBuilder: ComponentBuilderImpl = new ComponentBuilderImpl(component); this._componentBuilders.set(id, componentBuilder); @@ -1746,6 +1754,27 @@ class TabbedPanelComponentWrapper extends ComponentWrapper implements azdata.Tab } } +class PropertiesContainerComponentWrapper extends ComponentWrapper implements azdata.PropertiesContainerComponent { + constructor(proxy: MainThreadModelViewShape, handle: number, id: string) { + super(proxy, handle, ModelComponentTypes.PropertiesContainer, id); + this.properties = {}; + } + + public get propertyItems(): azdata.PropertiesContainerItem[] { + return this.properties['propertyItems']; + } + public set propertyItems(v: azdata.PropertiesContainerItem[]) { + this.setProperty('propertyItems', v); + } + + public get loading(): boolean { + return this.properties['loading']; + } + public set loading(v: boolean) { + this.setProperty('loading', v); + } +} + class GroupContainerComponentWrapper extends ComponentWrapper implements azdata.GroupContainer { constructor(proxy: MainThreadModelViewShape, handle: number, type: ModelComponentTypes, id: string) { super(proxy, handle, type, id); diff --git a/src/sql/workbench/api/common/sqlExtHostTypes.ts b/src/sql/workbench/api/common/sqlExtHostTypes.ts index 963ce57fad..2e2835e8fe 100644 --- a/src/sql/workbench/api/common/sqlExtHostTypes.ts +++ b/src/sql/workbench/api/common/sqlExtHostTypes.ts @@ -175,7 +175,8 @@ export enum ModelComponentTypes { Image, RadioCardGroup, TabbedPanel, - Separator + Separator, + PropertiesContainer } export enum ColumnSizingMode { diff --git a/src/sql/workbench/browser/modelComponents/propertiesContainer.component.ts b/src/sql/workbench/browser/modelComponents/propertiesContainer.component.ts new file mode 100644 index 0000000000..245d2eafda --- /dev/null +++ b/src/sql/workbench/browser/modelComponents/propertiesContainer.component.ts @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { + Component, Input, Inject, ChangeDetectorRef, forwardRef, + ViewChild, ElementRef, OnDestroy +} from '@angular/core'; + +import * as azdata from 'azdata'; +import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase'; +import { IComponent, IComponentDescriptor, IModelStore } from 'sql/platform/dashboard/browser/interfaces'; +import { PropertiesContainer, DisplayProperty } from 'sql/base/browser/ui/propertiesContainer/propertiesContainer.component'; + +@Component({ + selector: `modelview-properties-container`, + template: ` + + ` +}) +export default class PropertiesContainerComponent extends ComponentBase implements IComponent, OnDestroy { + @Input() descriptor: IComponentDescriptor; + @Input() modelStore: IModelStore; + + @ViewChild(PropertiesContainer) private _propertiesContainer: PropertiesContainer; + constructor( + @Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef, + @Inject(forwardRef(() => ElementRef)) el: ElementRef, + ) { + super(changeRef, el); + } + + ngOnInit(): void { + this.baseInit(); + } + + setLayout(layout: any): void { + this.layout(); + } + + public setProperties(properties: { [key: string]: any; }): void { + super.setProperties(properties); + this._propertiesContainer.displayProperties = this.displayProperties; + this._propertiesContainer.loading = this.loading; + } + + public get loading(): boolean { + return this.getPropertyOrDefault((props) => props.loading, true); + } + + public set loading(newValue: boolean) { + this.setPropertyFromUI((props, value) => props.loading = value, newValue); + this._propertiesContainer.loading = newValue; + } + + public get displayProperties(): DisplayProperty[] { + return this.getPropertyOrDefault((props) => props.displayProperties, []); + } + + public set displayProperties(newValue: azdata.PropertiesContainerItem[]) { + this.setPropertyFromUI((props, value) => props.displayProperties = value, newValue); + this._propertiesContainer.displayProperties = newValue; + } +} diff --git a/src/sql/workbench/contrib/modelView/browser/components.contribution.ts b/src/sql/workbench/contrib/modelView/browser/components.contribution.ts index b8c97bf717..fad2d992ed 100644 --- a/src/sql/workbench/contrib/modelView/browser/components.contribution.ts +++ b/src/sql/workbench/contrib/modelView/browser/components.contribution.ts @@ -33,6 +33,7 @@ import RadioCardGroup from 'sql/workbench/browser/modelComponents/radioCardGroup import TabbedPanelComponent from 'sql/workbench/browser/modelComponents/tabbedPanel.component'; import SeparatorComponent from 'sql/workbench/browser/modelComponents/separator.component'; import { ModelComponentTypes } from 'sql/platform/dashboard/browser/interfaces'; +import PropertiesContainerComponent from 'sql/workbench/browser/modelComponents/propertiesContainer.component'; export const DIV_CONTAINER = 'div-container'; registerComponentType(DIV_CONTAINER, ModelComponentTypes.DivContainer, DivContainer); @@ -63,7 +64,7 @@ registerComponentType(DROPDOWN_COMPONENT, ModelComponentTypes.DropDown, DropDown export const DECLARATIVETABLE_COMPONENT = 'declarativeTable-component'; registerComponentType(DECLARATIVETABLE_COMPONENT, ModelComponentTypes.DeclarativeTable, DeclarativeTableComponent); -export const LISTBOX_COMPONENT = 'lisbox-component'; +export const LISTBOX_COMPONENT = 'listbox-component'; registerComponentType(LISTBOX_COMPONENT, ModelComponentTypes.ListBox, ListBoxComponent); export const BUTTON_COMPONENT = 'button-component'; @@ -117,3 +118,6 @@ registerComponentType(TABBEDPANEL_COMPONENT, ModelComponentTypes.TabbedPanel, Ta export const SEPARATOR_COMPONENT = 'separator-component'; registerComponentType(SEPARATOR_COMPONENT, ModelComponentTypes.Separator, SeparatorComponent); + +export const PROPERTIESCONTAINER_COMPONENT = 'propertiescontainer-component'; +registerComponentType(PROPERTIESCONTAINER_COMPONENT, ModelComponentTypes.PropertiesContainer, PropertiesContainerComponent); diff --git a/src/sql/workbench/services/dialog/browser/dialog.module.ts b/src/sql/workbench/services/dialog/browser/dialog.module.ts index 129272c1b3..e82f25f430 100644 --- a/src/sql/workbench/services/dialog/browser/dialog.module.ts +++ b/src/sql/workbench/services/dialog/browser/dialog.module.ts @@ -28,6 +28,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IBootstrapParams, ISelector } from 'sql/workbench/services/bootstrap/common/bootstrapParams'; import { startsWith } from 'vs/base/common/strings'; import { PanelModule } from 'sql/base/browser/ui/panel/panel.module'; +import { PropertiesContainerModule } from 'sql/base/browser/ui/propertiesContainer/propertiesContainer.module'; export const DialogModule = (params, selector: string, instantiationService: IInstantiationService): any => { @@ -52,7 +53,8 @@ export const DialogModule = (params, selector: string, instantiationService: IIn FormsModule, CommonModule, BrowserModule, - PanelModule + PanelModule, + PropertiesContainerModule ], providers: [ { provide: APP_BASE_HREF, useValue: '/' },