Files
cloudbeaver/webapp/packages/plugin-datasource-context-switch/src/ConnectionSchemaManager/ConnectionSchemaManagerBootstrap.ts
T
AlexeyandEvgeniaBzzz 0d41713c2d CB-3456 refactor: user form (#2010)
* CB-3456 chore: cleanup users administration

* CB-3456 chore: add label for user credentials column

* CB-3456 chore: add deprecation message to reshadow system

* CB-3456 chore: add deprecation message to ComponentStyle

* CB-3456 refactor: user form

* CB-3456 fix: eslint problems

* CB-3456 fix: after review

* CB-3456 fix: base form localization

* CB-3456 fix: remove unused import

* CB-3456 fix: user default team assignment

* CB-3456 chore: update git indexes

* CB-3456 fix: imports

* CB-3456 fix: enable user by default

* CB-3456 refactor: implement FormPart

* CB-3456 fix: make sh executable

* CB-3456 fix: make sh executable

* CB-3456 fix: handle form part exceptions on save

---------

Co-authored-by: EvgeniaBzzz <139753579+EvgeniaBzzz@users.noreply.github.com>
2023-09-28 16:28:28 +03:00

395 lines
15 KiB
TypeScript

/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2023 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { AppAuthService } from '@cloudbeaver/core-authentication';
import {
compareConnectionsInfo,
ConnectionInfoResource,
ConnectionsManagerService,
ConnectionsSettingsService,
ContainerResource,
createConnectionParam,
serializeConnectionParam,
} from '@cloudbeaver/core-connections';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { LocalizationService } from '@cloudbeaver/core-localization';
import { EObjectFeature, NodeManagerUtils } from '@cloudbeaver/core-navigation-tree';
import { getCachedMapResourceLoaderState } from '@cloudbeaver/core-sdk';
import { OptionsPanelService } from '@cloudbeaver/core-ui';
import { DATA_CONTEXT_MENU, MenuBaseItem, menuExtractItems, MenuSeparatorItem, MenuService } from '@cloudbeaver/core-view';
import { MENU_APP_ACTIONS } from '@cloudbeaver/plugin-top-app-bar';
import { ConnectionSchemaManagerService } from './ConnectionSchemaManagerService';
import { ConnectionIcon } from './ConnectionSelector/ConnectionIcon';
import { ConnectionIconSmall } from './ConnectionSelector/ConnectionIconSmall';
import type { IConnectionSelectorExtraProps } from './ConnectionSelector/IConnectionSelectorExtraProps';
import { MENU_CONNECTION_DATA_CONTAINER_SELECTOR } from './MENU_CONNECTION_DATA_CONTAINER_SELECTOR';
import { MENU_CONNECTION_SELECTOR } from './MENU_CONNECTION_SELECTOR';
@injectable()
export class ConnectionSchemaManagerBootstrap extends Bootstrap {
get connectionSelectorLoading(): boolean {
return this.connectionSchemaManagerService.isChangingConnection || this.connectionsManagerService.containerContainers.isLoading();
}
constructor(
private readonly connectionInfoResource: ConnectionInfoResource,
private readonly connectionSchemaManagerService: ConnectionSchemaManagerService,
private readonly connectionsManagerService: ConnectionsManagerService,
private readonly optionsPanelService: OptionsPanelService,
private readonly appAuthService: AppAuthService,
private readonly containerResource: ContainerResource,
private readonly menuService: MenuService,
private readonly connectionsSettingsService: ConnectionsSettingsService,
private readonly localizationService: LocalizationService,
) {
super();
}
register(): void {
this.addTopAppMenuItems();
this.connectionInfoResource.onDataUpdate.addHandler(
this.connectionSchemaManagerService.onConnectionUpdate.bind(this.connectionSchemaManagerService),
);
this.menuService.setHandler<IConnectionSelectorExtraProps>({
id: 'connection-selector-base',
isApplicable: context => context.hasValue(DATA_CONTEXT_MENU, MENU_CONNECTION_SELECTOR),
isLoading: () => this.connectionSelectorLoading,
isHidden: () => this.isHidden() || !this.appAuthService.authenticated,
isDisabled: () =>
!this.connectionSchemaManagerService.isConnectionChangeable ||
this.connectionSelectorLoading ||
!this.connectionsManagerService.hasAnyConnection() ||
this.connectionSchemaManagerService.isChangingConnectionContainer,
getInfo: (context, menu) => {
const connection = this.connectionSchemaManagerService.currentConnection;
const label = connection?.name || 'plugin_datasource_context_switch_select_connection';
return {
...menu,
label,
};
},
iconComponent: () => ConnectionIcon,
hideIfEmpty: () => false,
getExtraProps: () => ({ connectionKey: this.connectionSchemaManagerService.currentConnectionKey, small: true }),
getLoader: (context, menu) => {
if (this.isHidden()) {
return [];
}
const activeConnectionKey = this.connectionSchemaManagerService.activeConnectionKey;
if (!activeConnectionKey) {
return this.appAuthService.loaders;
}
return [
...this.appAuthService.loaders,
getCachedMapResourceLoaderState(this.containerResource, () => ({
...activeConnectionKey,
catalogId: this.connectionSchemaManagerService.activeObjectCatalogId,
})),
];
},
});
this.menuService.addCreator({
menus: [MENU_CONNECTION_SELECTOR],
isApplicable: () => this.connectionsManagerService.hasAnyConnection() && this.connectionSchemaManagerService.isConnectionChangeable,
getItems: (context, items) => {
items = [...items];
const connections = this.connectionsManagerService.projectConnections
.filter(connection => {
if (
!this.connectionSchemaManagerService.isProjectChangeable &&
this.connectionSchemaManagerService.activeProjectId &&
connection.projectId !== this.connectionSchemaManagerService.activeProjectId
) {
return false;
}
return !connection.template;
})
.sort((a, b) => {
if (a.connected === b.connected) {
return compareConnectionsInfo(a, b);
}
return Number(b.connected) - Number(a.connected);
});
for (const connection of connections) {
const connectionKey = createConnectionParam(connection);
items.push(
new MenuBaseItem<IConnectionSelectorExtraProps>(
{
id: serializeConnectionParam(connectionKey),
label: connection.name,
tooltip: connection.description,
},
{
onSelect: () => {
this.connectionSchemaManagerService.selectConnection(connectionKey);
},
},
{
iconComponent: () => ConnectionIconSmall,
isDisabled: () =>
this.connectionSchemaManagerService.currentConnectionKey !== null &&
this.connectionSchemaManagerService.currentConnectionKey !== undefined &&
this.connectionInfoResource.isKeyEqual(this.connectionSchemaManagerService.currentConnectionKey, connectionKey),
getExtraProps: () => ({ connectionKey }),
},
),
);
}
return items;
},
});
this.menuService.setHandler({
id: 'connection-data-container-selector-base',
isApplicable: context => context.hasValue(DATA_CONTEXT_MENU, MENU_CONNECTION_DATA_CONTAINER_SELECTOR),
isDisabled: () =>
!this.connectionSchemaManagerService.currentConnection?.connected ||
this.connectionSelectorLoading ||
this.connectionSchemaManagerService.isChangingConnectionContainer ||
(!this.connectionSchemaManagerService.isObjectCatalogChangeable && !this.connectionSchemaManagerService.isObjectSchemaChangeable),
isLoading: () => !this.connectionSelectorLoading && this.connectionSchemaManagerService.isChangingConnectionContainer,
isHidden: () =>
this.isHidden() ||
!this.appAuthService.authenticated ||
!this.connectionSchemaManagerService.objectContainerList ||
(this.connectionSchemaManagerService.currentObjectSchemaId === undefined &&
this.connectionSchemaManagerService.currentObjectCatalogId === undefined &&
!this.connectionSchemaManagerService.isObjectCatalogChangeable &&
!this.connectionSchemaManagerService.isObjectSchemaChangeable) ||
(this.connectionSchemaManagerService.objectContainerList.schemaList.length === 0 &&
this.connectionSchemaManagerService.objectContainerList.catalogList.length === 0),
getLoader: (context, menu) => {
if (this.isHidden()) {
return [];
}
return this.appAuthService.loaders;
},
hideIfEmpty: () => false,
getInfo: (context, menu) => {
const connectionSchemaManagerService = this.connectionSchemaManagerService;
let icon: string | undefined = '/icons/plugin_datasource_context_switch_database_m.svg';
let label = NodeManagerUtils.concatSchemaAndCatalog(
connectionSchemaManagerService.currentObjectCatalogId,
connectionSchemaManagerService.currentObjectSchemaId,
);
if (!label) {
label = 'plugin_datasource_context_switch_select_container';
}
if (!connectionSchemaManagerService.currentObjectSchema && !connectionSchemaManagerService.currentObjectCatalog) {
icon = undefined;
} else if (connectionSchemaManagerService.currentObjectSchema?.object?.features?.includes(EObjectFeature.schema)) {
// TODO move such kind of icon paths to a set of constants
icon = '/icons/plugin_datasource_context_switch_schema_m.svg';
} else if (connectionSchemaManagerService.currentObjectCatalog?.object?.features?.includes(EObjectFeature.catalog)) {
icon = '/icons/plugin_datasource_context_switch_database_m.svg';
}
const tooltip = this.localizationService.translate('plugin_datasource_context_switch_select_container_tooltip', undefined, {
name: connectionSchemaManagerService.currentConnection?.name,
});
return {
...menu,
icon,
label,
tooltip,
};
},
});
this.menuService.addCreator({
menus: [MENU_CONNECTION_DATA_CONTAINER_SELECTOR],
isApplicable: () =>
(this.connectionSchemaManagerService.isObjectCatalogChangeable || this.connectionSchemaManagerService.isObjectSchemaChangeable) &&
!!this.connectionSchemaManagerService.objectContainerList,
getItems: (context, items) => {
items = [...items];
if (!this.connectionSchemaManagerService.objectContainerList) {
return [];
}
const schemaList = this.connectionSchemaManagerService.objectContainerList.schemaList.slice().sort((a, b) => {
if (a.name === b.name) {
return 0;
}
if (a.name === this.connectionSchemaManagerService.currentObjectSchemaId) {
return -1;
}
if (b.name === this.connectionSchemaManagerService.currentObjectSchemaId) {
return 1;
}
return 0;
});
const catalogList = this.connectionSchemaManagerService.objectContainerList.catalogList.slice().sort((a, b) => {
if (a.catalog.name === b.catalog.name) {
return 0;
}
if (a.catalog.name === this.connectionSchemaManagerService.currentObjectCatalogId) {
return -1;
}
if (b.catalog.name === this.connectionSchemaManagerService.currentObjectCatalogId) {
return 1;
}
return 0;
});
let previousSelected: boolean | null = null;
for (const schema of schemaList) {
if (!schema.name) {
continue;
}
const title = schema.name;
const selected = this.connectionSchemaManagerService.currentObjectSchemaId === title;
if (previousSelected && !selected) {
items.push(new MenuSeparatorItem());
}
previousSelected = selected;
items.push(
new MenuBaseItem(
{
id: title,
label: title,
tooltip: title,
icon: '/icons/plugin_datasource_context_switch_schema_sm.svg',
},
{
onSelect: async () => {
await this.connectionSchemaManagerService.selectSchema(title);
},
},
{
isDisabled: () => this.connectionSchemaManagerService.currentObjectSchemaId === title,
},
),
);
}
for (const catalogData of catalogList) {
const catalog = catalogData.catalog;
if (!catalog.name) {
continue;
}
const selected = this.connectionSchemaManagerService.currentObjectCatalogId === catalog.name;
if (previousSelected && !selected) {
items.push(new MenuSeparatorItem());
}
previousSelected = selected;
if (catalogData.schemaList.length === 0) {
items.push(
new MenuBaseItem(
{
id: catalog.name,
label: catalog.name,
tooltip: catalog.name,
icon: '/icons/plugin_datasource_context_switch_database_sm.svg',
},
{
onSelect: async () => {
await this.connectionSchemaManagerService.selectCatalog(catalog.name!);
},
},
{
isDisabled: () => this.connectionSchemaManagerService.currentObjectCatalogId === catalog.name,
},
),
);
}
for (const schema of catalogData.schemaList) {
if (!schema.name) {
continue;
}
const title = NodeManagerUtils.concatSchemaAndCatalog(catalog.name, schema.name);
items.push(
new MenuBaseItem(
{
id: title,
label: title,
tooltip: title,
icon: '/icons/plugin_datasource_context_switch_schema_sm.svg',
},
{
onSelect: async () => {
await this.connectionSchemaManagerService.selectSchema(schema.name!, catalog.name!);
},
},
{
isDisabled: () =>
this.connectionSchemaManagerService.currentObjectSchemaId === schema.name &&
this.connectionSchemaManagerService.currentObjectCatalogId === catalog.name,
},
),
);
}
}
return items;
},
});
}
load(): void {}
private isHidden(): boolean {
return (
this.connectionsSettingsService.settings.getValue('disabled') ||
this.optionsPanelService.active ||
(!this.connectionSchemaManagerService.isConnectionChangeable && !this.connectionSchemaManagerService.currentConnectionKey)
);
}
private addTopAppMenuItems() {
this.menuService.addCreator({
menus: [MENU_APP_ACTIONS],
getItems: (context, items) => [...items, MENU_CONNECTION_SELECTOR, MENU_CONNECTION_DATA_CONTAINER_SELECTOR],
orderItems: (context, items) => {
const extracted = menuExtractItems(items, [MENU_CONNECTION_SELECTOR, MENU_CONNECTION_DATA_CONTAINER_SELECTOR]);
return [...items, ...extracted];
},
});
}
}