diff --git a/webapp/packages/core-app/src/AppScreen/Main.tsx b/webapp/packages/core-app/src/AppScreen/Main.tsx
index 910fb81cfb..cf4211b5e8 100644
--- a/webapp/packages/core-app/src/AppScreen/Main.tsx
+++ b/webapp/packages/core-app/src/AppScreen/Main.tsx
@@ -9,7 +9,7 @@
import { observer } from 'mobx-react-lite';
import styled, { css } from 'reshadow';
-import { splitStyles, Split, ResizerControls, Pane, useSplitUserState, useStyles, Loader } from '@cloudbeaver/core-blocks';
+import { splitStyles, Split, ResizerControls, Pane, useSplitUserState, useStyles, Loader, getComputed } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { LeftBarPanelService, SideBarPanel, SideBarPanelService } from '@cloudbeaver/core-ui';
@@ -38,11 +38,8 @@ export const Main = observer(function Main() {
const splitMainState = useSplitUserState('main');
const splitRightState = useSplitUserState('main-right');
- const activeSideBars = sideBarPanelService.tabsContainer.getDisplayed();
- const activeLeftBars = leftBarPanelService.tabsContainer.getDisplayed();
-
- const sideBarDisabled = activeSideBars.length === 0;
- const leftBarDisabled = activeLeftBars.length === 0;
+ const sideBarDisabled = getComputed(() => sideBarPanelService.tabsContainer.getDisplayed().length === 0);
+ const leftBarDisabled = getComputed(() => leftBarPanelService.tabsContainer.getDisplayed().length === 0);
return styled(styles)(
diff --git a/webapp/packages/core-blocks/src/Loader/Loader.tsx b/webapp/packages/core-blocks/src/Loader/Loader.tsx
index 9ecbb4f027..f6d991bf5a 100644
--- a/webapp/packages/core-blocks/src/Loader/Loader.tsx
+++ b/webapp/packages/core-blocks/src/Loader/Loader.tsx
@@ -242,7 +242,10 @@ export const Loader = observer(function Loader({
return renderWrappedChildren();
}
- if (exception && !loading && !hideException) {
+ if (exception && !loading) {
+ if (hideException) {
+ return null;
+ }
return styled(style)(
> = T & {
@@ -35,8 +34,8 @@ export const Placeholder = observer(function Placeholder
+ <>
{elements.map(({ id, component: Component }) => )}
-
+ >
);
});
diff --git a/webapp/packages/core-blocks/src/PropertiesTable/PropertyItem.tsx b/webapp/packages/core-blocks/src/PropertiesTable/PropertyItem.tsx
index 169456d69a..78e6aa42be 100644
--- a/webapp/packages/core-blocks/src/PropertiesTable/PropertyItem.tsx
+++ b/webapp/packages/core-blocks/src/PropertiesTable/PropertyItem.tsx
@@ -183,6 +183,20 @@ export const PropertyItem = observer(function PropertyItem({
>
{propertyValue}
+ {edited && !isDeletable && (
+
+
+
+ )}
+ {isDeletable && (
+
+
+
+ )}
{(!readOnly && property.validValues && property.validValues.length > 0) && (
(function PropertyItem({
)}
- {edited && !isDeletable && (
-
-
-
- )}
- {isDeletable && (
-
-
-
- )}
);
});
diff --git a/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts b/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts
index d0a208f591..9e4c481a4d 100644
--- a/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts
+++ b/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
-import { computed, observable, toJS, untracked, when } from 'mobx';
+import { action, computed, observable, reaction, toJS, untracked, when } from 'mobx';
import { useEffect, useContext, useState } from 'react';
import { IServiceConstructor, useService } from '@cloudbeaver/core-di';
@@ -271,6 +271,7 @@ export function useResource<
}
},
}), {
+ load: action,
resourceException: computed,
exception: observable.ref,
loadingPromise: observable.ref,
@@ -323,9 +324,9 @@ export function useResource<
}
// React Suspense block
- if (refObj.loadingPromise) {
- throw refObj.loadingPromise;
- }
+ // if (refObj.loadingPromise) {
+ // throw refObj.loadingPromise;
+ // }
if (this.loading) {
throw this.resource.waitLoad();
@@ -395,30 +396,24 @@ export function useResource<
}, { preloaded });
useEffect(() => {
- let prevData: any;
- const disposeDataUpdate = when(
- () => {
- try {
- if (result.isError()) {
- return false;
- }
- result.data;
- return true;
- } catch {
- return false;
- }
+ const disposeDataUpdate = reaction(
+ () => result.data,
+ (data, prev) => {
+ actions?.onData?.(data as any, resource, prev as any);
},
- () => {
- const newData = result.data;
- refObj.actions?.onData?.(newData, resource, prevData);
- prevData = newData;
+ {
+ onError: () => {},
+ fireImmediately: true,
}
);
- const disposeErrorUpdate = when(
- () => result.isError(),
- () => {
+ const disposeErrorUpdate = reaction(
+ () => result.exception,
+ exception => {
+ if (!result.isError()) {
+ return;
+ }
if (propertiesRef.errorContext) {
- const errors = Array.isArray(result.exception) ? result.exception : [result.exception];
+ const errors = Array.isArray(exception) ? exception : [exception];
for (const error of errors) {
if (error) {
@@ -426,7 +421,10 @@ export function useResource<
}
}
}
- refObj.actions?.onError?.(result.exception);
+ actions?.onError?.(exception);
+ },
+ {
+ fireImmediately: true,
}
);
return () => {
diff --git a/webapp/packages/core-blocks/src/getComputed.ts b/webapp/packages/core-blocks/src/getComputed.ts
index b2c34eb7ba..eaba4bb973 100644
--- a/webapp/packages/core-blocks/src/getComputed.ts
+++ b/webapp/packages/core-blocks/src/getComputed.ts
@@ -8,6 +8,6 @@
import { computed } from 'mobx';
-export function getComputed(action: () => T): T {
- return computed(action).get();
+export function getComputed(action: () => T, equals?: (a: T, b: T) => boolean): T {
+ return computed(action, { equals }).get();
}
diff --git a/webapp/packages/core-bootstrap/src/renderLayout.tsx b/webapp/packages/core-bootstrap/src/renderLayout.tsx
index 8e279d2f9d..9f52c70854 100644
--- a/webapp/packages/core-bootstrap/src/renderLayout.tsx
+++ b/webapp/packages/core-bootstrap/src/renderLayout.tsx
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
-import { StrictMode, Suspense } from 'react';
+import { Suspense } from 'react';
import { createRoot, Root } from 'react-dom/client';
import styled from 'reshadow';
@@ -52,7 +52,6 @@ export function renderLayout(serviceInjector: IServiceInjector): IRender {
height: 100vh;
}
`(
- //
}>
@@ -60,7 +59,6 @@ export function renderLayout(serviceInjector: IServiceInjector): IRender {
- //
));
},
renderError(exception?: any) {
diff --git a/webapp/packages/core-di/src/AppContext.tsx b/webapp/packages/core-di/src/AppContext.tsx
index cfaff4c7cd..7588dc2ee6 100644
--- a/webapp/packages/core-di/src/AppContext.tsx
+++ b/webapp/packages/core-di/src/AppContext.tsx
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
-import { createContext } from 'react';
+import { createContext, StrictMode } from 'react';
import type { IServiceInjector } from './IApp';
import { useAppLoadingScreen } from './useAppLoadingScreen';
@@ -19,5 +19,9 @@ interface Props {
export const AppContext: React.FC> = function AppContext({ app, children }) {
useAppLoadingScreen();
- return {children};
+ return (
+ // // problems with TabState when empty -> displayed state switch
+ {children}
+ //
+ );
};
diff --git a/webapp/packages/core-ui/src/Tabs/TabsState.tsx b/webapp/packages/core-ui/src/Tabs/TabsState.tsx
index 8b4b3cd591..aaae6dd2ed 100644
--- a/webapp/packages/core-ui/src/Tabs/TabsState.tsx
+++ b/webapp/packages/core-ui/src/Tabs/TabsState.tsx
@@ -13,7 +13,7 @@ import { useTabState } from 'reakit/Tab';
import { useExecutor, useObjectRef, useObservableRef } from '@cloudbeaver/core-blocks';
import { Executor, ExecutorInterrupter } from '@cloudbeaver/core-executor';
-import { MetadataMap, MetadataValueGetter } from '@cloudbeaver/core-utils';
+import { isNull, isUndefined, MetadataMap, MetadataValueGetter } from '@cloudbeaver/core-utils';
import type { ITabData, ITabsContainer } from './TabsContainer/ITabsContainer';
import { TabsContext, ITabsContext } from './TabsContext';
@@ -96,12 +96,21 @@ export const TabsState = observer(function TabsState>({
tabList,
});
- if (currentTabId !== undefined && currentTabId !== null) {
+ if (
+ !isNull(currentTabId)
+ && !isUndefined(currentTabId)
+ ) {
state.selectedId = currentTabId;
dynamic.selectedId = currentTabId;
}
- if (displayed.length > 0 && dynamic.selectedId && selectedId) {
+ if (
+ displayed.length > 0
+ && !isNull(dynamic.selectedId)
+ && !isUndefined(dynamic.selectedId)
+ && !isNull(selectedId)
+ && !isUndefined(selectedId)
+ ) {
const tabExists = displayed.includes(dynamic.selectedId);
if (!tabExists) {
@@ -134,7 +143,10 @@ export const TabsState = observer(function TabsState>({
});
useEffect(() => {
- if (currentTabId !== undefined && currentTabId !== null) {
+ if (
+ !isNull(currentTabId)
+ && !isUndefined(currentTabId)
+ ) {
return;
}
@@ -145,13 +157,16 @@ export const TabsState = observer(function TabsState>({
}, [currentTabId, state.selectedId]);
useEffect(() => {
- if (state.selectedId) {
+ if (
+ !isNull(state.selectedId)
+ && !isUndefined(state.selectedId)
+ ) {
openExecutor.execute({
- tabId: state.selectedId!,
+ tabId: state.selectedId,
props,
});
}
- }, []);
+ }, [!isNull(state.selectedId) && !isUndefined(state.selectedId)]);
const value = useObservableRef>(() => ({
getTabInfo(tabId: string) {
diff --git a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/Form/ServerConfigurationFeaturesForm.tsx b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/Form/ServerConfigurationFeaturesForm.tsx
index 98a0757042..d66235a7b7 100644
--- a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/Form/ServerConfigurationFeaturesForm.tsx
+++ b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/Form/ServerConfigurationFeaturesForm.tsx
@@ -11,7 +11,7 @@ import { useContext } from 'react';
import styled from 'reshadow';
import { AdministrationSettingsService } from '@cloudbeaver/core-administration';
-import { BASE_CONTAINERS_STYLES, FormContext, GroupTitle, Loader, PlaceholderComponent, Switch, useResource, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
+import { BASE_CONTAINERS_STYLES, FormContext, GroupTitle, PlaceholderComponent, Switch, useResource, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { FeaturesResource } from '@cloudbeaver/core-root';
import type { IConfigurationPlaceholderProps } from '@cloudbeaver/plugin-administration';
@@ -20,16 +20,21 @@ export const ServerConfigurationFeaturesForm: PlaceholderComponent
{translate('administration_configuration_wizard_configuration_services_group')}
-
- {() => styled(styles)(
- <>
- {features.data.map(feature => (
-
- {feature.label}
-
- ))}
- >
- )}
-
+ {features.data.map(feature => (
+
+ {feature.label}
+
+ ))}
>
);
});
diff --git a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationPage.tsx b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationPage.tsx
index ab99415eee..51c7f9a3b4 100644
--- a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationPage.tsx
+++ b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationPage.tsx
@@ -36,6 +36,10 @@ const styles = css`
white-space: pre-wrap;
line-height: 2;
}
+
+ Loader {
+ height: 100%;
+ }
`;
export const ServerConfigurationPage: AdministrationItemContentComponent = observer(function ServerConfigurationPage({
@@ -118,27 +122,29 @@ export const ServerConfigurationPage: AdministrationItemContentComponent = obser
)}
{() => styled(style)(
-
-
-
- {translate('administration_configuration_wizard_configuration_plugins')}
-
-
-
+
+
+
+
+ {translate('administration_configuration_wizard_configuration_plugins')}
+
+
+
+
+
-
-
-
-
-
+
+
+
+
)}
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/IdentityProviders/AuthConfigurationForm.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/IdentityProviders/AuthConfigurationForm.tsx
index 60af6b5b3c..983b5e0469 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/IdentityProviders/AuthConfigurationForm.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/IdentityProviders/AuthConfigurationForm.tsx
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
import { useEffect } from 'react';
import styled, { css } from 'reshadow';
-import { Placeholder, useObjectRef, useExecutor, BASE_CONTAINERS_STYLES, IconOrImage, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
+import { Placeholder, useObjectRef, useExecutor, BASE_CONTAINERS_STYLES, IconOrImage, useTranslate, useStyles, Loader } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import type { AdminAuthProviderConfiguration } from '@cloudbeaver/core-sdk';
import { TabsState, TabList, UNDERLINE_TAB_STYLES, TabPanelList, BASE_TAB_STYLES } from '@cloudbeaver/core-ui';
@@ -149,7 +149,9 @@ export const AuthConfigurationForm = observer(function AuthConfigurationF
-
+
+
+
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/IdentityProviders/AuthConfigurationsTable/AuthConfiguration.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/IdentityProviders/AuthConfigurationsTable/AuthConfiguration.tsx
index 6179972148..0b497fe002 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/IdentityProviders/AuthConfigurationsTable/AuthConfiguration.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/IdentityProviders/AuthConfigurationsTable/AuthConfiguration.tsx
@@ -12,7 +12,7 @@ import styled, { css, use } from 'reshadow';
import { AuthProvidersResource } from '@cloudbeaver/core-authentication';
import {
TableItem, TableColumnValue, TableItemSelect, TableItemExpand,
- Placeholder, StaticImage, useResource, FieldCheckbox
+ Placeholder, StaticImage, useResource, FieldCheckbox, Loader
} from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import type { AdminAuthProviderConfiguration } from '@cloudbeaver/core-sdk';
@@ -65,7 +65,9 @@ export const AuthConfiguration = observer(function AuthConfiguration({ co
-
+
+
+
);
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/ServerConfiguration/AuthenticationProviders.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/ServerConfiguration/AuthenticationProviders.tsx
index b088acccb5..489e0f61a5 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/ServerConfiguration/AuthenticationProviders.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/ServerConfiguration/AuthenticationProviders.tsx
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
import React, { useContext } from 'react';
import styled from 'reshadow';
-import { AuthProviderService, AuthProvidersResource, AuthSettingsService, AUTH_PROVIDER_LOCAL_ID } from '@cloudbeaver/core-authentication';
+import { AuthProvider, AuthProviderService, AuthProvidersResource, AuthSettingsService, AUTH_PROVIDER_LOCAL_ID } from '@cloudbeaver/core-authentication';
import { BASE_CONTAINERS_STYLES, FormContext, Group, GroupTitle, Loader, PlaceholderComponent, Switch, useExecutor, useResource, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { CachedMapAllKey } from '@cloudbeaver/core-sdk';
@@ -33,8 +33,8 @@ export const AuthenticationProviders: PlaceholderComponent {
- if (configurationWizard && provider.configurable) {
+ const providerList = providers.data.filter((provider): provider is AuthProvider => {
+ if (configurationWizard && provider?.configurable) {
return false;
}
@@ -89,56 +89,51 @@ export const AuthenticationProviders: PlaceholderComponent
) : null}
-
- {() => styled(styles)(
- <>
- {providerList.map(provider => {
- const links = authProviderService.getServiceDescriptionLinks(provider);
- let disabled = provider.requiredFeatures.some(feat => !serverConfig.enabledFeatures?.includes(feat));
- const tooltip = disabled ? `Following services need to be enabled: "${provider.requiredFeatures.join(', ')}"` : '';
- if (
- !localProvider
+ {providerList.map(provider => {
+ const links = authProviderService.getServiceDescriptionLinks(provider);
+ let disabled = provider.requiredFeatures.some(feat => !serverConfig.enabledFeatures?.includes(feat));
+ const tooltip = disabled ? `Following services need to be enabled: "${provider.requiredFeatures.join(', ')}"` : '';
+
+ if (
+ !localProvider
&& primaryProvider?.id === provider.id
&& serverConfig.enabledAuthProviders?.length === 1
&& serverConfig.enabledAuthProviders.includes(provider.id)
- ) {
- disabled = true;
- }
+ ) {
+ disabled = true;
+ }
- if (provider.private || (configurationWizard && (disabled || provider.id !== AUTH_PROVIDER_LOCAL_ID))) {
- return null;
- }
+ if (provider.private || (configurationWizard && (disabled || provider.id !== AUTH_PROVIDER_LOCAL_ID))) {
+ return null;
+ }
- return (
-
- {provider.description}
- {links.map(link => {
- const Description = link.description();
- return ;
- })}
- >
- )}
- mod={['primary']}
- disabled={disabled}
- small
- autoHide
- >
- {provider.label}
-
- );
- })}
- >
- )}
-
+ return (
+
+ {provider.description}
+ {links.map(link => {
+ const Description = link.description();
+ return ;
+ })}
+ >
+ )}
+ mod={['primary']}
+ disabled={disabled}
+ small
+ autoHide
+ >
+ {provider.label}
+
+ );
+ })}
{configurationWizard && localProvider && (
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoForm.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoForm.tsx
new file mode 100644
index 0000000000..40e6e9463b
--- /dev/null
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoForm.tsx
@@ -0,0 +1,46 @@
+/*
+ * CloudBeaver - Cloud Database Manager
+ * Copyright (C) 2020-2022 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 { observer } from 'mobx-react-lite';
+import styled from 'reshadow';
+
+import { UserMetaParametersResource } from '@cloudbeaver/core-authentication';
+import { BASE_CONTAINERS_STYLES, Container, ObjectPropertyInfoForm, useResource, useStyles } from '@cloudbeaver/core-blocks';
+import type { UserInfo } from '@cloudbeaver/core-sdk';
+import type { ComponentStyle } from '@cloudbeaver/core-theming';
+
+interface Props {
+ user: UserInfo;
+ className?: string;
+ style?: ComponentStyle;
+}
+
+export const MetaParameterInfoForm = observer(function MetaParameterInfoForm({
+ user,
+ className,
+ style,
+}) {
+ const userMetaParameters = useResource(MetaParameterInfoForm, UserMetaParametersResource, undefined);
+ const styles = useStyles(style, BASE_CONTAINERS_STYLES);
+
+ if (!userMetaParameters.data.length) {
+ return null;
+ }
+
+ return styled(styles)(
+
+
+
+ );
+});
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoPanel.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoPanel.tsx
index 517c9196c0..d9666c5904 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoPanel.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoPanel.tsx
@@ -9,14 +9,12 @@
import { observer } from 'mobx-react-lite';
import styled from 'reshadow';
-import { UserMetaParametersResource } from '@cloudbeaver/core-authentication';
-import { TabPanel } from '@cloudbeaver/core-ui';
-import { BASE_CONTAINERS_STYLES, ColoredContainer, Container, Group, InputField, Loader, ObjectPropertyInfoForm, useResource, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
-
+import { useStyles } from '@cloudbeaver/core-blocks';
import type { UserInfo } from '@cloudbeaver/core-sdk';
import type { ComponentStyle } from '@cloudbeaver/core-theming';
+import { TabPanel } from '@cloudbeaver/core-ui';
-import { AuthProvidersList } from '../AuthProviders/ConfigurationsList';
+import { MetaParametersForm } from './MetaParametersForm';
interface Props {
user: UserInfo;
@@ -29,66 +27,11 @@ export const MetaParameterInfoPanel = observer(function MetaParameterInfo
className,
style,
}) {
- const userMetaParameters = useResource(MetaParameterInfoPanel, UserMetaParametersResource, undefined);
- const styles = useStyles(style, BASE_CONTAINERS_STYLES);
- const translate = useTranslate();
+ const styles = useStyles(style);
return styled(styles)(
-
-
-
-
-
- {translate('plugin_user_profile_info_id')}
-
-
- {translate('plugin_user_profile_info_displayName')}
-
-
-
-
- {() => userMetaParameters.data.length > 0 && styled(styles)(
-
-
-
- )}
-
-
-
-
-
-
-
-
+
);
});
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoTab.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoTab.tsx
index fe2c9f61c8..b423bef863 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoTab.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParameterInfoTab.tsx
@@ -9,9 +9,9 @@
import { observer } from 'mobx-react-lite';
import styled from 'reshadow';
+import type { ComponentStyle } from '@cloudbeaver/core-theming';
import { Tab } from '@cloudbeaver/core-ui';
-import type { ComponentStyle } from '@cloudbeaver/core-theming';
interface Props {
className?: string;
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParametersForm.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParametersForm.tsx
new file mode 100644
index 0000000000..d082a975dd
--- /dev/null
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/MetaParameters/Form/UserInfo/MetaParametersForm.tsx
@@ -0,0 +1,76 @@
+/*
+ * CloudBeaver - Cloud Database Manager
+ * Copyright (C) 2020-2022 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 { observer } from 'mobx-react-lite';
+import styled from 'reshadow';
+
+import { BASE_CONTAINERS_STYLES, ColoredContainer, Container, Group, InputField, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
+import type { UserInfo } from '@cloudbeaver/core-sdk';
+import type { ComponentStyle } from '@cloudbeaver/core-theming';
+
+import { AuthProvidersList } from '../AuthProviders/ConfigurationsList';
+import { MetaParameterInfoForm } from './MetaParameterInfoForm';
+
+interface Props {
+ user: UserInfo;
+ className?: string;
+ style?: ComponentStyle;
+}
+
+export const MetaParametersForm = observer(function MetaParametersForm({
+ user,
+ className,
+ style,
+}) {
+ const styles = useStyles(style, BASE_CONTAINERS_STYLES);
+ const translate = useTranslate();
+
+ return styled(styles)(
+
+
+
+
+
+ {translate('plugin_user_profile_info_id')}
+
+
+ {translate('plugin_user_profile_info_displayName')}
+
+
+
+
+
+
+
+
+
+
+ );
+});
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnections.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnections.tsx
index aafba41634..e88c7b079a 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnections.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/GrantedConnections.tsx
@@ -12,7 +12,7 @@ import styled, { css } from 'reshadow';
import {
BASE_CONTAINERS_STYLES, ColoredContainer, Container, getComputed, Group,
- InfoItem, Loader, TextPlaceholder, useResource, useStyles, useTranslate
+ InfoItem, Loader, TextPlaceholder, useAutoLoad, useResource, useStyles, useTranslate
} from '@cloudbeaver/core-blocks';
import { Connection, ConnectionInfoProjectKey, ConnectionInfoResource, DBDriverResource, isCloudConnection } from '@cloudbeaver/core-connections';
import type { TLocalizationToken } from '@cloudbeaver/core-localization';
@@ -60,7 +60,7 @@ export const GrantedConnections: TabContainerPanelComponent = ob
.map(project => project.id)
);
- const dbDriverResource = useResource(
+ useResource(
GrantedConnections,
DBDriverResource,
CachedMapAllKey,
@@ -80,11 +80,7 @@ export const GrantedConnections: TabContainerPanelComponent = ob
.filter(connection => state.state.grantedSubjects.includes(connection.id))
);
- useEffect(() => {
- if (selected && !loaded) {
- state.load();
- }
- });
+ useAutoLoad(state, selected && !loaded);
if (!selected) {
return null;
@@ -103,7 +99,7 @@ export const GrantedConnections: TabContainerPanelComponent = ob
}
return styled(style)(
-
+
{() => styled(style)(
{!connections.length ? (
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/useGrantedConnections.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/useGrantedConnections.tsx
index ede71f60f9..e9d03b9a03 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/useGrantedConnections.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedConnections/useGrantedConnections.tsx
@@ -13,12 +13,12 @@ import { useObservableRef } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { useTabState } from '@cloudbeaver/core-ui';
-import { isArraysEqual } from '@cloudbeaver/core-utils';
+import { ILoadableState, isArraysEqual } from '@cloudbeaver/core-utils';
import type { TeamFormMode } from '../ITeamFormProps';
import type { IGrantedConnectionsTabState } from './IGrantedConnectionsTabState';
-interface State {
+interface State extends ILoadableState {
state: IGrantedConnectionsTabState;
changed: boolean;
edit: () => void;
@@ -36,6 +36,15 @@ export function useGrantedConnections(team: TeamInfo, mode: TeamFormMode): Reado
get changed() {
return !isArraysEqual(this.state.initialGrantedSubjects, this.state.grantedSubjects);
},
+ isLoading() {
+ return this.state.loading;
+ },
+ isLoaded() {
+ return this.state.loaded;
+ },
+ isError() {
+ return false;
+ },
edit() {
this.state.editing = !this.state.editing;
},
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx
index 69f9dca4d8..48b21c53ff 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUsers.tsx
@@ -6,15 +6,13 @@
* you may not use this file except in compliance with the License.
*/
-import { computed } from 'mobx';
import { observer } from 'mobx-react-lite';
-import { useEffect, useMemo } from 'react';
import styled, { css } from 'reshadow';
-import { UsersResource } from '@cloudbeaver/core-authentication';
+import { AdminUser, UsersResource } from '@cloudbeaver/core-authentication';
import {
- BASE_CONTAINERS_STYLES, ColoredContainer, Container, Group,
- InfoItem, Loader, TextPlaceholder, useResource, useStyles, useTranslate
+ BASE_CONTAINERS_STYLES, ColoredContainer, Container, getComputed, Group,
+ InfoItem, Loader, TextPlaceholder, useAutoLoad, useResource, useStyles, useTranslate
} from '@cloudbeaver/core-blocks';
import { CachedMapAllKey } from '@cloudbeaver/core-sdk';
import { TabContainerPanelComponent, useTab } from '@cloudbeaver/core-ui';
@@ -51,24 +49,20 @@ export const GrantedUsers: TabContainerPanelComponent = observer
const state = useGrantedUsers(formState.config, formState.mode);
const { selected } = useTab(tabId);
- const users = useResource(GrantedUsers, UsersResource, selected ? CachedMapAllKey : null);
+ const users = useResource(GrantedUsers, UsersResource, CachedMapAllKey, { active: selected });
- const grantedUsers = useMemo(() => computed(() => users.resource.values
- .filter(user => state.state.grantedUsers.includes(user.userId))
- ), [state.state.grantedUsers, users.resource]);
+ const grantedUsers = getComputed(() => users.data
+ .filter((user): user is AdminUser => !!user && state.state.grantedUsers.includes(user.userId))
+ );
- useEffect(() => {
- if (selected && !state.state.loaded) {
- state.load();
- }
- }, [selected, state.state.loaded]);
+ useAutoLoad(state, selected && !state.state.loaded);
if (!selected) {
return null;
}
return styled(style)(
-
+
{() => styled(style)(
{!users.resource.values.length ? (
@@ -80,7 +74,7 @@ export const GrantedUsers: TabContainerPanelComponent = observer
{formState.mode === 'edit' && state.changed && }
void;
@@ -36,6 +36,15 @@ export function useGrantedUsers(team: TeamInfo, mode: TeamFormMode): Readonly(function TeamMetaParameters({
+ state,
+}) {
+ const teamMetaParameters = useResource(TeamMetaParameters, TeamMetaParametersResource, undefined);
+ const translate = useTranslate();
+ const style = useStyles(BASE_CONTAINERS_STYLES);
+
+ if (teamMetaParameters.data.length > 0) {
+ return null;
+ }
+
+ return styled(style)(
+
+ {translate('authentication_team_meta_parameters')}
+
+
+ );
+});
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Options/TeamOptions.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Options/TeamOptions.tsx
index 12eb189fcb..2045db1bad 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Options/TeamOptions.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/Options/TeamOptions.tsx
@@ -10,13 +10,13 @@ import { observer } from 'mobx-react-lite';
import { useRef } from 'react';
import styled, { css } from 'reshadow';
-import { TeamMetaParametersResource } from '@cloudbeaver/core-authentication';
import { BASE_CONTAINERS_STYLES, ColoredContainer, Group, InputField, SubmittingForm, Textarea, useTranslate, useStyles, useResource, Loader, GroupTitle, ObjectPropertyInfoForm } from '@cloudbeaver/core-blocks';
import { ServerConfigResource } from '@cloudbeaver/core-root';
import type { TabContainerPanelComponent } from '@cloudbeaver/core-ui';
import type { ITeamFormProps } from '../ITeamFormProps';
import { Permissions } from './Permissions';
+import { TeamMetaParameters } from './TeamMetaParameters';
const styles = css`
SubmittingForm {
@@ -28,13 +28,10 @@ const styles = css`
export const TeamOptions: TabContainerPanelComponent = observer(function TeamOptions({
state,
}) {
- const formRef = useRef(null);
-
- const translate = useTranslate();
const serverConfigResource = useResource(TeamOptions, ServerConfigResource, undefined);
- const teamMetaParameters = useResource(TeamOptions, TeamMetaParametersResource, undefined);
-
const style = useStyles(BASE_CONTAINERS_STYLES, styles);
+ const formRef = useRef(null);
+ const translate = useTranslate();
const edit = state.mode === 'edit';
return styled(style)(
@@ -74,20 +71,7 @@ export const TeamOptions: TabContainerPanelComponent = observer(
{!serverConfigResource.resource.distributed && }
-
- {() => teamMetaParameters.data.length > 0 && styled(style)(
-
- {translate('authentication_team_meta_parameters')}
-
-
- )}
-
+
);
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.tsx
index 7f38bab62e..0651dd1b53 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamForm.tsx
@@ -11,7 +11,7 @@ import { useEffect } from 'react';
import styled, { css } from 'reshadow';
import type { TeamInfo } from '@cloudbeaver/core-authentication';
-import { Placeholder, useObjectRef, useExecutor, BASE_CONTAINERS_STYLES, IconOrImage, useTranslate, useStyles } from '@cloudbeaver/core-blocks';
+import { Placeholder, useObjectRef, useExecutor, BASE_CONTAINERS_STYLES, IconOrImage, useTranslate, useStyles, Loader } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { TabsState, TabList, UNDERLINE_TAB_STYLES, TabPanelList, BASE_TAB_STYLES } from '@cloudbeaver/core-ui';
@@ -150,7 +150,9 @@ export const TeamForm = observer(function TeamForm({
-
+
+
+
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsTable/Team.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsTable/Team.tsx
index d4b3838c3b..54a6c82f5a 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsTable/Team.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsTable/Team.tsx
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
import styled, { css, use } from 'reshadow';
import type { TeamInfo } from '@cloudbeaver/core-authentication';
-import { TableItem, TableColumnValue, TableItemSelect, TableItemExpand, Placeholder, useStyles } from '@cloudbeaver/core-blocks';
+import { TableItem, TableColumnValue, TableItemSelect, TableItemExpand, Placeholder, useStyles, Loader } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
@@ -53,7 +53,9 @@ export const Team = observer(function Team({ team }) {
{team.teamName || ''}
{team.description || ''}
-
+
+
+
);
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/User.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/User.tsx
index 166040da27..0ba5172c6a 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/User.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/User.tsx
@@ -11,7 +11,7 @@ import styled, { css, use } from 'reshadow';
import { AdminUser, UsersResource } from '@cloudbeaver/core-authentication';
import {
- TableItem, TableColumnValue, TableItemSelect, TableItemExpand, Placeholder, Checkbox, useTranslate
+ TableItem, TableColumnValue, TableItemSelect, TableItemExpand, Placeholder, Checkbox, useTranslate, Loader
} from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
@@ -76,7 +76,9 @@ export const User = observer(function User({ user, displayAuthRole, selec
/>
-
+
+
+
);
diff --git a/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx b/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx
index e37127a2e5..5cf5eb96f7 100644
--- a/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx
+++ b/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx
@@ -184,21 +184,17 @@ export const AuthDialog: DialogComponent = observer(function
)}
-
- {() => federate
- ? (
- {
- state.setActiveConfiguration(provider, configuration);
- }}
- onClose={rejectDialog}
- />
- )
- : renderForm(state.activeProvider)}
-
+ {federate ? (
+ {
+ state.setActiveConfiguration(provider, configuration);
+ }}
+ onClose={rejectDialog}
+ />
+ ) : renderForm(state.activeProvider)}
{!federate && (
diff --git a/webapp/packages/plugin-authentication/src/Dialog/useAuthDialogState.ts b/webapp/packages/plugin-authentication/src/Dialog/useAuthDialogState.ts
index cdada1b164..64ff6e88ce 100644
--- a/webapp/packages/plugin-authentication/src/Dialog/useAuthDialogState.ts
+++ b/webapp/packages/plugin-authentication/src/Dialog/useAuthDialogState.ts
@@ -26,7 +26,6 @@ interface IData {
destroyed: boolean;
configure: boolean;
adminPageActive: boolean;
- loadingState: ILoadableState;
providers: AuthProvider[];
configurations: AuthProvider[];
@@ -52,7 +51,7 @@ export function useAuthDialogState(accessRequest: boolean, providerId: string |
const primaryId = authProvidersResource.resource.getPrimary();
const adminPageActive = administrationScreenService.isAdministrationPageActive;
- const providers = authProvidersResource.resource.values
+ const providers = authProvidersResource.data
.filter(notEmptyProvider)
.sort(compareProviders);
@@ -129,7 +128,6 @@ export function useAuthDialogState(accessRequest: boolean, providerId: string |
exception: null,
authenticating: false,
destroyed: false,
- loadingState: authProvidersResource,
get configure(): boolean {
if (state.activeProvider) {
@@ -197,7 +195,7 @@ export function useAuthDialogState(accessRequest: boolean, providerId: string |
}
function notEmptyProvider(obj: any): obj is AuthProvider {
- return typeof obj === 'object';
+ return !!obj && typeof obj === 'object';
}
function compareProviders(providerA: AuthProvider, providerB: AuthProvider): number {
diff --git a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/Connection.tsx b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/Connection.tsx
index 5639ae6ade..d4e282229b 100644
--- a/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/Connection.tsx
+++ b/webapp/packages/plugin-connections-administration/src/Administration/Connections/ConnectionsTable/Connection.tsx
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
import styled, { css } from 'reshadow';
import {
- TableItem, TableColumnValue, TableItemSelect, TableItemExpand, StaticImage, Placeholder
+ TableItem, TableColumnValue, TableItemSelect, TableItemExpand, StaticImage, Placeholder, Loader
} from '@cloudbeaver/core-blocks';
import { DatabaseConnection, DBDriverResource, IConnectionInfoParams } from '@cloudbeaver/core-connections';
import { useService } from '@cloudbeaver/core-di';
@@ -65,10 +65,12 @@ export const Connection = observer(function Connection({ connectionKey, c
{projectName !== undefined && (
{projectName})}
-
+
+
+
);
diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.tsx
index 7485cf8768..82d3800b9d 100644
--- a/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.tsx
+++ b/webapp/packages/plugin-connections/src/ConnectionForm/ConnectionForm.tsx
@@ -175,7 +175,9 @@ export const ConnectionForm = observer(function ConnectionForm({
-
+
+
+
diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/DriverProperties/DriverProperties.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/DriverProperties/DriverProperties.tsx
index 32fde09876..79f9dee4cc 100644
--- a/webapp/packages/plugin-connections/src/ConnectionForm/DriverProperties/DriverProperties.tsx
+++ b/webapp/packages/plugin-connections/src/ConnectionForm/DriverProperties/DriverProperties.tsx
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
-import { computed, observable } from 'mobx';
+import { computed, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react-lite';
import { useMemo, useState } from 'react';
import styled, { css } from 'reshadow';
@@ -64,21 +64,23 @@ export const DriverProperties: TabContainerPanelComponent
DriverProperties,
DBDriverResource,
{ key: (selected && formState.config.driverId) || null, includes: ['includeDriverProperties'] as const },
- {
- active: selected && !!formState.config.driverId,
- onData: driver => {
- for (const key of Object.keys(formState.config.properties)) {
- if (driver.driverProperties.some(property => property.id === key)
- || state.propertiesList.some(property => property.key === key)) {
- continue;
- }
-
- state.add(key, formState.config.properties[key]);
- }
- },
- }
);
+ runInAction(() => {
+ if (driver.data) {
+ for (const key of Object.keys(formState.config.properties)) {
+ if (
+ driver.data.driverProperties.some(property => property.id === key)
+ || state.propertiesList.some(property => property.key === key)
+ ) {
+ continue;
+ }
+
+ state.add(key, formState.config.properties[key]);
+ }
+ }
+ });
+
const joinedProperties = useMemo(() => computed(() => ([
...state.propertiesList,
...(driver.data?.driverProperties
@@ -96,21 +98,17 @@ export const DriverProperties: TabContainerPanelComponent
])), [driver.data]);
return styled(style)(
-
- {() => styled(style)(
-
-
-
-
-
- )}
-
+
+
+
+
+
);
});
diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx
index 83e3ad97d3..0011ca7062 100644
--- a/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx
+++ b/webapp/packages/plugin-connections/src/ConnectionForm/Options/Options.tsx
@@ -99,17 +99,6 @@ export const Options: TabContainerPanelComponent = observe
const optionsHook = useOptions(state);
const { credentialsSavingEnabled } = useAdministrationSettings();
- const handleDriverSelect = useCallback(async (value?: string, name?: string, prev?: string) => {
- if (!value) {
- return;
- }
-
- const prevDriver = prev ? await driverMap.resource.load(prev) : undefined;
- const newDriver = await driverMap.resource.load(value);
-
- optionsHook.setDefaults(newDriver, prevDriver);
- }, []);
-
const handleAuthModelSelect = useCallback(async (value?: string, name?: string, prev?: string) => {
const model = applicableAuthModels.find(model => model?.id === value);
@@ -125,10 +114,8 @@ export const Options: TabContainerPanelComponent = observe
DBDriverResource,
{ key: config.driverId || null, includes: ['includeProviderProperties'] as const },
{
- onData: (data, resource, prevData) => {
- if (data.id !== prevData?.id) {
- optionsHook.setDefaults(data);
- }
+ onData: (data, resource, prevDriver) => {
+ optionsHook.setDefaults(data, prevDriver);
},
}
);
@@ -222,7 +209,6 @@ export const Options: TabContainerPanelComponent = observe
loading={driverMap.isLoading()}
tiny
fill
- onSelect={handleDriverSelect}
>
{translate('connections_connection_driver')}
diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/ElementsTreeTools/NavigationTreeSettings/NavigationTreeSettings.tsx b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/ElementsTreeTools/NavigationTreeSettings/NavigationTreeSettings.tsx
index 607fd30d74..bcad092362 100644
--- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/ElementsTreeTools/NavigationTreeSettings/NavigationTreeSettings.tsx
+++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/ElementsTreeTools/NavigationTreeSettings/NavigationTreeSettings.tsx
@@ -9,10 +9,9 @@
import { observer } from 'mobx-react-lite';
import styled, { css } from 'reshadow';
-import { BASE_CONTAINERS_STYLES, Group, Placeholder, PlaceholderElement, useStyles } from '@cloudbeaver/core-blocks';
+import { BASE_CONTAINERS_STYLES, Group, Loader, Placeholder, PlaceholderElement, useStyles } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
-
import { ElementsTreeSettingsService, IElementsTreeSettingsProps } from './ElementsTreeSettingsService';
const expandStyles = css`
@@ -47,12 +46,14 @@ export const NavigationTreeSettings = observer(function NavigationTreeSet
return styled(styles)(
-
+
+
+
);
diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx
index 3fda0aaf11..c9df37090e 100644
--- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx
+++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx
@@ -48,9 +48,7 @@ export const VirtualFolderPanel: NavNodeTransformViewComponent = observer(functi
});
useEffect(() => {
- untracked(() => {
- navNodeViewService.logDuplicates(nodeId, duplicates);
- });
+ navNodeViewService.logDuplicates(nodeId, duplicates);
});
const objects = dbObject.data
diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx
index 3d5e434ca8..10f0ddd07c 100644
--- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx
+++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx
@@ -52,9 +52,7 @@ export const ObjectPropertyTable = observer(function O
});
useEffect(() => {
- untracked(() => {
- navNodeViewService.logDuplicates(objectId, duplicates);
- });
+ navNodeViewService.logDuplicates(objectId, duplicates);
});
const objects = dbObject.data.filter(object => nodes.includes(object?.id ?? '')) as DBObject[];
diff --git a/webapp/packages/plugin-resource-manager/src/Tree/ResourceManagerTree.tsx b/webapp/packages/plugin-resource-manager/src/Tree/ResourceManagerTree.tsx
index ad052f61ed..30b2e730c0 100644
--- a/webapp/packages/plugin-resource-manager/src/Tree/ResourceManagerTree.tsx
+++ b/webapp/packages/plugin-resource-manager/src/Tree/ResourceManagerTree.tsx
@@ -10,12 +10,13 @@ import { observer } from 'mobx-react-lite';
import { useMemo } from 'react';
import styled, { css } from 'reshadow';
-import { useResource, useUserData } from '@cloudbeaver/core-blocks';
+import { getComputed, useResource, useUserData } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { NavNodeInfoResource, NavTreeResource, ProjectsNavNodeService } from '@cloudbeaver/core-navigation-tree';
import { ProjectInfoResource, ProjectsService } from '@cloudbeaver/core-projects';
import { IResourceManagerParams, ResourceManagerResource, RESOURCES_NODE_PATH } from '@cloudbeaver/core-resource-manager';
import { resourceKeyList } from '@cloudbeaver/core-sdk';
+import { isArraysEqual } from '@cloudbeaver/core-utils';
import { CaptureView } from '@cloudbeaver/core-view';
import { NavigationTreeService, ElementsTreeLoader, IElementsTreeSettings, createElementsTreeSettings, validateElementsTreeSettings, getNavigationTreeUserSettingsId } from '@cloudbeaver/plugin-navigation-tree';
@@ -79,9 +80,13 @@ export const ResourceManagerTree: React.FC = observer(function ResourceMa
const resourceManagerService = useService(ResourceManagerService);
const navTreeResource = useService(NavTreeResource);
- const key: IResourceManagerParams[] = projectsService.activeProjectIds.map(id => ({ projectId: id }));
+ const key = getComputed(
+ () => projectsService.activeProjects.map(project => ({ projectId: project.id })),
+ isArraysEqual
+ );
useResource(ResourceManagerTree, ResourceManagerResource, resourceKeyList(key));
+
const settings = useUserData(
getNavigationTreeUserSettingsId(root),
createElementsTreeSettings,
@@ -166,7 +171,6 @@ export const ResourceManagerTree: React.FC = observer(function ResourceMa
const settingsElements = useMemo(() => ([ProjectsSettingsPlaceholderElement]), []);
-
return styled(styles)(