mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
refactor: CB-722 resource's includes API
This commit is contained in:
@@ -34,6 +34,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
rules: {
|
||||
'@typescript-eslint/no-invalid-void-type': 'off',
|
||||
'@typescript-eslint/dot-notation': 'off',
|
||||
'@typescript-eslint/no-throw-literal': 'off',
|
||||
'@typescript-eslint/no-base-to-string': 'off',
|
||||
|
||||
@@ -20,7 +20,7 @@ export class DBObjectService extends CachedMapResource<string, DBObject> {
|
||||
private graphQLService: GraphQLService,
|
||||
private navNodeInfoResource: NavNodeInfoResource
|
||||
) {
|
||||
super(new Map());
|
||||
super();
|
||||
this.navNodeInfoResource.onDataOutdated.addHandler(this.markOutdated.bind(this));
|
||||
this.navNodeInfoResource.onItemDelete.addHandler(this.delete.bind(this));
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ import {
|
||||
ResourceKey,
|
||||
isResourceKeyList,
|
||||
NavNodeInfoFragment,
|
||||
ICachedResourceMetadata,
|
||||
ResourceKeyUtils
|
||||
ResourceKeyUtils,
|
||||
ICachedMapResourceMetadata
|
||||
} from '@cloudbeaver/core-sdk';
|
||||
import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
|
||||
@@ -26,7 +26,7 @@ type NavNodeInfo = NavNodeInfoFragment;
|
||||
|
||||
export const ROOT_NODE_PATH = '';
|
||||
|
||||
interface INodeMetadata extends ICachedResourceMetadata {
|
||||
interface INodeMetadata extends ICachedMapResourceMetadata<NavNode> {
|
||||
withDetails: boolean;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ interface INodeMetadata extends ICachedResourceMetadata {
|
||||
export class NavNodeInfoResource extends CachedMapResource<string, NavNode> {
|
||||
protected metadata: MetadataMap<string, INodeMetadata>;
|
||||
constructor(private graphQLService: GraphQLService) {
|
||||
super(new Map());
|
||||
super();
|
||||
|
||||
makeObservable(this, {
|
||||
setDetails: action,
|
||||
@@ -44,6 +44,8 @@ export class NavNodeInfoResource extends CachedMapResource<string, NavNode> {
|
||||
outdated: true,
|
||||
loading: false,
|
||||
withDetails: false,
|
||||
includes: [],
|
||||
loadedIncludes: [],
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ import {
|
||||
isResourceKeyList,
|
||||
ResourceKeyList,
|
||||
resourceKeyList,
|
||||
NavNodeChildrenQuery as fake, ResourceKeyUtils, ICachedResourceMetadata
|
||||
NavNodeChildrenQuery as fake,
|
||||
ResourceKeyUtils,
|
||||
ICachedMapResourceMetadata
|
||||
} from '@cloudbeaver/core-sdk';
|
||||
import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
|
||||
@@ -29,7 +31,7 @@ export interface NodePath {
|
||||
|
||||
type NavNodeChildrenQuery = fake & NodePath;
|
||||
|
||||
interface INodeMetadata extends ICachedResourceMetadata {
|
||||
interface INodeMetadata extends ICachedMapResourceMetadata<string[]> {
|
||||
withDetails: boolean;
|
||||
}
|
||||
|
||||
@@ -41,7 +43,7 @@ export class NavTreeResource extends CachedMapResource<string, string[]> {
|
||||
private graphQLService: GraphQLService,
|
||||
private navNodeInfoResource: NavNodeInfoResource
|
||||
) {
|
||||
super(new Map());
|
||||
super();
|
||||
|
||||
makeObservable(this, {
|
||||
setDetails: action,
|
||||
@@ -51,6 +53,8 @@ export class NavTreeResource extends CachedMapResource<string, string[]> {
|
||||
outdated: true,
|
||||
loading: false,
|
||||
withDetails: false,
|
||||
includes: [],
|
||||
loadedIncludes: [],
|
||||
}));
|
||||
this.onDataOutdated.addHandler(navNodeInfoResource.markOutdated.bind(navNodeInfoResource));
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
export class RolesResource extends CachedMapResource<string, AdminRoleInfo> {
|
||||
private loadedKeyMetadata: MetadataMap<string, boolean>;
|
||||
constructor(private graphQLService: GraphQLService) {
|
||||
super(new Map());
|
||||
super();
|
||||
this.loadedKeyMetadata = new MetadataMap(() => false);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ export class UsersResource extends CachedMapResource<string, AdminUser> {
|
||||
private authProviderService: AuthProviderService,
|
||||
private authInfoService: AuthInfoService
|
||||
) {
|
||||
super(new Map());
|
||||
super();
|
||||
this.loadedKeyMetadata = new MetadataMap(() => false);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { computed } from 'mobx';
|
||||
import { observer, useLocalStore } from 'mobx-react-lite';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { Button } from '../Button';
|
||||
import { useObjectRef } from '../useObjectRef';
|
||||
import type { IProperty } from './IProperty';
|
||||
import { PropertyItem } from './PropertyItem';
|
||||
import { PROPERTIES_TABLE_STYLES } from './styles';
|
||||
@@ -32,19 +32,14 @@ interface PropertiesTableProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const PropertiesTable = observer(function PropertiesTable({
|
||||
properties,
|
||||
propertiesState,
|
||||
readOnly,
|
||||
onKeyChange,
|
||||
onChange,
|
||||
onAdd,
|
||||
onRemove,
|
||||
className,
|
||||
}: PropertiesTableProps) {
|
||||
export const PropertiesTable = observer(function PropertiesTable(props: PropertiesTableProps) {
|
||||
const { className, onAdd, readOnly, propertiesState } = props;
|
||||
const propsRef = useObjectRef(props);
|
||||
const translate = useTranslate();
|
||||
const state = useLocalStore<PropertiesState>(() => (propertiesState || {}));
|
||||
|
||||
const changeName = useCallback((id: string, key: string) => {
|
||||
const { properties, onKeyChange } = propsRef;
|
||||
const property = properties.find(property => property.id === id);
|
||||
|
||||
if (!property) {
|
||||
@@ -63,9 +58,10 @@ export const PropertiesTable = observer(function PropertiesTable({
|
||||
onKeyChange(property.key, key);
|
||||
}
|
||||
property.key = key;
|
||||
}, [properties]);
|
||||
}, []);
|
||||
|
||||
const changeValue = useCallback((id: string, value: string) => {
|
||||
const { properties, onChange } = propsRef;
|
||||
const property = properties.find(property => property.id === id);
|
||||
|
||||
if (!property) {
|
||||
@@ -77,9 +73,10 @@ export const PropertiesTable = observer(function PropertiesTable({
|
||||
if (onChange) {
|
||||
onChange(state);
|
||||
}
|
||||
}, [properties, onChange]);
|
||||
}, []);
|
||||
|
||||
const removeProperty = useCallback((id: string) => {
|
||||
const { properties, onRemove } = propsRef;
|
||||
const property = properties.find(property => property.id === id);
|
||||
|
||||
if (!property) {
|
||||
@@ -95,15 +92,15 @@ export const PropertiesTable = observer(function PropertiesTable({
|
||||
onRemove(id);
|
||||
}
|
||||
properties.splice(properties.indexOf(property), 1);
|
||||
}, [properties, onRemove]);
|
||||
}, []);
|
||||
|
||||
const isKeyUnique = useCallback(
|
||||
(key: string) => properties.filter(property => property.key === key).length === 1,
|
||||
(key: string) => propsRef.properties.filter(property => property.key === key).length === 1,
|
||||
[]
|
||||
);
|
||||
|
||||
const alphabetOrderProperties = useMemo(() => computed(() => properties.slice().sort(
|
||||
(a, b) => (a?.displayName ?? '').localeCompare(b?.displayName ?? ''))), [properties]);
|
||||
const alphabetOrderProperties = propsRef.properties.slice().sort(
|
||||
(a, b) => (a?.displayName ?? '').localeCompare(b?.displayName ?? ''));
|
||||
|
||||
return styled(useStyles(PROPERTIES_TABLE_STYLES))(
|
||||
<properties as="div" className={className}>
|
||||
@@ -119,7 +116,7 @@ export const PropertiesTable = observer(function PropertiesTable({
|
||||
</properties-header-right>
|
||||
</properties-header>
|
||||
<properties-list as="div">
|
||||
{alphabetOrderProperties.get().map(property => (
|
||||
{alphabetOrderProperties.map(property => (
|
||||
<PropertyItem
|
||||
key={property.id}
|
||||
property={property}
|
||||
|
||||
@@ -26,38 +26,50 @@ interface IActions<TResource> {
|
||||
) => Promise<any> | any;
|
||||
}
|
||||
|
||||
interface KeyWithIncludes<TKey, TIncludes> {
|
||||
key: TKey | null;
|
||||
includes: TIncludes;
|
||||
}
|
||||
|
||||
interface IMapResourceResult<
|
||||
TKeyArg extends ResourceKey<CachedMapResourceKey<TResource>>,
|
||||
TResource extends CachedMapResource<any, any>
|
||||
TResource extends CachedMapResource<any, any>,
|
||||
TIncludes extends Array<keyof CachedMapResourceValue<TResource>>
|
||||
> {
|
||||
data: CachedMapResourceGetter<TKeyArg, CachedMapResourceKey<TResource>, CachedMapResourceValue<TResource>>;
|
||||
data: CachedMapResourceGetter<TKeyArg, CachedMapResourceKey<TResource>, CachedMapResourceValue<TResource>, TIncludes>;
|
||||
resource: TResource;
|
||||
isLoading: () => boolean;
|
||||
isLoaded: () => boolean;
|
||||
}
|
||||
|
||||
export function useMapResource<
|
||||
TResource extends CachedMapResource<any, any>,
|
||||
TKeyArg extends ResourceKey<CachedMapResourceKey<TResource>>,
|
||||
TIncludes extends Array<keyof CachedMapResourceValue<TResource>> = []
|
||||
>(
|
||||
ctor: IServiceConstructor<TResource>,
|
||||
key: TKeyArg | null,
|
||||
keyObj: TKeyArg | null | KeyWithIncludes<TKeyArg, TIncludes>,
|
||||
actions?: IActions<TResource>
|
||||
): IMapResourceResult<TKeyArg, TResource> {
|
||||
): IMapResourceResult<TKeyArg, TResource, TIncludes> {
|
||||
const resource = useService(ctor);
|
||||
const notifications = useService(NotificationService);
|
||||
const key = keyObj && typeof keyObj === 'object' && 'includes' in keyObj ? keyObj.key : keyObj;
|
||||
const includes = keyObj && typeof keyObj === 'object' && 'includes' in keyObj ? keyObj.includes : [];
|
||||
|
||||
const refObj = useObjectRef({
|
||||
resource,
|
||||
key,
|
||||
includes,
|
||||
actions,
|
||||
prevData: (isResourceKeyList(key) ? [] : undefined) as CachedMapResourceValue<TResource>,
|
||||
}, {
|
||||
resource,
|
||||
key,
|
||||
includes,
|
||||
actions,
|
||||
});
|
||||
|
||||
const [result] = useState<IMapResourceResult<TKeyArg, TResource>>(() => ({
|
||||
const [result] = useState<IMapResourceResult<TKeyArg, TResource, TIncludes>>(() => ({
|
||||
get resource() {
|
||||
return refObj.resource;
|
||||
},
|
||||
@@ -68,6 +80,13 @@ export function useMapResource<
|
||||
|
||||
return resource.get(refObj.key);
|
||||
},
|
||||
isLoaded: () => {
|
||||
if (refObj.key === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return resource.isLoaded(refObj.key, refObj.includes);
|
||||
},
|
||||
isLoading: () => {
|
||||
if (refObj.key === null) {
|
||||
return false;
|
||||
@@ -88,7 +107,7 @@ export function useMapResource<
|
||||
return;
|
||||
}
|
||||
|
||||
const newData = await resource.load(key);
|
||||
const newData = await resource.load(key, includes);
|
||||
|
||||
try {
|
||||
await actions?.onData?.(
|
||||
@@ -103,7 +122,7 @@ export function useMapResource<
|
||||
notifications.logException(exception, 'Can\'t load data');
|
||||
}
|
||||
})();
|
||||
}, [key]);
|
||||
}, [key, includes]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ import {
|
||||
ConnectionsAdministrationService,
|
||||
ConnectionsResource,
|
||||
ConnectionsLocaleService,
|
||||
DriverPropertiesService,
|
||||
ConnectionsAdministrationNavService,
|
||||
CreateConnectionService,
|
||||
ConnectionManualService,
|
||||
@@ -140,7 +139,6 @@ export const coreManifest: PluginManifest = {
|
||||
ContainerResource,
|
||||
DBDriverResource,
|
||||
NetworkHandlerResource,
|
||||
DriverPropertiesService,
|
||||
ConnectionsManagerService,
|
||||
ScreenService,
|
||||
AppScreenService,
|
||||
|
||||
+4
-4
@@ -14,7 +14,7 @@ import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import type { ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
|
||||
import { uuid } from '@cloudbeaver/core-utils';
|
||||
|
||||
import { DriverPropertiesService } from '../../../../DriverPropertiesService';
|
||||
import { DBDriverResource } from '../../../../DBDriverResource';
|
||||
|
||||
interface StaticId {
|
||||
staticId: string;
|
||||
@@ -35,7 +35,7 @@ export class DriverPropertiesController {
|
||||
private state!: Record<string, string>;
|
||||
|
||||
constructor(
|
||||
private driverPropertiesService: DriverPropertiesService,
|
||||
private dbDriverResource: DBDriverResource,
|
||||
private notificationService: NotificationService
|
||||
) {
|
||||
makeObservable(this, {
|
||||
@@ -68,8 +68,8 @@ export class DriverPropertiesController {
|
||||
}
|
||||
this.isLoading = true;
|
||||
try {
|
||||
const driverProperties = await this.driverPropertiesService.loadDriverProperties(this.driverId);
|
||||
this.driverProperties = observable(driverProperties.map<IProperty>(property => ({
|
||||
const driver = await this.dbDriverResource.load(this.driverId, ['driverProperties']);
|
||||
this.driverProperties = observable(driver.driverProperties.map<IProperty>(property => ({
|
||||
id: property.id!,
|
||||
key: property.id!,
|
||||
keyPlaceholder: property.id,
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ import type { IConnectionFormModel } from '../IConnectionFormModel';
|
||||
|
||||
@injectable()
|
||||
export class OptionsController
|
||||
implements IInitializableController {
|
||||
implements IInitializableController {
|
||||
get drivers(): DBDriver[] {
|
||||
return Array.from(this.dbDriverResource.data.values())
|
||||
.filter(({ id }) => this.model.availableDrivers.includes(id));
|
||||
@@ -173,7 +173,7 @@ export class OptionsController
|
||||
}
|
||||
|
||||
try {
|
||||
await this.dbDriverResource.load(driverId);
|
||||
await this.dbDriverResource.load(driverId, ['providerProperties']);
|
||||
await this.dbAuthModelsResource.load(
|
||||
this.model.connection.authModel || this.driver!.defaultAuthModel
|
||||
);
|
||||
|
||||
@@ -43,7 +43,7 @@ export class ConnectionsResource extends CachedMapResource<string, AdminConnecti
|
||||
constructor(
|
||||
private graphQLService: GraphQLService
|
||||
) {
|
||||
super(new Map());
|
||||
super();
|
||||
|
||||
makeObservable(this, {
|
||||
add: action,
|
||||
|
||||
@@ -37,7 +37,7 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
|
||||
appAuthService: AppAuthService,
|
||||
sessionResource: SessionResource
|
||||
) {
|
||||
super(new Map());
|
||||
super();
|
||||
|
||||
makeObservable(this, {
|
||||
refreshSession: action,
|
||||
|
||||
@@ -10,35 +10,22 @@ import { injectable } from '@cloudbeaver/core-di';
|
||||
import {
|
||||
GraphQLService,
|
||||
CachedMapResource,
|
||||
DriverInfo
|
||||
ResourceKey,
|
||||
ResourceKeyUtils,
|
||||
DatabaseDriverFragment
|
||||
} from '@cloudbeaver/core-sdk';
|
||||
import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
|
||||
export type DBDriver = Pick<
|
||||
DriverInfo,
|
||||
| 'id'
|
||||
| 'name'
|
||||
| 'icon'
|
||||
| 'description'
|
||||
| 'defaultPort'
|
||||
| 'defaultDatabase'
|
||||
| 'defaultServer'
|
||||
| 'defaultUser'
|
||||
| 'sampleURL'
|
||||
| 'embedded'
|
||||
| 'anonymousAccess'
|
||||
| 'promotedScore'
|
||||
| 'defaultAuthModel'
|
||||
| 'applicableNetworkHandlers'
|
||||
| 'providerProperties'
|
||||
>;
|
||||
export type DBDriver = DatabaseDriverFragment;
|
||||
|
||||
const allKey = 'all';
|
||||
|
||||
@injectable()
|
||||
export class DBDriverResource extends CachedMapResource<string, DBDriver> {
|
||||
private loadedKeyMetadata: MetadataMap<string, boolean>;
|
||||
|
||||
constructor(private graphQLService: GraphQLService) {
|
||||
super(new Map());
|
||||
super();
|
||||
this.loadedKeyMetadata = new MetadataMap(() => false);
|
||||
}
|
||||
|
||||
@@ -51,7 +38,7 @@ export class DBDriverResource extends CachedMapResource<string, DBDriver> {
|
||||
}
|
||||
|
||||
async loadAll(): Promise<Map<string, DBDriver>> {
|
||||
await this.load('all');
|
||||
await this.load(allKey);
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@@ -63,18 +50,30 @@ export class DBDriverResource extends CachedMapResource<string, DBDriver> {
|
||||
return (driverB.promotedScore || 0) - (driverA.promotedScore || 0);
|
||||
}
|
||||
|
||||
protected async loader(key: string): Promise<Map<string, DBDriver>> {
|
||||
const { driverList } = await this.graphQLService.sdk.driverList();
|
||||
protected async loader(key: ResourceKey<string>): Promise<Map<string, DBDriver>> {
|
||||
await ResourceKeyUtils.forEachAsync(key, async key => {
|
||||
const { drivers } = await this.graphQLService.sdk.driverList({
|
||||
driverId: key === allKey ? undefined : key,
|
||||
includeDriverParameters: false,
|
||||
includeDriverProperties: false,
|
||||
includeProviderProperties: false,
|
||||
...this.getIncludes(key === allKey ? undefined : key),
|
||||
});
|
||||
|
||||
this.data.clear();
|
||||
if (key === allKey) {
|
||||
this.data.clear();
|
||||
}
|
||||
|
||||
for (const driver of driverList) {
|
||||
this.set(driver.id, driver);
|
||||
}
|
||||
for (const driver of drivers) {
|
||||
this.set(driver.id, driver);
|
||||
}
|
||||
|
||||
// TODO: driverList must accept driverId, so we can update some drivers or all drivers,
|
||||
// here we should check is it's was a full update
|
||||
this.loadedKeyMetadata.set('all', true);
|
||||
if (key === allKey) {
|
||||
// TODO: driverList must accept driverId, so we can update some drivers or all drivers,
|
||||
// here we should check is it's was a full update
|
||||
this.loadedKeyMetadata.set(allKey, true);
|
||||
}
|
||||
});
|
||||
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
@injectable()
|
||||
export class DatabaseAuthModelsResource extends CachedMapResource<string, DatabaseAuthModel> {
|
||||
constructor(private graphQLService: GraphQLService) {
|
||||
super(new Map());
|
||||
super();
|
||||
}
|
||||
|
||||
protected async loader(key: string): Promise<Map<string, DatabaseAuthModel>> {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 { injectable } from '@cloudbeaver/core-di';
|
||||
import { GraphQLService, ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
|
||||
|
||||
@injectable()
|
||||
export class DriverPropertiesService {
|
||||
constructor(
|
||||
private graphQLService: GraphQLService
|
||||
) {
|
||||
}
|
||||
|
||||
async loadDriverProperties(driverId: string): Promise<ObjectPropertyInfo[]> {
|
||||
const response = await this.graphQLService.sdk.driverProperties({
|
||||
driverId,
|
||||
});
|
||||
|
||||
if (response.driver.length === 0) {
|
||||
throw new Error('Driver properties loading failed');
|
||||
}
|
||||
|
||||
return response.driver[0].driverProperties! as ObjectPropertyInfo[];
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ export class NetworkHandlerResource extends CachedMapResource<string, NetworkHan
|
||||
private readonly graphQLService: GraphQLService,
|
||||
private readonly notificationService: NotificationService
|
||||
) {
|
||||
super(new Map());
|
||||
super();
|
||||
this.loadedKeyMetadata = new MetadataMap(() => false);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ export * from './extensions/IConnectionSetter';
|
||||
export * from './ConnectionsManagerService';
|
||||
export * from './ConnectionInfoResource';
|
||||
export * from './ConnectionAuthService';
|
||||
export * from './DriverPropertiesService';
|
||||
export * from './EConnectionFeature';
|
||||
export * from './ContainerResource';
|
||||
export * from './ConnectionsLocaleService';
|
||||
|
||||
@@ -15,6 +15,7 @@ import { isConstructor } from './isConstructor';
|
||||
export class DIContainer implements IServiceInjector, IServiceCollection {
|
||||
protected container = new Container({
|
||||
defaultScope: 'Singleton',
|
||||
skipBaseClassChecks: true,
|
||||
});
|
||||
|
||||
private parent: DIContainer | null = null;
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
|
||||
import { CachedResource } from './CachedResource';
|
||||
|
||||
@injectable()
|
||||
export abstract class CachedDataResource<
|
||||
TData,
|
||||
TParam,
|
||||
|
||||
@@ -8,28 +8,46 @@
|
||||
|
||||
import { computed, makeObservable } from 'mobx';
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { Executor, IExecutor } from '@cloudbeaver/core-executor';
|
||||
import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
|
||||
import { CachedResource } from './CachedResource';
|
||||
import { CachedResource, ICachedResourceMetadata } from './CachedResource';
|
||||
import { ResourceKey, resourceKeyList, ResourceKeyList, ResourceKeyUtils } from './ResourceKeyList';
|
||||
|
||||
export type CachedMapValueIncludes<TValue, TKeys extends Array<keyof TValue>> = TValue
|
||||
& (TKeys extends Array<infer T> ?
|
||||
{
|
||||
[P in Extract<T, keyof TValue>]-?: Required<TValue>[P] extends undefined ? TValue[P] : NonNullable<TValue[P]>;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
: { });
|
||||
|
||||
export type CachedMapResourceGetter<
|
||||
TRealKey extends ResourceKey<TKey>,
|
||||
TKey,
|
||||
TValue
|
||||
TValue,
|
||||
TIncludes extends Array<keyof TValue>
|
||||
> = TRealKey extends ResourceKeyList<TKey>
|
||||
? Array<TValue | undefined>
|
||||
: TValue | undefined;
|
||||
? Array<CachedMapValueIncludes<TValue, TIncludes> | undefined>
|
||||
: CachedMapValueIncludes<TValue, TIncludes> | undefined;
|
||||
|
||||
@injectable()
|
||||
export abstract class CachedMapResource<TKey, TValue> extends CachedResource<
|
||||
Map<TKey, TValue>,
|
||||
ResourceKey<TKey>,
|
||||
TKey
|
||||
> {
|
||||
export interface ICachedMapResourceMetadata<TValue> extends ICachedResourceMetadata {
|
||||
includes: Array<keyof TValue>;
|
||||
loadedIncludes: Array<keyof TValue>;
|
||||
}
|
||||
|
||||
export abstract class CachedMapResource<
|
||||
TKey,
|
||||
TValue
|
||||
> extends CachedResource<
|
||||
Map<TKey, TValue>,
|
||||
ResourceKey<TKey>,
|
||||
TKey
|
||||
> {
|
||||
readonly onItemAdd: IExecutor<ResourceKey<TKey>>;
|
||||
readonly onItemDelete: IExecutor<ResourceKey<TKey>>;
|
||||
protected metadata: MetadataMap<TKey, ICachedMapResourceMetadata<TValue>>;
|
||||
private defaultIncludes: Array<keyof TValue>;
|
||||
|
||||
get values(): TValue[] {
|
||||
return Array.from(this.data.values());
|
||||
@@ -39,10 +57,18 @@ TKey
|
||||
return Array.from(this.data.keys());
|
||||
}
|
||||
|
||||
constructor(defaultValue?: Map<TKey, TValue>) {
|
||||
constructor(defaultIncludes?: Array<keyof TValue>, defaultValue?: Map<TKey, TValue>) {
|
||||
super(defaultValue || new Map());
|
||||
this.onItemAdd = new Executor(null, this.includes);
|
||||
this.onItemDelete = new Executor(null, this.includes);
|
||||
this.defaultIncludes = defaultIncludes || [];
|
||||
|
||||
this.metadata = new MetadataMap(() => ({
|
||||
outdated: true,
|
||||
loading: false,
|
||||
includes: this.defaultIncludes,
|
||||
loadedIncludes: this.defaultIncludes,
|
||||
}));
|
||||
|
||||
makeObservable(this, {
|
||||
values: computed,
|
||||
@@ -50,6 +76,14 @@ TKey
|
||||
});
|
||||
}
|
||||
|
||||
isIncludes(key: ResourceKey<TKey>, includes: Array<keyof TValue>): boolean {
|
||||
return ResourceKeyUtils.every(key, key => {
|
||||
const metadata = this.metadata.get(key);
|
||||
|
||||
return includes.every(include => metadata.includes.includes(include));
|
||||
});
|
||||
}
|
||||
|
||||
isOutdated(key: ResourceKey<TKey>): boolean {
|
||||
return ResourceKeyUtils.some(key, key => this.metadata.get(key).outdated);
|
||||
}
|
||||
@@ -66,6 +100,7 @@ TKey
|
||||
}
|
||||
|
||||
markDataLoaded(key: ResourceKey<TKey>): void {
|
||||
this.commitIncludes(key);
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
const metadata = this.metadata.get(key);
|
||||
metadata.loading = false;
|
||||
@@ -99,8 +134,27 @@ TKey
|
||||
});
|
||||
}
|
||||
|
||||
isLoaded(key: ResourceKey<TKey>): boolean {
|
||||
return ResourceKeyUtils.every(key, key => this.has(key));
|
||||
isLoaded(key: ResourceKey<TKey>, includes?: Array<keyof TValue>): boolean {
|
||||
return ResourceKeyUtils.every(key, key => {
|
||||
if (!this.has(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const metadata = this.metadata.get(key);
|
||||
|
||||
if (!includes) {
|
||||
includes = metadata.includes;
|
||||
}
|
||||
|
||||
if (includes.length > metadata.loadedIncludes.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (includes.some(include => !metadata.loadedIncludes.includes(include))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
get(key: TKey): TValue | undefined;
|
||||
@@ -133,20 +187,46 @@ TKey
|
||||
this.onItemDelete.execute(key);
|
||||
}
|
||||
|
||||
async refresh(key: TKey): Promise<TValue>;
|
||||
async refresh(key: ResourceKeyList<TKey>): Promise<TValue[]>;
|
||||
async refresh(key: ResourceKey<TKey>): Promise<TValue[]| TValue>;
|
||||
async refresh(key: ResourceKey<TKey>): Promise<TValue[]| TValue> {
|
||||
async refresh<T extends Array<keyof TValue> = []>(
|
||||
key: TKey,
|
||||
includes?: T
|
||||
): Promise<CachedMapValueIncludes<TValue, T>>;
|
||||
async refresh<T extends Array<keyof TValue> = []>(
|
||||
key: ResourceKeyList<TKey>,
|
||||
includes?: T
|
||||
): Promise<Array<CachedMapValueIncludes<TValue, T>>>;
|
||||
async refresh<T extends Array<keyof TValue> = []>(
|
||||
key: ResourceKey<TKey>,
|
||||
includes?: T
|
||||
): Promise<Array<CachedMapValueIncludes<TValue, T>> | CachedMapValueIncludes<TValue, T>>;
|
||||
async refresh<T extends Array<keyof TValue> = []>(
|
||||
key: ResourceKey<TKey>,
|
||||
includes?: T
|
||||
): Promise<Array<CachedMapValueIncludes<TValue, T>> | CachedMapValueIncludes<TValue, T>> {
|
||||
this.setIncludes(key, includes || []);
|
||||
await this.loadData(key, true);
|
||||
return this.get(key) as TValue[]| TValue;
|
||||
return this.get(key) as Array<CachedMapValueIncludes<TValue, T>> | CachedMapValueIncludes<TValue, T>;
|
||||
}
|
||||
|
||||
async load(key: TKey): Promise<TValue>;
|
||||
async load(key: ResourceKeyList<TKey>): Promise<TValue[]>;
|
||||
async load(key: ResourceKey<TKey>): Promise<TValue[]| TValue>;
|
||||
async load(key: ResourceKey<TKey>): Promise<TValue[]| TValue> {
|
||||
async load<T extends Array<keyof TValue> = []>(
|
||||
key: TKey,
|
||||
includes?: T
|
||||
): Promise<CachedMapValueIncludes<TValue, T>>;
|
||||
async load<T extends Array<keyof TValue> = []>(
|
||||
key: ResourceKeyList<TKey>,
|
||||
includes?: T
|
||||
): Promise<Array<CachedMapValueIncludes<TValue, T>>>;
|
||||
async load<T extends Array<keyof TValue> = []>(
|
||||
key: ResourceKey<TKey>,
|
||||
includes?: T
|
||||
): Promise<Array<CachedMapValueIncludes<TValue, T>> | CachedMapValueIncludes<TValue, T>>;
|
||||
async load<T extends Array<keyof TValue> = []>(
|
||||
key: ResourceKey<TKey>,
|
||||
includes?: T
|
||||
): Promise<Array<CachedMapValueIncludes<TValue, T>> | CachedMapValueIncludes<TValue, T>> {
|
||||
this.setIncludes(key, includes || []);
|
||||
await this.loadData(key);
|
||||
return this.get(key) as TValue[]| TValue;
|
||||
return this.get(key) as Array<CachedMapValueIncludes<TValue, T>> | CachedMapValueIncludes<TValue, T>;
|
||||
}
|
||||
|
||||
has(key: TKey): boolean {
|
||||
@@ -156,4 +236,55 @@ TKey
|
||||
includes(param: ResourceKey<TKey>, key: ResourceKey<TKey>): boolean {
|
||||
return ResourceKeyUtils.includes(param, key);
|
||||
}
|
||||
|
||||
getIncludes(key?: ResourceKey<TKey>): Record<string, any> {
|
||||
if (!key) {
|
||||
return ['base', ...this.defaultIncludes].reduce<any>((map, key) => {
|
||||
map[this.getIncludeName(key as string)] = true;
|
||||
|
||||
return map;
|
||||
}, {});
|
||||
}
|
||||
|
||||
const metadata = this.metadata.get(ResourceKeyUtils.first(key));
|
||||
|
||||
return ['base', ...metadata.includes].reduce<any>((map, key) => {
|
||||
map[this.getIncludeName(key as string)] = true;
|
||||
|
||||
return map;
|
||||
}, {});
|
||||
}
|
||||
|
||||
private setIncludes(key: ResourceKey<TKey>, includes: Array<keyof TValue>) {
|
||||
if (includes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
const metadata = this.metadata.get(key);
|
||||
|
||||
const newIncludes = [...metadata.loadedIncludes];
|
||||
|
||||
for (const include of includes) {
|
||||
if (!metadata.loadedIncludes.includes(include)) {
|
||||
newIncludes.push(include);
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata.loadedIncludes.length < newIncludes.length) {
|
||||
metadata.includes = newIncludes;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private commitIncludes(key: ResourceKey<TKey>) {
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
const metadata = this.metadata.get(key);
|
||||
metadata.loadedIncludes = metadata.includes;
|
||||
});
|
||||
}
|
||||
|
||||
private getIncludeName(key: string) {
|
||||
return 'include' + key.charAt(0).toUpperCase() + key.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import { observable, makeObservable } from 'mobx';
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { Executor, IExecutor, TaskScheduler } from '@cloudbeaver/core-executor';
|
||||
import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
|
||||
@@ -17,7 +16,6 @@ export interface ICachedResourceMetadata {
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export abstract class CachedResource<
|
||||
TData,
|
||||
TParam,
|
||||
|
||||
@@ -8,10 +8,8 @@
|
||||
|
||||
import { observable, makeObservable } from 'mobx';
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { Executor, IExecutor, TaskScheduler } from '@cloudbeaver/core-executor';
|
||||
|
||||
@injectable()
|
||||
export abstract class LocalResource<
|
||||
TData,
|
||||
TParam,
|
||||
@@ -30,7 +28,7 @@ export abstract class LocalResource<
|
||||
protected scheduler: TaskScheduler<TParam>;
|
||||
|
||||
constructor(defaultValue: TData) {
|
||||
makeObservable<LocalResource, 'outdated' | 'dataLoading' | 'loading'>(this, {
|
||||
makeObservable<LocalResource<TData, TParam>, 'outdated' | 'dataLoading' | 'loading'>(this, {
|
||||
data: observable,
|
||||
outdated: observable,
|
||||
dataLoading: observable,
|
||||
|
||||
@@ -35,6 +35,7 @@ interface MapFnc {
|
||||
}
|
||||
|
||||
export interface ResourceKeyUtils {
|
||||
first: <TKey>(key: ResourceKey<TKey>) => TKey;
|
||||
forEach: <TKey>(key: ResourceKey<TKey>, action: (key: TKey, index: number) => any) => void;
|
||||
forEachAsync: <TKey>(key: ResourceKey<TKey>, action: (key: TKey, index: number) => Promise<any>) => Promise<void>;
|
||||
some: <TKey>(key: ResourceKey<TKey>, predicate: (key: TKey, index: number) => boolean) => boolean;
|
||||
@@ -45,6 +46,16 @@ export interface ResourceKeyUtils {
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
||||
export const ResourceKeyUtils: ResourceKeyUtils = {
|
||||
first<TKey>(
|
||||
key: ResourceKey<TKey>
|
||||
): TKey {
|
||||
if (isResourceKeyList(key)) {
|
||||
return key.list[0];
|
||||
} else {
|
||||
return key;
|
||||
}
|
||||
},
|
||||
|
||||
forEach<TKey>(
|
||||
key: ResourceKey<TKey>,
|
||||
action: (key: TKey, index: number) => any | Promise<any>
|
||||
|
||||
@@ -1,32 +1,5 @@
|
||||
query driverList {
|
||||
driverList {
|
||||
id
|
||||
name
|
||||
icon
|
||||
description
|
||||
defaultPort
|
||||
defaultDatabase
|
||||
defaultServer
|
||||
defaultUser
|
||||
sampleURL
|
||||
embedded
|
||||
anonymousAccess
|
||||
promotedScore
|
||||
|
||||
defaultAuthModel
|
||||
# applicableAuthModel
|
||||
|
||||
providerProperties {
|
||||
id
|
||||
displayName
|
||||
description
|
||||
category
|
||||
dataType
|
||||
defaultValue
|
||||
validValues
|
||||
features
|
||||
order
|
||||
}
|
||||
applicableNetworkHandlers
|
||||
query driverList($driverId: ID, $includeProviderProperties: Boolean!, $includeDriverProperties: Boolean!, $includeDriverParameters: Boolean!) {
|
||||
drivers: driverList(id: $driverId) {
|
||||
...DatabaseDriver
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
query driverProperties($driverId: ID!) {
|
||||
driver: driverList(id: $driverId) {
|
||||
driverProperties {
|
||||
id
|
||||
displayName
|
||||
description
|
||||
category
|
||||
dataType
|
||||
defaultValue
|
||||
validValues
|
||||
}
|
||||
driverParameters
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
query getDriverById($driverId: ID!) {
|
||||
driverList(id: $driverId) {
|
||||
id
|
||||
name
|
||||
icon
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ fragment AdminConnection on ConnectionInfo {
|
||||
|
||||
template
|
||||
connected
|
||||
provided
|
||||
useUrl
|
||||
readOnly
|
||||
saveCredentials
|
||||
@@ -38,6 +39,10 @@ fragment AdminConnection on ConnectionInfo {
|
||||
properties
|
||||
}
|
||||
|
||||
navigatorSettings {
|
||||
...AllNavigatorSettings
|
||||
}
|
||||
|
||||
features
|
||||
supportedDataFormats
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
fragment DatabaseDriver on DriverInfo {
|
||||
id
|
||||
name
|
||||
icon
|
||||
description
|
||||
defaultPort
|
||||
defaultDatabase
|
||||
defaultServer
|
||||
defaultUser
|
||||
sampleURL
|
||||
embedded
|
||||
anonymousAccess
|
||||
promotedScore
|
||||
|
||||
defaultAuthModel
|
||||
# applicableAuthModel
|
||||
applicableNetworkHandlers
|
||||
|
||||
providerProperties @include(if: $includeProviderProperties) {
|
||||
id
|
||||
displayName
|
||||
description
|
||||
category
|
||||
dataType
|
||||
defaultValue
|
||||
validValues
|
||||
features
|
||||
order
|
||||
}
|
||||
|
||||
driverProperties @include(if: $includeDriverProperties) {
|
||||
id
|
||||
displayName
|
||||
description
|
||||
category
|
||||
dataType
|
||||
defaultValue
|
||||
validValues
|
||||
}
|
||||
driverParameters @include(if: $includeDriverParameters)
|
||||
}
|
||||
@@ -335,6 +335,7 @@ export interface MutationDeleteConnectionArgs {
|
||||
export interface MutationInitConnectionArgs {
|
||||
id: Scalars['ID'];
|
||||
credentials?: Maybe<Scalars['Object']>;
|
||||
networkCredentials?: Maybe<NetworkHandlerConfigInput[]>;
|
||||
saveCredentials?: Maybe<Scalars['Boolean']>;
|
||||
}
|
||||
|
||||
@@ -1110,25 +1111,14 @@ export type DeleteConnectionMutationVariables = Exact<{
|
||||
|
||||
export type DeleteConnectionMutation = Pick<Mutation, 'deleteConnection'>;
|
||||
|
||||
export type DriverListQueryVariables = Exact<{ [key: string]: never }>;
|
||||
|
||||
export interface DriverListQuery {
|
||||
driverList: Array<(
|
||||
Pick<DriverInfo, 'id' | 'name' | 'icon' | 'description' | 'defaultPort' | 'defaultDatabase' | 'defaultServer' | 'defaultUser' | 'sampleURL' | 'embedded' | 'anonymousAccess' | 'promotedScore' | 'defaultAuthModel' | 'applicableNetworkHandlers'>
|
||||
& { providerProperties: Array<Pick<ObjectPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'defaultValue' | 'validValues' | 'features' | 'order'>> }
|
||||
)>;
|
||||
}
|
||||
|
||||
export type DriverPropertiesQueryVariables = Exact<{
|
||||
driverId: Scalars['ID'];
|
||||
export type DriverListQueryVariables = Exact<{
|
||||
driverId?: Maybe<Scalars['ID']>;
|
||||
includeProviderProperties: Scalars['Boolean'];
|
||||
includeDriverProperties: Scalars['Boolean'];
|
||||
includeDriverParameters: Scalars['Boolean'];
|
||||
}>;
|
||||
|
||||
export interface DriverPropertiesQuery {
|
||||
driver: Array<(
|
||||
Pick<DriverInfo, 'driverParameters'>
|
||||
& { driverProperties: Array<Pick<ObjectPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'defaultValue' | 'validValues'>> }
|
||||
)>;
|
||||
}
|
||||
export interface DriverListQuery { drivers: DatabaseDriverFragment[] }
|
||||
|
||||
export type GetAuthModelsQueryVariables = Exact<{ [key: string]: never }>;
|
||||
|
||||
@@ -1151,12 +1141,6 @@ export type GetConnectionOriginDetailsQueryVariables = Exact<{
|
||||
|
||||
export interface GetConnectionOriginDetailsQuery { connection: { origin: { details?: Maybe<Array<Pick<ObjectPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'defaultValue' | 'validValues' | 'value' | 'features' | 'order'>>> } } }
|
||||
|
||||
export type GetDriverByIdQueryVariables = Exact<{
|
||||
driverId: Scalars['ID'];
|
||||
}>;
|
||||
|
||||
export interface GetDriverByIdQuery { driverList: Array<Pick<DriverInfo, 'id' | 'name' | 'icon'>> }
|
||||
|
||||
export type GetTemplateConnectionsQueryVariables = Exact<{ [key: string]: never }>;
|
||||
|
||||
export interface GetTemplateConnectionsQuery { connections: UserConnectionFragment[] }
|
||||
@@ -1242,8 +1226,8 @@ export type NavGetStructContainersQueryVariables = Exact<{
|
||||
export interface NavGetStructContainersQuery { navGetStructContainers: { catalogList: Array<Pick<DatabaseObjectInfo, 'name' | 'description' | 'type' | 'features'>>; schemaList: Array<Pick<DatabaseObjectInfo, 'name' | 'description' | 'type' | 'features'>> } }
|
||||
|
||||
export type AdminConnectionFragment = (
|
||||
Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'template' | 'connected' | 'useUrl' | 'readOnly' | 'saveCredentials' | 'host' | 'port' | 'databaseName' | 'url' | 'properties' | 'providerProperties' | 'features' | 'authNeeded' | 'authModel' | 'supportedDataFormats'>
|
||||
& { origin: ObjectOriginInfoFragment; authProperties: UserConnectionAuthPropertiesFragment[]; networkHandlersConfig: Array<Pick<NetworkHandlerConfig, 'id' | 'enabled' | 'userName' | 'password' | 'savePassword' | 'properties'>> }
|
||||
Pick<ConnectionInfo, 'id' | 'name' | 'description' | 'driverId' | 'template' | 'connected' | 'provided' | 'useUrl' | 'readOnly' | 'saveCredentials' | 'host' | 'port' | 'databaseName' | 'url' | 'properties' | 'providerProperties' | 'features' | 'authNeeded' | 'authModel' | 'supportedDataFormats'>
|
||||
& { origin: ObjectOriginInfoFragment; authProperties: UserConnectionAuthPropertiesFragment[]; networkHandlersConfig: Array<Pick<NetworkHandlerConfig, 'id' | 'enabled' | 'userName' | 'password' | 'savePassword' | 'properties'>>; navigatorSettings: AllNavigatorSettingsFragment }
|
||||
);
|
||||
|
||||
export type AdminUserInfoFragment = (
|
||||
@@ -1253,6 +1237,11 @@ export type AdminUserInfoFragment = (
|
||||
|
||||
export type AllNavigatorSettingsFragment = Pick<NavigatorSettings, 'showSystemObjects' | 'showUtilityObjects' | 'showOnlyEntities' | 'mergeEntities' | 'hideFolders' | 'hideSchemas' | 'hideVirtualModel'>;
|
||||
|
||||
export type DatabaseDriverFragment = (
|
||||
MakeOptional<Pick<DriverInfo, 'id' | 'name' | 'icon' | 'description' | 'defaultPort' | 'defaultDatabase' | 'defaultServer' | 'defaultUser' | 'sampleURL' | 'embedded' | 'anonymousAccess' | 'promotedScore' | 'defaultAuthModel' | 'applicableNetworkHandlers' | 'driverParameters'>, 'driverParameters'>
|
||||
& { providerProperties: Array<Pick<ObjectPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'defaultValue' | 'validValues' | 'features' | 'order'>>; driverProperties: Array<Pick<ObjectPropertyInfo, 'id' | 'displayName' | 'description' | 'category' | 'dataType' | 'defaultValue' | 'validValues'>> }
|
||||
);
|
||||
|
||||
export type NavNodeInfoFragment = (
|
||||
Pick<NavigatorNodeInfo, 'id' | 'name' | 'hasChildren' | 'nodeType' | 'icon' | 'folder' | 'inline' | 'navigable' | 'features'>
|
||||
& { object?: Maybe<Pick<DatabaseObjectInfo, 'features'>>; nodeDetails?: Maybe<NavNodePropertiesFragment[]> }
|
||||
@@ -1484,7 +1473,7 @@ export type ServerConfigQueryVariables = Exact<{ [key: string]: never }>;
|
||||
|
||||
export interface ServerConfigQuery {
|
||||
serverConfig: (
|
||||
Pick<ServerConfig, 'name' | 'version' | 'productConfiguration' | 'supportsCustomConnections' | 'supportsConnectionBrowser' | 'supportsWorkspaces' | 'sessionExpireTime' | 'anonymousAccessEnabled' | 'authenticationEnabled' | 'configurationMode' | 'developmentMode'>
|
||||
Pick<ServerConfig, 'name' | 'version' | 'productConfiguration' | 'supportsCustomConnections' | 'supportsConnectionBrowser' | 'supportsWorkspaces' | 'sessionExpireTime' | 'anonymousAccessEnabled' | 'authenticationEnabled' | 'adminCredentialsSaveEnabled' | 'publicCredentialsSaveEnabled' | 'configurationMode' | 'developmentMode'>
|
||||
& { supportedLanguages: Array<Pick<ServerLanguage, 'isoCode' | 'displayName' | 'nativeName'>>; defaultNavigatorSettings: AllNavigatorSettingsFragment }
|
||||
);
|
||||
}
|
||||
@@ -1555,6 +1544,17 @@ export const UserConnectionAuthPropertiesFragmentDoc = `
|
||||
order
|
||||
}
|
||||
`;
|
||||
export const AllNavigatorSettingsFragmentDoc = `
|
||||
fragment AllNavigatorSettings on NavigatorSettings {
|
||||
showSystemObjects
|
||||
showUtilityObjects
|
||||
showOnlyEntities
|
||||
mergeEntities
|
||||
hideFolders
|
||||
hideSchemas
|
||||
hideVirtualModel
|
||||
}
|
||||
`;
|
||||
export const AdminConnectionFragmentDoc = `
|
||||
fragment AdminConnection on ConnectionInfo {
|
||||
id
|
||||
@@ -1563,6 +1563,7 @@ export const AdminConnectionFragmentDoc = `
|
||||
driverId
|
||||
template
|
||||
connected
|
||||
provided
|
||||
useUrl
|
||||
readOnly
|
||||
saveCredentials
|
||||
@@ -1589,11 +1590,15 @@ export const AdminConnectionFragmentDoc = `
|
||||
savePassword
|
||||
properties
|
||||
}
|
||||
navigatorSettings {
|
||||
...AllNavigatorSettings
|
||||
}
|
||||
features
|
||||
supportedDataFormats
|
||||
}
|
||||
${ObjectOriginInfoFragmentDoc}
|
||||
${UserConnectionAuthPropertiesFragmentDoc}`;
|
||||
${UserConnectionAuthPropertiesFragmentDoc}
|
||||
${AllNavigatorSettingsFragmentDoc}`;
|
||||
export const AdminUserInfoFragmentDoc = `
|
||||
fragment AdminUserInfo on AdminUserInfo {
|
||||
userId
|
||||
@@ -1603,6 +1608,45 @@ export const AdminUserInfoFragmentDoc = `
|
||||
}
|
||||
}
|
||||
${ObjectOriginInfoFragmentDoc}`;
|
||||
export const DatabaseDriverFragmentDoc = `
|
||||
fragment DatabaseDriver on DriverInfo {
|
||||
id
|
||||
name
|
||||
icon
|
||||
description
|
||||
defaultPort
|
||||
defaultDatabase
|
||||
defaultServer
|
||||
defaultUser
|
||||
sampleURL
|
||||
embedded
|
||||
anonymousAccess
|
||||
promotedScore
|
||||
defaultAuthModel
|
||||
applicableNetworkHandlers
|
||||
providerProperties @include(if: $includeProviderProperties) {
|
||||
id
|
||||
displayName
|
||||
description
|
||||
category
|
||||
dataType
|
||||
defaultValue
|
||||
validValues
|
||||
features
|
||||
order
|
||||
}
|
||||
driverProperties @include(if: $includeDriverProperties) {
|
||||
id
|
||||
displayName
|
||||
description
|
||||
category
|
||||
dataType
|
||||
defaultValue
|
||||
validValues
|
||||
}
|
||||
driverParameters @include(if: $includeDriverParameters)
|
||||
}
|
||||
`;
|
||||
export const NavNodePropertiesFragmentDoc = `
|
||||
fragment NavNodeProperties on ObjectPropertyInfo {
|
||||
id
|
||||
@@ -1642,17 +1686,6 @@ export const SessionStateFragmentDoc = `
|
||||
locale
|
||||
}
|
||||
`;
|
||||
export const AllNavigatorSettingsFragmentDoc = `
|
||||
fragment AllNavigatorSettings on NavigatorSettings {
|
||||
showSystemObjects
|
||||
showUtilityObjects
|
||||
showOnlyEntities
|
||||
mergeEntities
|
||||
hideFolders
|
||||
hideSchemas
|
||||
hideVirtualModel
|
||||
}
|
||||
`;
|
||||
export const UserConnectionFragmentDoc = `
|
||||
fragment UserConnection on ConnectionInfo {
|
||||
id
|
||||
@@ -1938,52 +1971,12 @@ export const DeleteConnectionDocument = `
|
||||
}
|
||||
`;
|
||||
export const DriverListDocument = `
|
||||
query driverList {
|
||||
driverList {
|
||||
id
|
||||
name
|
||||
icon
|
||||
description
|
||||
defaultPort
|
||||
defaultDatabase
|
||||
defaultServer
|
||||
defaultUser
|
||||
sampleURL
|
||||
embedded
|
||||
anonymousAccess
|
||||
promotedScore
|
||||
defaultAuthModel
|
||||
providerProperties {
|
||||
id
|
||||
displayName
|
||||
description
|
||||
category
|
||||
dataType
|
||||
defaultValue
|
||||
validValues
|
||||
features
|
||||
order
|
||||
}
|
||||
applicableNetworkHandlers
|
||||
query driverList($driverId: ID, $includeProviderProperties: Boolean!, $includeDriverProperties: Boolean!, $includeDriverParameters: Boolean!) {
|
||||
drivers: driverList(id: $driverId) {
|
||||
...DatabaseDriver
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const DriverPropertiesDocument = `
|
||||
query driverProperties($driverId: ID!) {
|
||||
driver: driverList(id: $driverId) {
|
||||
driverProperties {
|
||||
id
|
||||
displayName
|
||||
description
|
||||
category
|
||||
dataType
|
||||
defaultValue
|
||||
validValues
|
||||
}
|
||||
driverParameters
|
||||
}
|
||||
}
|
||||
`;
|
||||
${DatabaseDriverFragmentDoc}`;
|
||||
export const GetAuthModelsDocument = `
|
||||
query getAuthModels {
|
||||
models: authModels {
|
||||
@@ -2039,15 +2032,6 @@ export const GetConnectionOriginDetailsDocument = `
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const GetDriverByIdDocument = `
|
||||
query getDriverById($driverId: ID!) {
|
||||
driverList(id: $driverId) {
|
||||
id
|
||||
name
|
||||
icon
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const GetTemplateConnectionsDocument = `
|
||||
query getTemplateConnections {
|
||||
connections: templateConnections {
|
||||
@@ -2641,12 +2625,9 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
|
||||
deleteConnection(variables: DeleteConnectionMutationVariables): Promise<DeleteConnectionMutation> {
|
||||
return withWrapper(() => client.request<DeleteConnectionMutation>(DeleteConnectionDocument, variables));
|
||||
},
|
||||
driverList(variables?: DriverListQueryVariables): Promise<DriverListQuery> {
|
||||
driverList(variables: DriverListQueryVariables): Promise<DriverListQuery> {
|
||||
return withWrapper(() => client.request<DriverListQuery>(DriverListDocument, variables));
|
||||
},
|
||||
driverProperties(variables: DriverPropertiesQueryVariables): Promise<DriverPropertiesQuery> {
|
||||
return withWrapper(() => client.request<DriverPropertiesQuery>(DriverPropertiesDocument, variables));
|
||||
},
|
||||
getAuthModels(variables?: GetAuthModelsQueryVariables): Promise<GetAuthModelsQuery> {
|
||||
return withWrapper(() => client.request<GetAuthModelsQuery>(GetAuthModelsDocument, variables));
|
||||
},
|
||||
@@ -2656,9 +2637,6 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
|
||||
getConnectionOriginDetails(variables: GetConnectionOriginDetailsQueryVariables): Promise<GetConnectionOriginDetailsQuery> {
|
||||
return withWrapper(() => client.request<GetConnectionOriginDetailsQuery>(GetConnectionOriginDetailsDocument, variables));
|
||||
},
|
||||
getDriverById(variables: GetDriverByIdQueryVariables): Promise<GetDriverByIdQuery> {
|
||||
return withWrapper(() => client.request<GetDriverByIdQuery>(GetDriverByIdDocument, variables));
|
||||
},
|
||||
getTemplateConnections(variables?: GetTemplateConnectionsQueryVariables): Promise<GetTemplateConnectionsQuery> {
|
||||
return withWrapper(() => client.request<GetTemplateConnectionsQuery>(GetTemplateConnectionsDocument, variables));
|
||||
},
|
||||
|
||||
+3
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
import { observable, action, makeObservable } from 'mobx';
|
||||
|
||||
import { DBDriver, DatabaseAuthModelsResource, ConnectionInfoResource, getUniqueConnectionName } from '@cloudbeaver/core-connections';
|
||||
import { DBDriver, DatabaseAuthModelsResource, ConnectionInfoResource, getUniqueConnectionName, DBDriverResource } from '@cloudbeaver/core-connections';
|
||||
import { injectable, IInitializableController, IDestructibleController } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService } from '@cloudbeaver/core-dialogs';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
@@ -53,6 +53,7 @@ implements IInitializableController, IDestructibleController {
|
||||
private maxHostLength = 20;
|
||||
|
||||
constructor(
|
||||
private dbDriverResource: DBDriverResource,
|
||||
private customConnectionService: CustomConnectionService,
|
||||
private notificationService: NotificationService,
|
||||
private commonDialogService: CommonDialogService,
|
||||
@@ -222,6 +223,7 @@ implements IInitializableController, IDestructibleController {
|
||||
}
|
||||
|
||||
try {
|
||||
await this.dbDriverResource.load(this.driver.id, ['providerProperties']);
|
||||
this.authModel = await this.dbAuthModelsResource.load(this.driver.defaultAuthModel);
|
||||
} catch (exception) {
|
||||
this.notificationService.logException(exception, 'Can\'t load driver auth model');
|
||||
|
||||
+4
-4
@@ -9,7 +9,7 @@
|
||||
import { observable, makeObservable } from 'mobx';
|
||||
|
||||
import type { IProperty } from '@cloudbeaver/core-blocks';
|
||||
import { DBDriver, DriverPropertiesService } from '@cloudbeaver/core-connections';
|
||||
import { DBDriver, DBDriverResource } from '@cloudbeaver/core-connections';
|
||||
import { injectable, IInitializableController } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import type { ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
|
||||
@@ -37,7 +37,7 @@ export class DriverPropertiesController implements IInitializableController {
|
||||
private state!: Record<string, string>;
|
||||
|
||||
constructor(
|
||||
private driverPropertiesService: DriverPropertiesService,
|
||||
private dbDriverResource: DBDriverResource,
|
||||
private notificationService: NotificationService
|
||||
) {
|
||||
makeObservable(this, {
|
||||
@@ -70,8 +70,8 @@ export class DriverPropertiesController implements IInitializableController {
|
||||
}
|
||||
this.isLoading = true;
|
||||
try {
|
||||
const driverProperties = await this.driverPropertiesService.loadDriverProperties(this.driver.id);
|
||||
this.driverProperties = observable(driverProperties.map<IProperty>(property => ({
|
||||
const driver = await this.dbDriverResource.load(this.driver.id, ['driverProperties']);
|
||||
this.driverProperties = observable(driver.driverProperties.map<IProperty>(property => ({
|
||||
id: property.id!,
|
||||
key: property.id!,
|
||||
displayName: property.displayName!,
|
||||
|
||||
Reference in New Issue
Block a user