Error handling for dashboard tab contributions (#851)

* support tab without title

* address comments

* formatting

* support error validation for dashboard tab and container contributions

* formatting
This commit is contained in:
Abbie Petchtes
2018-03-07 11:06:42 -08:00
committed by GitHub
parent ba188189a8
commit 7f79ab47ac
8 changed files with 214 additions and 46 deletions

View File

@@ -172,20 +172,17 @@ export function filterConfigs<T extends { when?: string }>(config: T[], dashboar
* Get registered container if it is specified as the key
* @param container dashboard container
*/
export function getDashboardContainer(container: object): object {
if (Object.keys(container).length !== 1) {
error(nls.localize('moreThanOneDashboardContainersError', 'Exactly 1 dashboard container must be defined per space'));
}
export function getDashboardContainer(container: object): { result: boolean, message: string, container: object } {
let key = Object.keys(container)[0];
let containerTypeFound = containerTypes.find(c => (c === key));
if (!containerTypeFound) {
let dashboardContainer = dashboardcontainerRegistry.getRegisteredContainer(key);
if (!dashboardContainer) {
error(nls.localize('unknownDashboardContainerError', 'The specified dashboard container is unknown.'));
let error = nls.localize('unknownDashboardContainerError', '{0} is an unknown container.', key);
return { result: false, message: error, container: null };
} else {
container = dashboardContainer.container;
}
}
return container;
return { result: true, message: null, container: container };
}

View File

@@ -189,11 +189,16 @@ export abstract class DashboardPage extends Disposable implements OnDestroy {
private loadNewTabs(dashboardTabs: IDashboardTab[], openLastTab: boolean = false) {
if (dashboardTabs && dashboardTabs.length > 0) {
let selectedTabs = dashboardTabs.map(v => {
let container = dashboardHelper.getDashboardContainer(v.container);
let key = Object.keys(container)[0];
let containerResult = dashboardHelper.getDashboardContainer(v.container);
if (!containerResult.result) {
let errorTitle = nls.localize('dashboardPage_loadTabError', 'Cannot open {0}. ', v.title);
this.dashboardService.messageService.show(Severity.Error, errorTitle + containerResult.message);
return null;
}
let key = Object.keys(containerResult.container)[0];
if (key === WIDGETS_CONTAINER || key === GRID_CONTAINER) {
let configs = <WidgetConfig[]>Object.values(container)[0];
let configs = <WidgetConfig[]>Object.values(containerResult.container)[0];
this._configModifiers.forEach(cb => {
configs = cb.apply(this, [configs, this.dashboardService, this.context]);
});
@@ -207,27 +212,33 @@ export abstract class DashboardPage extends Disposable implements OnDestroy {
return { id: v.id, title: v.title, container: { 'grid-container': configs }, alwaysShow: v.alwaysShow };
}
}
return { id: v.id, title: v.title, container: container, alwaysShow: v.alwaysShow };
return { id: v.id, title: v.title, container: containerResult.container, alwaysShow: v.alwaysShow };
}).map(v => {
let actions = [];
if (!v.alwaysShow) {
let pinnedTab = this._pinnedTabs.find(i => i.tabId === v.id);
actions.push(this.dashboardService.instantiationService.createInstance(PinUnpinTabAction, v.id, this.dashboardService.getUnderlyingUri(), !!pinnedTab));
}
if (v) {
let actions = [];
if (!v.alwaysShow) {
let pinnedTab = this._pinnedTabs.find(i => i.tabId === v.id);
actions.push(this.dashboardService.instantiationService.createInstance(PinUnpinTabAction, v.id, this.dashboardService.getUnderlyingUri(), !!pinnedTab));
}
let config = v as TabConfig;
config.context = this.context;
config.editable = false;
config.canClose = true;
config.actions = actions;
this.addNewTab(config);
return config;
let config = v as TabConfig;
config.context = this.context;
config.editable = false;
config.canClose = true;
config.actions = actions;
this.addNewTab(config);
return config;
}
return null;
});
if (openLastTab) {
// put this immediately on the stack so that is ran *after* the tab is rendered
setTimeout(() => {
this._panel.selectTab(selectedTabs.pop().id);
let selectedLastTab = selectedTabs.pop();
if (selectedLastTab) {
this._panel.selectTab(selectedLastTab.id);
}
});
}
}

View File

@@ -8,6 +8,9 @@ import { localize } from 'vs/nls';
import { registerTab } from 'sql/platform/dashboard/common/dashboardRegistry';
import { generateContainerTypeSchemaProperties } from 'sql/platform/dashboard/common/dashboardContainerRegistry';
import { NAV_SECTION, validateNavSectionContribution } from 'sql/parts/dashboard/containers/dashboardNavSection.contribution';
import { WIDGETS_CONTAINER, validateWidgetContainerContribution } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.contribution';
import { GRID_CONTAINER, validateGridContainerContribution } from 'sql/parts/dashboard/containers/dashboardGridContainer.contribution';
export interface IDashboardTabContrib {
id: string;
@@ -92,16 +95,43 @@ ExtensionsRegistry.registerExtensionPoint<IDashboardTabContrib | IDashboardTabCo
alwaysShow = alwaysShow || false;
let publisher = extension.description.publisher;
if (!title) {
extension.collector.error('No title specified for extension.');
extension.collector.error(localize('dashboardTab.contribution.noTitleError', 'No title specified for extension.'));
return;
}
if (!description) {
extension.collector.warn('No description specified to show.');
extension.collector.warn(localize('dashboardTab.contribution.noDescriptionWarning', 'No description specified to show.'));
}
if (!container) {
extension.collector.warn('No container specified to show.');
extension.collector.error(localize('dashboardTab.contribution.noContainerError', 'No container specified for extension.'));
return;
}
if (Object.keys(container).length !== 1) {
extension.collector.error(localize('dashboardTab.contribution.moreThanOneDashboardContainersError', 'Exactly 1 dashboard container must be defined per space'));
return;
}
let result = true;
let containerkey = Object.keys(container)[0];
let containerValue = Object.values(container)[0];
switch (containerkey) {
case WIDGETS_CONTAINER:
result = validateWidgetContainerContribution(extension, containerValue);
break;
case GRID_CONTAINER:
result = validateGridContainerContribution(extension, containerValue);
break;
case NAV_SECTION:
result = validateNavSectionContribution(extension, containerValue);
break;
}
if (result) {
registerTab({ description, title, container, edition, provider, id, alwaysShow, publisher });
}
registerTab({ description, title, container, edition, provider, id, alwaysShow, publisher });
}
for (let extension of extensions) {