mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-12 11:08:31 -05:00
Dataexplorer viewlet (#3967)
* added initial data explorer viewlet * added dataexplorer contribution point * removed test view * remove unused imports * added flag and tests * CR comments * added icon for data explorer
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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/actionBarLabel';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { VIEWLET_ID } from 'sql/parts/dataExplorer/common/dataExplorerExtensionPoint';
|
||||
import { DataExplorerViewlet, DataExplorerViewletViewsContribution } from 'sql/parts/dataExplorer/viewlet/dataExplorerViewlet';
|
||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { OpenConnectionsViewletAction } from 'sql/parts/objectExplorer/common/registeredServer.contribution';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
|
||||
// Data Explorer Viewlet
|
||||
const viewletDescriptor = new ViewletDescriptor(
|
||||
DataExplorerViewlet,
|
||||
VIEWLET_ID,
|
||||
localize('workbench.dataExplorer', 'Data Explorer'),
|
||||
'dataExplorer',
|
||||
0
|
||||
);
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(viewletDescriptor);
|
||||
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).setDefaultViewletId(VIEWLET_ID);
|
||||
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
workbenchRegistry.registerWorkbenchContribution(DataExplorerViewletViewsContribution, LifecyclePhase.Starting);
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(
|
||||
new SyncActionDescriptor(
|
||||
OpenConnectionsViewletAction,
|
||||
OpenConnectionsViewletAction.ID,
|
||||
OpenConnectionsViewletAction.LABEL,
|
||||
{ primary: KeyMod.CtrlCmd | KeyCode.Shift | KeyCode.KEY_C }),
|
||||
'View: Show Servers',
|
||||
localize('registeredServers.view', "View")
|
||||
);
|
||||
|
||||
let configurationRegistry = <IConfigurationRegistry>Registry.as(Extensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': 'databaseConnections',
|
||||
'order': 0,
|
||||
'title': localize('databaseConnections', 'Database Connections'),
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'datasource.connections': {
|
||||
'description': localize('datasource.connections', 'data source connections'),
|
||||
'type': 'array'
|
||||
},
|
||||
'datasource.connectionGroups': {
|
||||
'description': localize('datasource.connectionGroups', 'data source groups'),
|
||||
'type': 'array'
|
||||
}
|
||||
}
|
||||
});
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': 'startupConfig',
|
||||
'title': localize('startupConfig', 'Startup Configuration'),
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'startup.alwaysShowServersView': {
|
||||
'type': 'boolean',
|
||||
'description': localize('startup.alwaysShowServersView', 'True for the Servers view to be shown on launch of Azure Data Studio default; false if the last opened view should be shown'),
|
||||
'default': true
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
166
src/sql/parts/dataExplorer/common/dataExplorerExtensionPoint.ts
Normal file
166
src/sql/parts/dataExplorer/common/dataExplorerExtensionPoint.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { forEach } from 'vs/base/common/collections';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IViewContainersRegistry, ViewContainer, Extensions as ViewContainerExtensions, ICustomViewDescriptor, ViewsRegistry } from 'vs/workbench/common/views';
|
||||
import { IExtensionPoint, ExtensionsRegistry, ExtensionMessageCollector } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { CustomTreeViewPanel, CustomTreeViewer } from 'vs/workbench/browser/parts/views/customView';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { viewsContainersExtensionPoint } from 'vs/workbench/api/browser/viewsContainersExtensionPoint';
|
||||
|
||||
export const DataExplorerViewlet = {
|
||||
DataExplorer: 'dataExplorer'
|
||||
};
|
||||
export const VIEWLET_ID = 'workbench.view.dataExplorer';
|
||||
export const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer(VIEWLET_ID);
|
||||
|
||||
|
||||
|
||||
interface IUserFriendlyViewDescriptor {
|
||||
id: string;
|
||||
name: string;
|
||||
when?: string;
|
||||
}
|
||||
|
||||
const viewDescriptor: IJSONSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
description: localize('vscode.extension.contributes.view.id', 'Identifier of the view. Use this to register a data provider through `vscode.window.registerTreeDataProviderForView` API. Also to trigger activating your extension by registering `onView:${id}` event to `activationEvents`.'),
|
||||
type: 'string'
|
||||
},
|
||||
name: {
|
||||
description: localize('vscode.extension.contributes.view.name', 'The human-readable name of the view. Will be shown'),
|
||||
type: 'string'
|
||||
},
|
||||
when: {
|
||||
description: localize('vscode.extension.contributes.view.when', 'Condition which must be true to show this view'),
|
||||
type: 'string'
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const dataExplorerContribution: IJSONSchema = {
|
||||
description: localize('extension.contributes.dataExplorer', "Contributes views to the editor"),
|
||||
type: 'object',
|
||||
properties: {
|
||||
'dataExplorer': {
|
||||
description: localize('extension.dataExplorer', "Contributes views to Data Explorer container in the Activity bar"),
|
||||
type: 'array',
|
||||
items: viewDescriptor,
|
||||
default: []
|
||||
}
|
||||
},
|
||||
additionalProperties: {
|
||||
description: localize('dataExplorer.contributed', "Contributes views to contributed views container"),
|
||||
type: 'array',
|
||||
items: viewDescriptor,
|
||||
default: []
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const dataExplorerExtensionPoint: IExtensionPoint<{ [loc: string]: IUserFriendlyViewDescriptor[] }> = ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: IUserFriendlyViewDescriptor[] }>('dataExplorer', [viewsContainersExtensionPoint], dataExplorerContribution);
|
||||
|
||||
class DataExplorerContainerExtensionHandler implements IWorkbenchContribution {
|
||||
|
||||
private viewContainersRegistry: IViewContainersRegistry;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private instantiationService: IInstantiationService
|
||||
) {
|
||||
this.viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
this.handleAndRegisterCustomViews();
|
||||
}
|
||||
|
||||
private handleAndRegisterCustomViews() {
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
return;
|
||||
}
|
||||
dataExplorerExtensionPoint.setHandler(extensions => {
|
||||
for (let extension of extensions) {
|
||||
const { value, collector } = extension;
|
||||
|
||||
forEach(value, entry => {
|
||||
if (!this.isValidViewDescriptors(entry.value, collector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let container = this.viewContainersRegistry.get(VIEWLET_ID);
|
||||
if (!container) {
|
||||
collector.warn(localize('ViewsContainerDoesnotExist', "View container '{0}' does not exist and all views registered to it will be added to 'Data Explorer'.", entry.key));
|
||||
container = this.viewContainersRegistry.get(VIEWLET_ID);
|
||||
}
|
||||
const registeredViews = ViewsRegistry.getViews(container);
|
||||
const viewIds = [];
|
||||
const viewDescriptors = coalesce(entry.value.map(item => {
|
||||
// validate
|
||||
if (viewIds.indexOf(item.id) !== -1) {
|
||||
collector.error(localize('duplicateView1', "Cannot register multiple views with same id `{0}` in the view container `{1}`", item.id, container.id));
|
||||
return null;
|
||||
}
|
||||
if (registeredViews.some(v => v.id === item.id)) {
|
||||
collector.error(localize('duplicateView2', "A view with id `{0}` is already registered in the view container `{1}`", item.id, container.id));
|
||||
return null;
|
||||
}
|
||||
|
||||
const viewDescriptor = <ICustomViewDescriptor>{
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
ctor: CustomTreeViewPanel,
|
||||
container,
|
||||
when: ContextKeyExpr.deserialize(item.when),
|
||||
canToggleVisibility: true,
|
||||
collapsed: this.showCollapsed(container),
|
||||
treeViewer: this.instantiationService.createInstance(CustomTreeViewer, item.id, container)
|
||||
};
|
||||
|
||||
viewIds.push(viewDescriptor.id);
|
||||
return viewDescriptor;
|
||||
}));
|
||||
ViewsRegistry.registerViews(viewDescriptors);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private isValidViewDescriptors(viewDescriptors: IUserFriendlyViewDescriptor[], collector: ExtensionMessageCollector): boolean {
|
||||
if (!Array.isArray(viewDescriptors)) {
|
||||
collector.error(localize('requirearray', "views must be an array"));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let descriptor of viewDescriptors) {
|
||||
if (typeof descriptor.id !== 'string') {
|
||||
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'id'));
|
||||
return false;
|
||||
}
|
||||
if (typeof descriptor.name !== 'string') {
|
||||
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'name'));
|
||||
return false;
|
||||
}
|
||||
if (descriptor.when && typeof descriptor.when !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private showCollapsed(container: ViewContainer): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
workbenchRegistry.registerWorkbenchContribution(DataExplorerContainerExtensionHandler, LifecyclePhase.Starting);
|
||||
Reference in New Issue
Block a user