mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
tasks widget updates (#9860)
* fix toolbar and remove tasks widget * update refresh action * remove contribution * fix missing learn more menu item * Alanren/refresh widgets new (#9863) * refresh widgets * dashboard refresh * update
This commit is contained in:
@@ -235,8 +235,10 @@ export class DashboardGridContainer extends DashboardTab implements OnDestroy {
|
|||||||
widget.rowspan = '1';
|
widget.rowspan = '1';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.rows = this.createIndexes(this._contents.map(w => w.row));
|
if (this._contents.length > 0) {
|
||||||
this.cols = this.createIndexes(this._contents.map(w => w.col));
|
this.rows = this.createIndexes(this._contents.map(w => w.row));
|
||||||
|
this.cols = this.createIndexes(this._contents.map(w => w.col));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,4 +69,9 @@ export class DashboardHomeContainer extends DashboardWidgetContainer {
|
|||||||
this._scrollable.layout();
|
this._scrollable.layout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public refresh(): void {
|
||||||
|
super.refresh();
|
||||||
|
this._propertiesClass.refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import { AngularDisposable } from 'sql/base/browser/lifecycle';
|
|||||||
/* Widgets */
|
/* Widgets */
|
||||||
import { PropertiesWidgetComponent } from 'sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component';
|
import { PropertiesWidgetComponent } from 'sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component';
|
||||||
import { ExplorerWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.component';
|
import { ExplorerWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.component';
|
||||||
import { TasksWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/tasks/tasksWidget.component';
|
|
||||||
import { InsightsWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/insights/insightsWidget.component';
|
import { InsightsWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/insights/insightsWidget.component';
|
||||||
import { WebviewWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/webview/webviewWidget.component';
|
import { WebviewWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/webview/webviewWidget.component';
|
||||||
|
|
||||||
@@ -42,7 +41,6 @@ import { IColorTheme } from 'vs/platform/theme/common/themeService';
|
|||||||
const componentMap: { [x: string]: Type<IDashboardWidget> } = {
|
const componentMap: { [x: string]: Type<IDashboardWidget> } = {
|
||||||
'properties-widget': PropertiesWidgetComponent,
|
'properties-widget': PropertiesWidgetComponent,
|
||||||
'explorer-widget': ExplorerWidget,
|
'explorer-widget': ExplorerWidget,
|
||||||
'tasks-widget': TasksWidget,
|
|
||||||
'insights-widget': InsightsWidget,
|
'insights-widget': InsightsWidget,
|
||||||
'webview-widget': WebviewWidget
|
'webview-widget': WebviewWidget
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
// tslint:disable:no-unused-variable
|
// tslint:disable:no-unused-variable
|
||||||
private readonly homeTabTitle: string = nls.localize('home', "Home");
|
private readonly homeTabTitle: string = nls.localize('home', "Home");
|
||||||
private readonly homeTabId: string = 'homeTab';
|
private readonly homeTabId: string = 'homeTab';
|
||||||
private tabToolbarActionsConfig = new Map<string, WidgetConfig>();
|
private tabToolbarActionsConfig = new Map<string, any[]>();
|
||||||
private tabContents = new Map<string, string>();
|
private tabContents = new Map<string, string>();
|
||||||
|
|
||||||
static tabName = new RawContextKey<string>('tabName', undefined);
|
static tabName = new RawContextKey<string>('tabName', undefined);
|
||||||
@@ -145,12 +145,7 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let tempWidgets = this.dashboardService.getSettings<Array<WidgetConfig>>([this.context, 'widgets'].join('.'));
|
let tempWidgets = this.dashboardService.getSettings<Array<WidgetConfig>>([this.context, 'widgets'].join('.'));
|
||||||
// remove tasks widget because those will be shown in the toolbar
|
this.processTasksWidgets(tempWidgets, this.homeTabId);
|
||||||
const index = tempWidgets.findIndex(c => c.widget['tasks-widget']);
|
|
||||||
if (index !== -1) {
|
|
||||||
tempWidgets.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._originalConfig = objects.deepClone(tempWidgets);
|
this._originalConfig = objects.deepClone(tempWidgets);
|
||||||
let properties = this.getProperties();
|
let properties = this.getProperties();
|
||||||
this._configModifiers.forEach((cb) => {
|
this._configModifiers.forEach((cb) => {
|
||||||
@@ -170,8 +165,6 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.showToolbar = true;
|
this.showToolbar = true;
|
||||||
const homeToolbarConfig = this.dashboardService.getSettings<Array<WidgetConfig>>([this.context, 'widgets'].join('.'))[0].widget['tasks-widget'];
|
|
||||||
this.tabToolbarActionsConfig.set(this.homeTabId, homeToolbarConfig);
|
|
||||||
this.createToolbar(this.toolbarContainer.nativeElement, this.homeTabId);
|
this.createToolbar(this.toolbarContainer.nativeElement, this.homeTabId);
|
||||||
|
|
||||||
this._register(this.themeService.onDidColorThemeChange((event: IColorTheme) => {
|
this._register(this.themeService.onDidColorThemeChange((event: IColorTheme) => {
|
||||||
@@ -179,58 +172,52 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private getExtensionContributedHomeToolbarContent(content: ITaskbarContent[]): void {
|
private getContributedTasks(tabId: string): ITaskbarContent[] {
|
||||||
let primary: IAction[] = [];
|
const tasks: ITaskbarContent[] = [];
|
||||||
let secondary: IAction[] = [];
|
// for now we only allow contributing to the home tab toolbar.
|
||||||
const menu = this.menuService.createMenu(MenuId.DashboardToolbar, this.contextKeyService);
|
if (tabId === this.homeTabId) {
|
||||||
let groups = menu.getActions({ arg: null, shouldForwardArgs: true });
|
let primary: IAction[] = [];
|
||||||
fillInActions(groups, { primary, secondary }, false, (group: string) => group === undefined || group === '');
|
let secondary: IAction[] = [];
|
||||||
|
const menu = this.menuService.createMenu(MenuId.DashboardToolbar, this.contextKeyService);
|
||||||
|
let groups = menu.getActions({ arg: null, shouldForwardArgs: true });
|
||||||
|
fillInActions(groups, { primary, secondary }, false, (group: string) => group === undefined || group === '');
|
||||||
|
|
||||||
primary.forEach(a => {
|
primary.forEach(a => {
|
||||||
if (a instanceof MenuItemAction) {
|
if (a instanceof MenuItemAction) {
|
||||||
// Need to ensure that we don't add the same action multiple times
|
// Need to ensure that we don't add the same action multiple times
|
||||||
let foundIndex = firstIndex(content, act => act.action && act.action.id === a.id);
|
let foundIndex = firstIndex(tasks, act => act.action && act.action.id === a.id);
|
||||||
if (foundIndex < 0) {
|
if (foundIndex < 0) {
|
||||||
content.push({ action: a });
|
tasks.push({ action: a });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (primary.length > 0) {
|
||||||
|
let separator: HTMLElement = Taskbar.createTaskbarSeparator();
|
||||||
|
tasks.push({ element: separator });
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (primary.length > 0) {
|
|
||||||
let separator: HTMLElement = Taskbar.createTaskbarSeparator();
|
|
||||||
content.push({ element: separator });
|
|
||||||
}
|
}
|
||||||
|
return tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasExtensionContributedToolbarContent(): boolean {
|
private createToolbar(parentElement: HTMLElement, tabId: string): void {
|
||||||
let primary: IAction[] = [];
|
|
||||||
let secondary: IAction[] = [];
|
|
||||||
const menu = this.menuService.createMenu(MenuId.DashboardToolbar, this.contextKeyService);
|
|
||||||
let groups = menu.getActions({ arg: null, shouldForwardArgs: true });
|
|
||||||
fillInActions(groups, { primary, secondary }, false, (group: string) => group === undefined || group === '');
|
|
||||||
return primary.length > 0 || secondary.length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private createToolbar(parentElement: HTMLElement, tabName: string): void {
|
|
||||||
// clear out toolbar
|
// clear out toolbar
|
||||||
DOM.clearNode(parentElement);
|
DOM.clearNode(parentElement);
|
||||||
this.toolbar = this._register(new Taskbar(parentElement, { actionViewItemProvider: action => this.createActionItemProvider(action as Action) }));
|
this.toolbar = this._register(new Taskbar(parentElement, { actionViewItemProvider: action => this.createActionItemProvider(action as Action) }));
|
||||||
|
|
||||||
let content = [];
|
let content = [];
|
||||||
content = this.getToolbarContent(this.tabToolbarActionsConfig.get(tabName));
|
content = this.getToolbarContent(tabId);
|
||||||
|
if (tabId === this.homeTabId) {
|
||||||
if (tabName === this.homeTabId) {
|
|
||||||
const configureDashboardCommand = MenuRegistry.getCommand('configureDashboard');
|
const configureDashboardCommand = MenuRegistry.getCommand('configureDashboard');
|
||||||
const configureDashboardAction = new ToolbarAction(configureDashboardCommand.id, configureDashboardCommand.title.toString(), TaskRegistry.getOrCreateTaskIconClassName(configureDashboardCommand), this.runAction, this, this.logService);
|
const configureDashboardAction = new ToolbarAction(configureDashboardCommand.id, configureDashboardCommand.title.toString(), TaskRegistry.getOrCreateTaskIconClassName(configureDashboardCommand), this.runAction, this, this.logService);
|
||||||
content.push({ action: configureDashboardAction });
|
content.push({ action: configureDashboardAction });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toolbar.setContent(content);
|
this.toolbar.setContent(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getToolbarContent(toolbarTasks: WidgetConfig): ITaskbarContent[] {
|
private getToolbarContent(tabId: string): ITaskbarContent[] {
|
||||||
|
const toolbarTasks = this.tabToolbarActionsConfig.get(tabId);
|
||||||
let tasks = TaskRegistry.getTasks();
|
let tasks = TaskRegistry.getTasks();
|
||||||
let content;
|
let content = [];
|
||||||
if (types.isArray(toolbarTasks) && toolbarTasks.length > 0) {
|
if (types.isArray(toolbarTasks) && toolbarTasks.length > 0) {
|
||||||
tasks = toolbarTasks.map(i => {
|
tasks = toolbarTasks.map(i => {
|
||||||
if (types.isString(i)) {
|
if (types.isString(i)) {
|
||||||
@@ -250,9 +237,12 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get extension actions contributed to the page's toolbar
|
// get extension actions contributed to the page's toolbar
|
||||||
this.getExtensionContributedHomeToolbarContent(content);
|
const contributedTasks = this.getContributedTasks(tabId);
|
||||||
|
content.push(...contributedTasks);
|
||||||
|
|
||||||
const refreshAction = new RefreshWidgetAction(this.refresh, this);
|
const refreshAction = new RefreshWidgetAction(() => {
|
||||||
|
this.refresh();
|
||||||
|
}, this);
|
||||||
content.push({ action: refreshAction });
|
content.push({ action: refreshAction });
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
@@ -456,12 +446,7 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
configs = cb.apply(this, [configs]);
|
configs = cb.apply(this, [configs]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove tasks widget because the tasks will be shown in the toolbar
|
this.processTasksWidgets(configs, value.id);
|
||||||
const index = configs.findIndex(c => c.widget['tasks-widget']);
|
|
||||||
if (index !== -1) {
|
|
||||||
this.tabToolbarActionsConfig.set(value.id, configs[index].widget['tasks-widget']);
|
|
||||||
configs.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key === WIDGETS_CONTAINER) {
|
if (key === WIDGETS_CONTAINER) {
|
||||||
return { id: value.id, title: value.title, container: { 'widgets-container': configs }, alwaysShow: value.alwaysShow, iconClass: value.iconClass };
|
return { id: value.id, title: value.title, container: { 'widgets-container': configs }, alwaysShow: value.alwaysShow, iconClass: value.iconClass };
|
||||||
@@ -473,6 +458,28 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
return { id: value.id, title: value.title, container: containerResult.container, alwaysShow: value.alwaysShow, iconClass: value.iconClass };
|
return { id: value.id, title: value.title, container: containerResult.container, alwaysShow: value.alwaysShow, iconClass: value.iconClass };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the tasks widgets, tasks widgets has been deprecated and the tasks are now in toolbar.
|
||||||
|
* @param widgets widgets
|
||||||
|
* @param tabId tab id
|
||||||
|
*/
|
||||||
|
private processTasksWidgets(widgets: WidgetConfig[], tabId: string): void {
|
||||||
|
let index;
|
||||||
|
const allTasks = [];
|
||||||
|
// do this in a while loop since there might be multiple tasks widgets in a tab
|
||||||
|
do {
|
||||||
|
index = widgets.findIndex(c => c.widget['tasks-widget']);
|
||||||
|
if (index !== -1) {
|
||||||
|
const tasks = widgets[index].widget['tasks-widget'];
|
||||||
|
if (Array.isArray(tasks)) {
|
||||||
|
allTasks.push(...tasks);
|
||||||
|
}
|
||||||
|
widgets.splice(index, 1);
|
||||||
|
}
|
||||||
|
} while (index !== -1);
|
||||||
|
this.tabToolbarActionsConfig.set(tabId, allTasks);
|
||||||
|
}
|
||||||
|
|
||||||
protected getContentType(tab: TabConfig): string {
|
protected getContentType(tab: TabConfig): string {
|
||||||
return tab.container ? Object.keys(tab.container)[0] : '';
|
return tab.container ? Object.keys(tab.container)[0] : '';
|
||||||
}
|
}
|
||||||
@@ -525,8 +532,7 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
public handleTabChange(tab: TabComponent): void {
|
public handleTabChange(tab: TabComponent): void {
|
||||||
this._tabName.set(tab.identifier);
|
this._tabName.set(tab.identifier);
|
||||||
const tabContent = this.tabContents.get(tab.identifier);
|
const tabContent = this.tabContents.get(tab.identifier);
|
||||||
if (tab.identifier === this.homeTabId || tabContent === WIDGETS_CONTAINER || tabContent === GRID_CONTAINER || tabContent === NAV_SECTION
|
if (tab.identifier === this.homeTabId || tabContent === WIDGETS_CONTAINER || tabContent === GRID_CONTAINER || tabContent === NAV_SECTION) {
|
||||||
|| this.hasExtensionContributedToolbarContent()) {
|
|
||||||
this.showToolbar = true;
|
this.showToolbar = true;
|
||||||
this.createToolbar(this.toolbarContainer.nativeElement, tab.identifier);
|
this.createToolbar(this.toolbarContainer.nativeElement, tab.identifier);
|
||||||
} else { // hide toolbar
|
} else { // hide toolbar
|
||||||
@@ -534,9 +540,6 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._cd.detectChanges();
|
this._cd.detectChanges();
|
||||||
const localtab = this._tabs.find(i => i.id === tab.identifier);
|
|
||||||
this._editEnabled.fire(localtab.editable);
|
|
||||||
this._cd.detectChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public handleTabClose(tab: TabComponent): void {
|
public handleTabClose(tab: TabComponent): void {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { InjectionToken, OnDestroy } from '@angular/core';
|
import { InjectionToken, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
||||||
import { NgGridItemConfig } from 'angular2-grid';
|
import { NgGridItemConfig } from 'angular2-grid';
|
||||||
import { Action } from 'vs/base/common/actions';
|
import { Action } from 'vs/base/common/actions';
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
@@ -63,6 +63,14 @@ export interface TabSettingConfig {
|
|||||||
|
|
||||||
export abstract class DashboardWidget extends Disposable implements OnDestroy {
|
export abstract class DashboardWidget extends Disposable implements OnDestroy {
|
||||||
protected _config: WidgetConfig;
|
protected _config: WidgetConfig;
|
||||||
|
protected _loading: boolean;
|
||||||
|
protected _inited: boolean = false;
|
||||||
|
protected _loadingMessage: string;
|
||||||
|
protected _loadingCompletedMessage: string;
|
||||||
|
|
||||||
|
constructor(protected _changeRef: ChangeDetectorRef) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
get actions(): Array<Action> {
|
get actions(): Array<Action> {
|
||||||
return [];
|
return [];
|
||||||
@@ -71,4 +79,11 @@ export abstract class DashboardWidget extends Disposable implements OnDestroy {
|
|||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.dispose();
|
this.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected setLoadingStatus(loading: boolean): void {
|
||||||
|
this._loading = loading;
|
||||||
|
if (this._inited) {
|
||||||
|
this._changeRef.detectChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ const pageComponents = [ServerDashboardPage, DatabaseDashboardPage];
|
|||||||
/* Widget Components */
|
/* Widget Components */
|
||||||
import { PropertiesWidgetComponent } from 'sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component';
|
import { PropertiesWidgetComponent } from 'sql/workbench/contrib/dashboard/browser/widgets/properties/propertiesWidget.component';
|
||||||
import { ExplorerWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.component';
|
import { ExplorerWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.component';
|
||||||
import { TasksWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/tasks/tasksWidget.component';
|
|
||||||
import { InsightsWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/insights/insightsWidget.component';
|
import { InsightsWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/insights/insightsWidget.component';
|
||||||
import { WebviewWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/webview/webviewWidget.component';
|
import { WebviewWidget } from 'sql/workbench/contrib/dashboard/browser/widgets/webview/webviewWidget.component';
|
||||||
import { JobStepsViewComponent } from 'sql/workbench/contrib/jobManagement/browser/jobStepsView.component';
|
import { JobStepsViewComponent } from 'sql/workbench/contrib/jobManagement/browser/jobStepsView.component';
|
||||||
@@ -93,7 +92,6 @@ import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
|||||||
const widgetComponents = [
|
const widgetComponents = [
|
||||||
PropertiesWidgetComponent,
|
PropertiesWidgetComponent,
|
||||||
ExplorerWidget,
|
ExplorerWidget,
|
||||||
TasksWidget,
|
|
||||||
InsightsWidget,
|
InsightsWidget,
|
||||||
WebviewWidget
|
WebviewWidget
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -4,11 +4,12 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
-->
|
-->
|
||||||
<div class="explorer-widget" style="display: flex; flex-flow: column; position: absolute; height:100%; width:100%; padding: 10px; box-sizing: border-box">
|
<div class="explorer-widget"
|
||||||
|
style="display: flex; flex-flow: column; position: absolute; height:100%; width:100%; padding: 10px; box-sizing: border-box">
|
||||||
<div #input style="width: 100%"></div>
|
<div #input style="width: 100%"></div>
|
||||||
<div style="flex: 1 1 auto; position: relative">
|
<div style="flex: 1 1 auto; position: relative">
|
||||||
<loading-spinner [loading]="loading" [loadingMessage]="loadingMessage"
|
<loading-spinner [loading]="_loading" [loadingMessage]="_loadingMessage"
|
||||||
[loadingCompletedMessage]="loadingCompletedMessage"></loading-spinner>
|
[loadingCompletedMessage]="_loadingCompletedMessage"></loading-spinner>
|
||||||
<div #table style="position: absolute; height: 100%; width: 100%"></div>
|
<div #table style="position: absolute; height: 100%; width: 100%"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -47,11 +47,6 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
private _treeDataSource = new ExplorerDataSource();
|
private _treeDataSource = new ExplorerDataSource();
|
||||||
private _treeFilter = new ExplorerFilter();
|
private _treeFilter = new ExplorerFilter();
|
||||||
|
|
||||||
private _inited = false;
|
|
||||||
public loading: boolean = false;
|
|
||||||
public loadingMessage: string;
|
|
||||||
public loadingCompletedMessage: string;
|
|
||||||
|
|
||||||
@ViewChild('input') private _inputContainer: ElementRef;
|
@ViewChild('input') private _inputContainer: ElementRef;
|
||||||
@ViewChild('table') private _tableContainer: ElementRef;
|
@ViewChild('table') private _tableContainer: ElementRef;
|
||||||
|
|
||||||
@@ -64,11 +59,11 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
@Inject(IContextViewService) private readonly contextViewService: IContextViewService,
|
@Inject(IContextViewService) private readonly contextViewService: IContextViewService,
|
||||||
@Inject(IInstantiationService) private readonly instantiationService: IInstantiationService,
|
@Inject(IInstantiationService) private readonly instantiationService: IInstantiationService,
|
||||||
@Inject(ICapabilitiesService) private readonly capabilitiesService: ICapabilitiesService,
|
@Inject(ICapabilitiesService) private readonly capabilitiesService: ICapabilitiesService,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private readonly _cd: ChangeDetectorRef
|
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef
|
||||||
) {
|
) {
|
||||||
super();
|
super(changeRef);
|
||||||
this.loadingMessage = this._config.context === 'database' ? nls.localize('loadingObjects', "loading objects") : nls.localize('loadingDatabases', "loading databases");
|
this._loadingMessage = this._config.context === 'database' ? nls.localize('loadingObjects', "loading objects") : nls.localize('loadingDatabases', "loading databases");
|
||||||
this.loadingCompletedMessage = this._config.context === 'database' ? nls.localize('loadingObjectsCompleted', "loading objects completed.") : nls.localize('loadingDatabasesCompleted', "loading databases completed.");
|
this._loadingCompletedMessage = this._config.context === 'database' ? nls.localize('loadingObjectsCompleted', "loading objects completed.") : nls.localize('loadingDatabasesCompleted', "loading databases completed.");
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,14 +162,6 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setLoadingStatus(loading: boolean): void {
|
|
||||||
this.loading = loading;
|
|
||||||
|
|
||||||
if (this._inited) {
|
|
||||||
this._cd.detectChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private showErrorMessage(message: string): void {
|
private showErrorMessage(message: string): void {
|
||||||
(<HTMLElement>this._el.nativeElement).innerText = message;
|
(<HTMLElement>this._el.nativeElement).innerText = message;
|
||||||
alert(message);
|
alert(message);
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ interface IStorageResult {
|
|||||||
<div *ngIf="lastUpdated" style="font-style: italic; font-size: 80%; margin-left: 5px">{{lastUpdated}}</div>
|
<div *ngIf="lastUpdated" style="font-style: italic; font-size: 80%; margin-left: 5px">{{lastUpdated}}</div>
|
||||||
<div *ngIf="autoRefreshStatus" style="font-style: italic; font-size: 80%; margin-left: 5px">{{autoRefreshStatus}}</div>
|
<div *ngIf="autoRefreshStatus" style="font-style: italic; font-size: 80%; margin-left: 5px">{{autoRefreshStatus}}</div>
|
||||||
<div style="margin: 10px; width: calc(100% - 20px); height: calc(100% - 20px)">
|
<div style="margin: 10px; width: calc(100% - 20px); height: calc(100% - 20px)">
|
||||||
<ng-template component-host></ng-template>
|
<ng-template *ngIf="!_loading" component-host></ng-template>
|
||||||
<loading-spinner [loading]="_loading"></loading-spinner>
|
<loading-spinner [loading]="_loading" [loadingMessage]="_loadingMessage" [loadingCompletedMessage]="_loadingCompletedMessage"></loading-spinner>
|
||||||
</div>`,
|
</div>`,
|
||||||
styles: [':host { width: 100%; height: 100% }']
|
styles: [':host { width: 100%; height: 100% }']
|
||||||
})
|
})
|
||||||
@@ -60,8 +60,6 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
@ViewChild(ComponentHostDirective) private componentHost: ComponentHostDirective;
|
@ViewChild(ComponentHostDirective) private componentHost: ComponentHostDirective;
|
||||||
|
|
||||||
private _typeKey: string;
|
private _typeKey: string;
|
||||||
private _init: boolean = false;
|
|
||||||
public _loading: boolean = true;
|
|
||||||
private _intervalTimer: IntervalTimer;
|
private _intervalTimer: IntervalTimer;
|
||||||
|
|
||||||
public error: string;
|
public error: string;
|
||||||
@@ -72,16 +70,17 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
@Inject(forwardRef(() => ComponentFactoryResolver)) private _componentFactoryResolver: ComponentFactoryResolver,
|
@Inject(forwardRef(() => ComponentFactoryResolver)) private _componentFactoryResolver: ComponentFactoryResolver,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private dashboardService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) private dashboardService: CommonServiceInterface,
|
||||||
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
|
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => Injector)) private _injector: Injector,
|
@Inject(forwardRef(() => Injector)) private _injector: Injector,
|
||||||
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
|
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
|
||||||
@Inject(IStorageService) private storageService: IStorageService,
|
@Inject(IStorageService) private storageService: IStorageService,
|
||||||
@Inject(IConfigurationService) private readonly _configurationService: IConfigurationService,
|
@Inject(IConfigurationService) private readonly _configurationService: IConfigurationService,
|
||||||
@Inject(IFileService) private readonly fileService: IFileService
|
@Inject(IFileService) private readonly fileService: IFileService
|
||||||
) {
|
) {
|
||||||
super();
|
super(changeRef);
|
||||||
this.insightConfig = <IInsightsConfig>this._config.widget['insights-widget'];
|
this.insightConfig = <IInsightsConfig>this._config.widget['insights-widget'];
|
||||||
|
this._loadingMessage = nls.localize('insightsWidgetLoadingMessage', "Loading {0}", this._config.name);
|
||||||
|
this._loadingCompletedMessage = nls.localize('insightsWidgetLoadingCompletedMessage', "Loading {0} completed", this._config.name);
|
||||||
this._verifyConfig();
|
this._verifyConfig();
|
||||||
|
|
||||||
this._parseConfig().then(() => {
|
this._parseConfig().then(() => {
|
||||||
@@ -91,8 +90,7 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
const cancelablePromise = createCancelablePromise(() => {
|
const cancelablePromise = createCancelablePromise(() => {
|
||||||
return promise.then(
|
return promise.then(
|
||||||
result => {
|
result => {
|
||||||
this._loading = false;
|
if (this._inited) {
|
||||||
if (this._init) {
|
|
||||||
this._updateChild(result);
|
this._updateChild(result);
|
||||||
this.setupInterval();
|
this.setupInterval();
|
||||||
} else {
|
} else {
|
||||||
@@ -100,37 +98,36 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this._loading = false;
|
|
||||||
if (isPromiseCanceledError(error)) {
|
if (isPromiseCanceledError(error)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this._init) {
|
if (this._inited) {
|
||||||
this.showError(error);
|
this.showError(error);
|
||||||
} else {
|
} else {
|
||||||
this.queryObv = Observable.fromPromise(Promise.resolve<SimpleExecuteResult>(error));
|
this.queryObv = Observable.fromPromise(Promise.resolve<SimpleExecuteResult>(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).then(() => this._cd.detectChanges());
|
).then(() => this._changeRef.detectChanges());
|
||||||
});
|
});
|
||||||
this._register(toDisposable(() => cancelablePromise.cancel()));
|
this._register(toDisposable(() => cancelablePromise.cancel()));
|
||||||
}
|
}
|
||||||
}, error => {
|
}, error => {
|
||||||
this._loading = false;
|
this.setLoadingStatus(false);
|
||||||
this.showError(error);
|
this.showError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterContentInit() {
|
ngAfterContentInit() {
|
||||||
this._init = true;
|
this._inited = true;
|
||||||
if (this.queryObv) {
|
if (this.queryObv) {
|
||||||
this._register(subscriptionToDisposable(this.queryObv.subscribe(
|
this._register(subscriptionToDisposable(this.queryObv.subscribe(
|
||||||
result => {
|
result => {
|
||||||
this._loading = false;
|
this.setLoadingStatus(false);
|
||||||
this._updateChild(result);
|
this._updateChild(result);
|
||||||
this.setupInterval();
|
this.setupInterval();
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this._loading = false;
|
this.setLoadingStatus(false);
|
||||||
this.showError(error);
|
this.showError(error);
|
||||||
}
|
}
|
||||||
)));
|
)));
|
||||||
@@ -156,13 +153,13 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
let newState = autoRefreshOn ? '' : nls.localize('insights.autoRefreshOffState', "Auto Refresh: OFF");
|
let newState = autoRefreshOn ? '' : nls.localize('insights.autoRefreshOffState', "Auto Refresh: OFF");
|
||||||
if (this.autoRefreshStatus !== newState) {
|
if (this.autoRefreshStatus !== newState) {
|
||||||
this.autoRefreshStatus = newState;
|
this.autoRefreshStatus = newState;
|
||||||
this._cd.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private showError(error: string): void {
|
private showError(error: string): void {
|
||||||
this.error = error;
|
this.error = error;
|
||||||
this._cd.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
get actions(): Array<Action> {
|
get actions(): Array<Action> {
|
||||||
@@ -189,7 +186,7 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
results: result
|
results: result
|
||||||
};
|
};
|
||||||
this.lastUpdated = nls.localize('insights.lastUpdated', "Last Updated: {0} {1}", currentTime.toLocaleTimeString(), currentTime.toLocaleDateString());
|
this.lastUpdated = nls.localize('insights.lastUpdated', "Last Updated: {0} {1}", currentTime.toLocaleTimeString(), currentTime.toLocaleDateString());
|
||||||
this._cd.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
this.storageService.store(this._getStorageKey(), JSON.stringify(store), StorageScope.GLOBAL);
|
this.storageService.store(this._getStorageKey(), JSON.stringify(store), StorageScope.GLOBAL);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -202,11 +199,10 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
const storedResult: IStorageResult = JSON.parse(storage);
|
const storedResult: IStorageResult = JSON.parse(storage);
|
||||||
const date = new Date(storedResult.date);
|
const date = new Date(storedResult.date);
|
||||||
this.lastUpdated = nls.localize('insights.lastUpdated', "Last Updated: {0} {1}", date.toLocaleTimeString(), date.toLocaleDateString());
|
this.lastUpdated = nls.localize('insights.lastUpdated', "Last Updated: {0} {1}", date.toLocaleTimeString(), date.toLocaleDateString());
|
||||||
this._loading = false;
|
if (this._inited) {
|
||||||
if (this._init) {
|
|
||||||
this._updateChild(storedResult.results);
|
this._updateChild(storedResult.results);
|
||||||
this.setupInterval();
|
this.setupInterval();
|
||||||
this._cd.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
} else {
|
} else {
|
||||||
this.queryObv = Observable.fromPromise(Promise.resolve<SimpleExecuteResult>(JSON.parse(storage)));
|
this.queryObv = Observable.fromPromise(Promise.resolve<SimpleExecuteResult>(JSON.parse(storage)));
|
||||||
}
|
}
|
||||||
@@ -231,11 +227,14 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _runQuery(): Promise<SimpleExecuteResult> {
|
private _runQuery(): Promise<SimpleExecuteResult> {
|
||||||
|
this.setLoadingStatus(true);
|
||||||
return Promise.resolve(this.dashboardService.queryManagementService.runQueryAndReturn(this.insightConfig.query as string).then(
|
return Promise.resolve(this.dashboardService.queryManagementService.runQueryAndReturn(this.insightConfig.query as string).then(
|
||||||
result => {
|
result => {
|
||||||
|
this.setLoadingStatus(false);
|
||||||
return this._storeResult(result);
|
return this._storeResult(result);
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
this.setLoadingStatus(false);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
@@ -244,7 +243,7 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
private _updateChild(result: SimpleExecuteResult): void {
|
private _updateChild(result: SimpleExecuteResult): void {
|
||||||
this.componentHost.viewContainerRef.clear();
|
this.componentHost.viewContainerRef.clear();
|
||||||
this.error = undefined;
|
this.error = undefined;
|
||||||
this._cd.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
|
|
||||||
if (result.rowCount === 0) {
|
if (result.rowCount === 0) {
|
||||||
this.showError(nls.localize('noResults', "No results to show"));
|
this.showError(nls.localize('noResults', "No results to show"));
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
-->
|
-->
|
||||||
<div #parent style="position: absolute; height: 100%; width: 100%;">
|
<loading-spinner [loading]="_loading" [loadingMessage]="_loadingMessage"
|
||||||
|
[loadingCompletedMessage]="_loadingCompletedMessage"></loading-spinner>
|
||||||
|
<div #parent style="position: absolute; height: 100%; width: 100%;" [style.display]="_loading ? 'none':'block'">
|
||||||
<div #container [style.margin-right.px]="_clipped ? 30 : 0" [style.width]="_clipped ? 94 + '%' : '100%'" style="overflow: hidden; padding-bottom: 10px">
|
<div #container [style.margin-right.px]="_clipped ? 30 : 0" [style.width]="_clipped ? 94 + '%' : '100%'" style="overflow: hidden; padding-bottom: 10px">
|
||||||
<span #child style="white-space : nowrap; width: fit-content">
|
<span #child style="white-space : nowrap; width: fit-content">
|
||||||
<ng-template ngFor let-item [ngForOf]="properties">
|
<ng-template ngFor let-item [ngForOf]="properties">
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ export class PropertiesWidgetComponent extends DashboardWidget implements IDashb
|
|||||||
private _databaseInfo: DatabaseInfo;
|
private _databaseInfo: DatabaseInfo;
|
||||||
public _clipped: boolean;
|
public _clipped: boolean;
|
||||||
private properties: Array<DisplayProperty>;
|
private properties: Array<DisplayProperty>;
|
||||||
private _hasInit = false;
|
|
||||||
|
|
||||||
@ViewChild('child', { read: ElementRef }) private _child: ElementRef;
|
@ViewChild('child', { read: ElementRef }) private _child: ElementRef;
|
||||||
@ViewChild('parent', { read: ElementRef }) private _parent: ElementRef;
|
@ViewChild('parent', { read: ElementRef }) private _parent: ElementRef;
|
||||||
@@ -76,18 +75,20 @@ export class PropertiesWidgetComponent extends DashboardWidget implements IDashb
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrap: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrap: CommonServiceInterface,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
|
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
|
||||||
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
|
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
|
||||||
@Inject(ILogService) private logService: ILogService,
|
@Inject(ILogService) private logService: ILogService,
|
||||||
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService
|
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService
|
||||||
) {
|
) {
|
||||||
super();
|
super(changeRef);
|
||||||
|
this._loadingMessage = nls.localize('loadingProperties', "Loading properties");
|
||||||
|
this._loadingCompletedMessage = nls.localize('loadingPropertiesCompleted', "Loading properties completed");
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this._hasInit = true;
|
this._inited = true;
|
||||||
this._register(addDisposableListener(window, EventType.RESIZE, () => this.handleClipping()));
|
this._register(addDisposableListener(window, EventType.RESIZE, () => this.handleClipping()));
|
||||||
this._changeRef.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
|
|
||||||
@@ -106,14 +107,17 @@ export class PropertiesWidgetComponent extends DashboardWidget implements IDashb
|
|||||||
|
|
||||||
private init(): void {
|
private init(): void {
|
||||||
this._connection = this._bootstrap.connectionManagementService.connectionInfo;
|
this._connection = this._bootstrap.connectionManagementService.connectionInfo;
|
||||||
|
this.setLoadingStatus(true);
|
||||||
this._register(subscriptionToDisposable(this._bootstrap.adminService.databaseInfo.subscribe(data => {
|
this._register(subscriptionToDisposable(this._bootstrap.adminService.databaseInfo.subscribe(data => {
|
||||||
this._databaseInfo = data;
|
this._databaseInfo = data;
|
||||||
this._changeRef.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
this.parseProperties();
|
this.parseProperties();
|
||||||
if (this._hasInit) {
|
if (this._inited) {
|
||||||
this.handleClipping();
|
this.handleClipping();
|
||||||
}
|
}
|
||||||
|
this.setLoadingStatus(false);
|
||||||
}, error => {
|
}, error => {
|
||||||
|
this.setLoadingStatus(false);
|
||||||
(<HTMLElement>this._el.nativeElement).innerText = nls.localize('dashboard.properties.error', "Unable to load dashboard properties");
|
(<HTMLElement>this._el.nativeElement).innerText = nls.localize('dashboard.properties.error', "Unable to load dashboard properties");
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
@@ -238,7 +242,7 @@ export class PropertiesWidgetComponent extends DashboardWidget implements IDashb
|
|||||||
this.properties.push(<DisplayProperty>assignProperty);
|
this.properties.push(<DisplayProperty>assignProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._hasInit) {
|
if (this._inited) {
|
||||||
this._changeRef.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
tasks-widget .tile-container {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row wrap;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks-widget .task-tile {
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-left: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks-widget .task-tile > div {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks-widget .task-tile .codicon {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<!--
|
|
||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
-->
|
|
||||||
<div #container style="position: absolute; height: 100%; width: 100%">
|
|
||||||
</div>
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* 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!sql/media/icons/common-icons';
|
|
||||||
import 'vs/css!./media/taskWidget';
|
|
||||||
|
|
||||||
/* Node Modules */
|
|
||||||
import { Component, Inject, forwardRef, ViewChild, OnInit, ElementRef } from '@angular/core';
|
|
||||||
|
|
||||||
/* SQL imports */
|
|
||||||
import { DashboardWidget, IDashboardWidget, WidgetConfig, WIDGET_CONFIG } from 'sql/workbench/contrib/dashboard/browser/core/dashboardWidget';
|
|
||||||
import { CommonServiceInterface } from 'sql/workbench/services/bootstrap/browser/commonServiceInterface.service';
|
|
||||||
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
|
||||||
|
|
||||||
/* VS imports */
|
|
||||||
import * as themeColors from 'vs/workbench/common/theme';
|
|
||||||
import * as colors from 'vs/platform/theme/common/colorRegistry';
|
|
||||||
import { registerThemingParticipant, ICssStyleCollector, IColorTheme } from 'vs/platform/theme/common/themeService';
|
|
||||||
import * as types from 'vs/base/common/types';
|
|
||||||
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
|
||||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
|
||||||
import * as DOM from 'vs/base/browser/dom';
|
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
|
||||||
import { MenuRegistry, ICommandAction } from 'vs/platform/actions/common/actions';
|
|
||||||
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
|
||||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
|
||||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
|
||||||
import { TaskRegistry } from 'sql/workbench/services/tasks/browser/tasksRegistry';
|
|
||||||
|
|
||||||
interface ITask {
|
|
||||||
name: string;
|
|
||||||
when: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selector = 'tasks-widget';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector,
|
|
||||||
templateUrl: decodeURI(require.toUrl('./tasksWidget.component.html'))
|
|
||||||
})
|
|
||||||
export class TasksWidget extends DashboardWidget implements IDashboardWidget, OnInit {
|
|
||||||
private _size: number = 98;
|
|
||||||
private _tasks: Array<ICommandAction> = [];
|
|
||||||
private _profile: IConnectionProfile;
|
|
||||||
private _scrollableElement: ScrollableElement;
|
|
||||||
private _tileContainer: HTMLElement;
|
|
||||||
static readonly ICON_PATH_TO_CSS_RULES: Map<string /* path*/, string /* CSS rule */> = new Map<string, string>();
|
|
||||||
|
|
||||||
private _inited = false;
|
|
||||||
|
|
||||||
@ViewChild('container', { read: ElementRef }) private _container: ElementRef;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
|
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private readonly _bootstrap: CommonServiceInterface,
|
|
||||||
@Inject(ICommandService) private readonly commandService: ICommandService,
|
|
||||||
@Inject(IContextKeyService) readonly contextKeyService: IContextKeyService
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
this._profile = this._bootstrap.connectionManagementService.connectionInfo.connectionProfile;
|
|
||||||
const tasksConfig = this._config.widget[selector] as Array<string | ITask>;
|
|
||||||
let tasks = TaskRegistry.getTasks();
|
|
||||||
|
|
||||||
if (types.isArray(tasksConfig) && tasksConfig.length > 0) {
|
|
||||||
tasks = tasksConfig.map(i => {
|
|
||||||
if (types.isString(i)) {
|
|
||||||
if (tasks.some(x => x === i)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tasks.some(x => x === i.name) && contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(i.when))) {
|
|
||||||
return i.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}).filter(i => !!i);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._tasks = tasks.map(i => MenuRegistry.getCommand(i)).filter(v => !!v);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this._inited = true;
|
|
||||||
this._register(registerThemingParticipant(this.registerThemeing));
|
|
||||||
this._computeContainer();
|
|
||||||
|
|
||||||
this._tasks.map(a => {
|
|
||||||
this._tileContainer.append(this._createTile(a));
|
|
||||||
});
|
|
||||||
|
|
||||||
this._scrollableElement = this._register(new ScrollableElement(this._tileContainer, {
|
|
||||||
horizontal: ScrollbarVisibility.Auto,
|
|
||||||
vertical: ScrollbarVisibility.Hidden,
|
|
||||||
scrollYToX: true,
|
|
||||||
useShadows: false
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._scrollableElement.onScroll(e => {
|
|
||||||
this._tileContainer.style.right = e.scrollLeft + 'px';
|
|
||||||
});
|
|
||||||
|
|
||||||
(this._container.nativeElement as HTMLElement).appendChild(this._scrollableElement.getDomNode());
|
|
||||||
|
|
||||||
// Update scrollbar
|
|
||||||
this._scrollableElement.setScrollDimensions({
|
|
||||||
width: DOM.getContentWidth(this._container.nativeElement),
|
|
||||||
scrollWidth: DOM.getContentWidth(this._tileContainer) + 18 // right padding
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _computeContainer(): void {
|
|
||||||
const height = DOM.getContentHeight(this._container.nativeElement);
|
|
||||||
const tilesHeight = Math.floor(height / (this._size + 10));
|
|
||||||
const width = (this._size + 18) * Math.ceil(this._tasks.length / tilesHeight);
|
|
||||||
if (!this._tileContainer) {
|
|
||||||
this._tileContainer = DOM.$('.tile-container');
|
|
||||||
}
|
|
||||||
this._tileContainer.style.height = height + 'px';
|
|
||||||
this._tileContainer.style.width = width + 'px';
|
|
||||||
}
|
|
||||||
|
|
||||||
private _createTile(action: ICommandAction): HTMLElement {
|
|
||||||
const label = DOM.$('div');
|
|
||||||
label.innerText = types.isString(action.title) ? action.title : action.title.value;
|
|
||||||
const tile = DOM.$('.task-tile');
|
|
||||||
tile.style.height = this._size + 'px';
|
|
||||||
tile.style.width = this._size + 'px';
|
|
||||||
const innerTile = DOM.$('div');
|
|
||||||
|
|
||||||
const iconClassName = TaskRegistry.getOrCreateTaskIconClassName(action);
|
|
||||||
if (iconClassName) {
|
|
||||||
const icon = DOM.$('span.codicon');
|
|
||||||
DOM.addClass(icon, iconClassName);
|
|
||||||
innerTile.append(icon);
|
|
||||||
}
|
|
||||||
innerTile.append(label);
|
|
||||||
tile.append(innerTile);
|
|
||||||
tile.setAttribute('tabindex', '0');
|
|
||||||
this._register(DOM.addDisposableListener(tile, DOM.EventType.CLICK, () => this.runTask(action)));
|
|
||||||
this._register(DOM.addDisposableListener(tile, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
|
|
||||||
const event = new StandardKeyboardEvent(e);
|
|
||||||
if (event.equals(KeyCode.Enter)) {
|
|
||||||
this.runTask(action);
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
return tile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private registerThemeing(theme: IColorTheme, collector: ICssStyleCollector) {
|
|
||||||
const contrastBorder = theme.getColor(colors.contrastBorder);
|
|
||||||
const sideBarColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND);
|
|
||||||
if (contrastBorder) {
|
|
||||||
const contrastBorderString = contrastBorder.toString();
|
|
||||||
collector.addRule(`tasks-widget .task-tile { border: 1px solid ${contrastBorderString} }`);
|
|
||||||
} else {
|
|
||||||
const sideBarColorString = sideBarColor.toString();
|
|
||||||
collector.addRule(`tasks-widget .task-tile { background-color: ${sideBarColorString} }`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public runTask(task: ICommandAction) {
|
|
||||||
this.commandService.executeCommand(task.id, this._profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
public layout(): void {
|
|
||||||
if (this._inited) {
|
|
||||||
this._computeContainer();
|
|
||||||
// Update scrollbar
|
|
||||||
this._scrollableElement.setScrollDimensions({
|
|
||||||
width: DOM.getContentWidth(this._container.nativeElement),
|
|
||||||
scrollWidth: DOM.getContentWidth(this._tileContainer) + 18 // right padding
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import { registerDashboardWidget } from 'sql/platform/dashboard/browser/widgetRegistry';
|
|
||||||
|
|
||||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
|
||||||
import { TaskRegistry } from 'sql/workbench/services/tasks/browser/tasksRegistry';
|
|
||||||
|
|
||||||
const singleTaskSchema: IJSONSchema = {
|
|
||||||
type: 'string',
|
|
||||||
enum: TaskRegistry.getTasks()
|
|
||||||
};
|
|
||||||
|
|
||||||
const tasksSchema: IJSONSchema = {
|
|
||||||
type: 'array',
|
|
||||||
items: {
|
|
||||||
anyOf: [
|
|
||||||
singleTaskSchema,
|
|
||||||
{
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
name: singleTaskSchema,
|
|
||||||
when: {
|
|
||||||
type: 'string'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TaskRegistry.onTaskRegistered(e => {
|
|
||||||
singleTaskSchema.enum.push(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
registerDashboardWidget('tasks-widget', '', tasksSchema);
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { Component, Inject, forwardRef, OnInit, ElementRef } from '@angular/core';
|
import { Component, Inject, forwardRef, OnInit, ElementRef, ChangeDetectorRef } from '@angular/core';
|
||||||
|
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
@@ -41,9 +41,10 @@ export class WebviewWidget extends DashboardWidget implements IDashboardWidget,
|
|||||||
@Inject(WIDGET_CONFIG) protected readonly _config: WidgetConfig,
|
@Inject(WIDGET_CONFIG) protected readonly _config: WidgetConfig,
|
||||||
@Inject(forwardRef(() => ElementRef)) private readonly _el: ElementRef,
|
@Inject(forwardRef(() => ElementRef)) private readonly _el: ElementRef,
|
||||||
@Inject(IDashboardViewService) private readonly dashboardViewService: IDashboardViewService,
|
@Inject(IDashboardViewService) private readonly dashboardViewService: IDashboardViewService,
|
||||||
@Inject(IWebviewService) private readonly webviewService: IWebviewService
|
@Inject(IWebviewService) private readonly webviewService: IWebviewService,
|
||||||
|
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef
|
||||||
) {
|
) {
|
||||||
super();
|
super(changeRef);
|
||||||
this._id = (_config.widget[selector] as IWebviewWidgetConfig).id;
|
this._id = (_config.widget[selector] as IWebviewWidgetConfig).id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -435,7 +435,6 @@ import 'sql/workbench/contrib/dashboard/browser/widgets/insights/views/tableInsi
|
|||||||
import 'sql/workbench/contrib/dashboard/browser/dashboard.contribution';
|
import 'sql/workbench/contrib/dashboard/browser/dashboard.contribution';
|
||||||
import 'sql/workbench/contrib/dashboard/browser/widgets/insights/insightsWidget.contribution';
|
import 'sql/workbench/contrib/dashboard/browser/widgets/insights/insightsWidget.contribution';
|
||||||
import 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.contribution';
|
import 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerWidget.contribution';
|
||||||
import 'sql/workbench/contrib/dashboard/browser/widgets/tasks/tasksWidget.contribution';
|
|
||||||
import 'sql/workbench/contrib/dashboard/browser/widgets/webview/webviewWidget.contribution';
|
import 'sql/workbench/contrib/dashboard/browser/widgets/webview/webviewWidget.contribution';
|
||||||
import 'sql/workbench/contrib/dashboard/browser/containers/dashboardWebviewContainer.contribution';
|
import 'sql/workbench/contrib/dashboard/browser/containers/dashboardWebviewContainer.contribution';
|
||||||
import 'sql/workbench/contrib/dashboard/browser/containers/dashboardControlHostContainer.contribution';
|
import 'sql/workbench/contrib/dashboard/browser/containers/dashboardControlHostContainer.contribution';
|
||||||
|
|||||||
Reference in New Issue
Block a user