Added categories and search based filtering to the resource dialog. (#12658)

* added filtering to the resource type along with a new component.

* -Added caching of cards
-Removed unused component props
-localized tags
-limited the scope of list items

* Made some changes in the PR

* - Added Iot Category to SQL edge
- Moved category names to constants
- Moved localization strings to localized constants
- Made filtering logic more concise
- Changed how category list is generated
--Category list can now be ordered
-Added back event generation for selectedCard

* Fixed bugs, and some additional changes
-Fixed radiogroup height to avoid the movement of options below it
-Restoring the focus back to the search and listview components
- Added focus behaviour for listview
- Fixed a typo in comment

* Made categories an Enum

* Added localized string

* localized category string
converted categories to enum.

* made the filtering logic more concise.

* returning string if no localized string formed
removed unnecessary returns

* fixed the filtering tag logic
resetting search when category is changed

* removing the iot tag from sql edge deployment

* made filtering logic more concise
made enum const

* added vscode list

* some cleanup

* Some PR changes
- Made PR camelcase
- added comments to SQL
- removed unnecessary export

* -Some PR related changes
-Removing unsupported style property
-scoping down css and removing unused ones.

* Fixed a comment text

* Fixed typings for listview event
This commit is contained in:
Aasim Khan
2020-10-07 13:38:12 -07:00
committed by GitHub
parent 830cef06db
commit 280a9d20f9
18 changed files with 512 additions and 28 deletions

View File

@@ -0,0 +1,4 @@
<div role="listbox" class="modelview-listview-container" [ngStyle]="styles" [style.width]="width" [style.height]="height">
<div *ngIf="title" class="modelview-listview-title">{{title.text}}</div>
<div #vscodelist> </div>
</div>

View File

@@ -0,0 +1,192 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ChangeDetectorRef, Component, ElementRef, forwardRef, Inject, Input, OnDestroy, ViewChild } from '@angular/core';
import * as azdata from 'azdata';
import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase';
import * as DOM from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IListOptions, List } from 'vs/base/browser/ui/list/listWidget';
import 'vs/css!./media/listView';
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/platform/dashboard/browser/interfaces';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
@Component({
templateUrl: decodeURI(require.toUrl('./listView.component.html'))
})
export default class ListViewComponent extends ComponentBase<azdata.ListViewComponentProperties> implements IComponent, OnDestroy {
@Input() descriptor: IComponentDescriptor;
@Input() modelStore: IModelStore;
@ViewChild('vscodelist', { read: ElementRef }) private _vscodeList: ElementRef;
private _optionsList!: List<azdata.ListViewOption>;
private _selectedElementIdx!: number;
static ROW_HEIGHT = 26;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
) {
super(changeRef, el);
}
ngOnInit(): void {
this.baseInit();
}
ngAfterViewInit(): void {
const vscodelistOption: IListOptions<azdata.ListViewOption> = {
keyboardSupport: true,
mouseSupport: true,
smoothScrolling: true,
verticalScrollMode: ScrollbarVisibility.Auto,
};
this._optionsList = new List<azdata.ListViewOption>('ModelViewListView', this._vscodeList.nativeElement, new OptionListDelegate(ListViewComponent.ROW_HEIGHT), [new OptionsListRenderer()], vscodelistOption);
this._register(attachListStyler(this._optionsList, this.themeService));
this._register(this._optionsList.onDidChangeSelection((e) => {
if (e.indexes.length !== 0) {
this.selectOptionByIdx(e.indexes[0]);
}
}));
this._register(this._optionsList.onKeyDown((event: any) => {
if (!this.enabled || this.options.length === 0) {
return;
}
let e = new StandardKeyboardEvent(event);
if (e.keyCode === KeyCode.Space) {
this._optionsList.setSelection([this._optionsList.getFocus()[0]]);
DOM.EventHelper.stop(e, true);
}
}));
}
setLayout(layout: any): void {
this.layout();
}
ngOnDestroy(): void {
this.baseDestroy();
}
public get options(): azdata.ListViewOption[] {
return this.getProperties().options ?? [];
}
public get width(): string | number | undefined {
return this.getProperties().width ?? undefined;
}
public get height(): string | number | undefined {
return this.getProperties().height ?? undefined;
}
public get styles(): azdata.CssStyles | undefined {
return this.getProperties().CSSStyles ?? undefined;
}
public get title(): azdata.ListViewTitle {
return this.getProperties().title ?? undefined;
}
public get selectedOptionId(): string | undefined {
return this.getProperties().selectedOptionId ?? undefined;
}
public setProperties(properties: { [key: string]: any }) {
super.setProperties(properties);
if (this.options) {
this._optionsList!.splice(0, this._optionsList!.length, this.options);
let height = (<number>this.height) ?? (this.options.length * ListViewComponent.ROW_HEIGHT);
this._optionsList.layout(height);
}
// This is the entry point for the extension to set the selectedOptionId
if (this.selectedOptionId) {
this._optionsList.setSelection([this.options.map(v => v.id).indexOf(this.selectedOptionId)]);
}
}
public selectOptionByIdx(idx: number): void {
if (!this.enabled || this.options.length === 0) {
return;
}
this._selectedElementIdx = idx;
const selectedOption = this.options[idx];
this.setPropertyFromUI<string | undefined>((props, value) => props.selectedOptionId = value, selectedOption.id);
this.fireEvent({
eventType: ComponentEventType.onDidClick,
args: {
id: selectedOption.id
}
});
}
public focus(): void {
super.focus();
if (this._selectedElementIdx !== undefined) {
this._optionsList.domFocus();
const focusElement = (this._selectedElementIdx === undefined) ? 0 : this._selectedElementIdx;
this._optionsList.setFocus([focusElement]);
}
}
}
class OptionListDelegate implements IListVirtualDelegate<azdata.ListViewOption> {
constructor(
private _height: number
) {
}
public getHeight(element: azdata.ListViewOption): number {
return this._height;
}
public getTemplateId(element: azdata.ListViewOption): string {
return 'optionListRenderer';
}
}
interface ExtensionListTemplate {
root: HTMLElement;
}
class OptionsListRenderer implements IListRenderer<azdata.ListViewOption, ExtensionListTemplate> {
public static TEMPLATE_ID = 'optionListRenderer';
public get templateId(): string {
return OptionsListRenderer.TEMPLATE_ID;
}
public renderTemplate(container: HTMLElement): ExtensionListTemplate {
const tableTemplate: ExtensionListTemplate = Object.create(null);
tableTemplate.root = DOM.append(container, DOM.$('div.list-row.listview-option'));
return tableTemplate;
}
public renderElement(option: azdata.ListViewOption, index: number, templateData: ExtensionListTemplate): void {
templateData.root.innerText = option.label ?? '';
}
public disposeTemplate(template: ExtensionListTemplate): void {
// noop
}
public disposeElement(element: azdata.ListViewOption, index: number, templateData: ExtensionListTemplate): void {
// noop
}
}

View File

@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.modelview-listview-container {
display: flex;
flex-direction: column;
height: 100%;
max-width: 150px;
min-width: 120px;
font-size: 100%;
font-weight: inherit;
overflow: auto;
padding: 0 0 0 0;
font-size: 12px;
}
.modelview-listview-container .modelview-listview-title {
margin: 0 5px 5px 0;
font-weight: bold;
line-height: 16px;
padding: 5px 0px 5px 5px;
}
.modelview-listview-container .listview-option {
line-height: 16px;
width: 95%;
padding: 5px 0px 5px 5px;
}