diff --git a/webapp/packages/core-administration/src/Administration/Administration.tsx b/webapp/packages/core-administration/src/Administration/Administration.tsx index 196f933e58..41debaffad 100644 --- a/webapp/packages/core-administration/src/Administration/Administration.tsx +++ b/webapp/packages/core-administration/src/Administration/Administration.tsx @@ -79,7 +79,7 @@ export const Administration: React.FC = observer(function Administration( const contentRef = useRef(null); const administrationItemService = useService(AdministrationItemService); const items = administrationItemService.getActiveItems(configurationWizard); - const hasOnlyActive = items.some(filterOnlyActive); + const hasOnlyActive = items.some(filterOnlyActive(configurationWizard)); useLayoutEffect(() => { contentRef.current?.scrollTo({ top: 0, left: 0 }); diff --git a/webapp/packages/core-administration/src/Administration/DrawerItem.tsx b/webapp/packages/core-administration/src/Administration/DrawerItem.tsx index f837cc753d..7203ee69d6 100644 --- a/webapp/packages/core-administration/src/Administration/DrawerItem.tsx +++ b/webapp/packages/core-administration/src/Administration/DrawerItem.tsx @@ -24,7 +24,7 @@ export const DrawerItem = observer(function DrawerItem({ disabled = !configurationWizardService.isStepAvailable(item.name); } - const onlyActive = filterOnlyActive(item) ? false : disabled; + const onlyActive = filterOnlyActive(configurationWizard)(item) ? false : disabled; return ( { + if (a.replace && b.replace) { + return (b.replace.priority ?? Number.MIN_SAFE_INTEGER) - (a.replace.priority ?? Number.MIN_SAFE_INTEGER); + } + return 0; + }) + .filter(item => !item.replace?.condition || item.replace.condition(configurationWizard)); + + let lastItem: IAdministrationItem | null = null; + for (const item of orderedByPriority) { + if (lastItem?.name === item.name) { + continue; + } + items.push(item); + lastItem = item; + } + + return items; + } + getActiveItems(configurationWizard: boolean): IAdministrationItem[] { - return this.items.filter(item => - filterHiddenAdministrationItem(item) + return this.getUniqueItems(configurationWizard).filter(item => + filterHiddenAdministrationItem(configurationWizard)(item) && filterConfigurationWizard(configurationWizard)(item) ).sort(orderAdministrationItems(configurationWizard)); } @@ -42,7 +66,7 @@ export class AdministrationItemService { return null; } - const onlyActive = items.find(filterOnlyActive); + const onlyActive = items.find(filterOnlyActive(configurationWizard)); if (onlyActive) { return onlyActive.name; @@ -60,11 +84,7 @@ export class AdministrationItemService { } getItem(name: string, configurationWizard: boolean): IAdministrationItem | null { - const item = this.items.find(item => ( - filterHiddenAdministrationItem(item) - && filterConfigurationWizard(configurationWizard)(item) - && item.name === name - )); + const item = this.getActiveItems(configurationWizard).find(item => item.name === name); if (!item) { return null; @@ -82,7 +102,7 @@ export class AdministrationItemService { return sub; } - create(options: IAdministrationItemOptions, replace?: boolean): void { + create(options: IAdministrationItemOptions): void { const type = options.type ?? AdministrationItemType.Administration; const existedIndex = this.items.findIndex(item => item.name === options.name && ( @@ -91,7 +111,7 @@ export class AdministrationItemService { || type === AdministrationItemType.Default )); - if (!replace && existedIndex !== -1) { + if (!options.replace && existedIndex !== -1) { throw new Error(`Administration item "${options.name}" already exists in the same visibility scope`); } @@ -101,11 +121,7 @@ export class AdministrationItemService { sub: options.sub ?? [], order: options.order ?? Number.MAX_SAFE_INTEGER, }; - if (replace && existedIndex !== -1) { - this.items.splice(existedIndex, 1, item); - } else { - this.items.push(item); - } + this.items.push(item); } async activate( @@ -113,12 +129,16 @@ export class AdministrationItemService { configurationWizard: boolean, outside: boolean ): Promise { - const item = this.getItem(screen.item, configurationWizard); - if (!item) { - return; + if (configurationWizard) { + const items = this.getActiveItems(configurationWizard); + + for (const item of items) { + await item.configurationWizardOptions?.onLoad?.(); + } } - if (!filterHiddenAdministrationItem(item)) { + const item = this.getItem(screen.item, configurationWizard); + if (!item) { return; } @@ -139,10 +159,6 @@ export class AdministrationItemService { return; } - if (!filterHiddenAdministrationItem(item)) { - return; - } - await item.onDeActivate?.(configurationWizard, outside); if (screen.sub) { @@ -160,10 +176,6 @@ export class AdministrationItemService { return false; } - if (!filterHiddenAdministrationItem(item)) { - return false; - } - if (item.canActivate && !(await item.canActivate(configurationWizard, outside))) { return false; } @@ -179,18 +191,22 @@ export class AdministrationItemService { } } -export function filterHiddenAdministrationItem(item: IAdministrationItem): boolean { - if (typeof item.isHidden === 'function') { - return !item.isHidden(); - } +export function filterHiddenAdministrationItem(configurationWizard: boolean): (item: IAdministrationItem) => boolean { + return function filterHiddenAdministrationItem(item: IAdministrationItem) { + if (typeof item.isHidden === 'function') { + return !item.isHidden(configurationWizard); + } - return !item.isHidden; + return !item.isHidden; + }; } -export function filterOnlyActive(item: IAdministrationItem): boolean { - if (typeof item.isOnlyActive === 'function') { - return item.isOnlyActive(); - } +export function filterOnlyActive(configurationWizard: boolean): (item: IAdministrationItem) => boolean { + return function filterOnlyActive(item: IAdministrationItem) { + if (typeof item.isOnlyActive === 'function') { + return item.isOnlyActive(configurationWizard); + } - return item.isOnlyActive === true; + return item.isOnlyActive === true; + }; } diff --git a/webapp/packages/core-administration/src/AdministrationItem/IAdministrationItem.ts b/webapp/packages/core-administration/src/AdministrationItem/IAdministrationItem.ts index 6f0ec32ee2..61b370d814 100644 --- a/webapp/packages/core-administration/src/AdministrationItem/IAdministrationItem.ts +++ b/webapp/packages/core-administration/src/AdministrationItem/IAdministrationItem.ts @@ -16,6 +16,11 @@ export enum AdministrationItemType { ConfigurationWizard } +export interface IAdministrationItemReplaceOptions { + priority: number; + condition?: (configurationWizard: boolean) => boolean; +} + export interface AdministrationItemDrawerProps { item: IAdministrationItem; configurationWizard: boolean; @@ -69,8 +74,9 @@ export interface IConfigurationWizardItemOptions { isDisabled?: () => boolean; isHidden?: () => boolean; isDone?: () => boolean; + onLoad?: () => Promise | void; onFinish?: () => Promise | boolean; - onConfigurationFinish?: () => Promise | void; + onConfigurationFinish?: () => Promise | any; } export interface IAdministrationItemOptions { @@ -80,8 +86,9 @@ export interface IAdministrationItemOptions { configurationWizardOptions?: IConfigurationWizardItemOptions; order?: number; sub?: IAdministrationItemSubItem[]; - isHidden?: (() => boolean) | boolean; - isOnlyActive?: (() => boolean) | boolean; + isHidden?: ((configurationWizard: boolean) => boolean) | boolean; + isOnlyActive?: ((configurationWizard: boolean) => boolean) | boolean; + replace?: IAdministrationItemReplaceOptions; getDrawerComponent: () => AdministrationItemDrawerComponent; getContentComponent: () => AdministrationItemContentComponent; onActivate?: AdministrationItemEvent; diff --git a/webapp/packages/core-administration/src/AdministrationScreen/ConfigurationWizard/ConfigurationWizardService.ts b/webapp/packages/core-administration/src/AdministrationScreen/ConfigurationWizard/ConfigurationWizardService.ts index 8ce6b5abd1..5d5ddb776b 100644 --- a/webapp/packages/core-administration/src/AdministrationScreen/ConfigurationWizard/ConfigurationWizardService.ts +++ b/webapp/packages/core-administration/src/AdministrationScreen/ConfigurationWizard/ConfigurationWizardService.ts @@ -11,7 +11,7 @@ import { computed, makeObservable } from 'mobx'; import { injectable } from '@cloudbeaver/core-di'; import { ScreenService } from '@cloudbeaver/core-routing'; -import { AdministrationItemService } from '../../AdministrationItem/AdministrationItemService'; +import { AdministrationItemService, filterHiddenAdministrationItem } from '../../AdministrationItem/AdministrationItemService'; import { filterConfigurationWizard } from '../../AdministrationItem/filterConfigurationWizard'; import type { IAdministrationItem } from '../../AdministrationItem/IAdministrationItem'; import { orderAdministrationItems } from '../../AdministrationItem/orderAdministrationItems'; @@ -20,8 +20,11 @@ import { AdministrationScreenService } from '../AdministrationScreenService'; @injectable() export class ConfigurationWizardService { get steps(): IAdministrationItem[] { - return this.administrationItemService.items - .filter(filterConfigurationWizard(true)) + return this.administrationItemService.getUniqueItems(true) + .filter(item => + filterConfigurationWizard(true)(item) + && filterHiddenAdministrationItem(true)(item) + ) .sort(orderAdministrationItems(true)); } @@ -163,7 +166,7 @@ export class ConfigurationWizardService { } private getStep(name: string) { - return this.administrationItemService.items + return this.administrationItemService.getUniqueItems(true) .find(step => filterConfigurationWizard(true)(step) && step.name === name); } diff --git a/webapp/packages/core-authentication/src/AuthProvidersResource.ts b/webapp/packages/core-authentication/src/AuthProvidersResource.ts index a44ee0e1a4..a5184606c7 100644 --- a/webapp/packages/core-authentication/src/AuthProvidersResource.ts +++ b/webapp/packages/core-authentication/src/AuthProvidersResource.ts @@ -7,7 +7,7 @@ */ import { injectable } from '@cloudbeaver/core-di'; -import { PermissionsResource } from '@cloudbeaver/core-root'; +import { PermissionsResource, ServerConfigResource } from '@cloudbeaver/core-root'; import { GraphQLService, CachedDataResource, @@ -20,13 +20,22 @@ export type AuthProvider = Omit; export class AuthProvidersResource extends CachedDataResource { constructor( private graphQLService: GraphQLService, - private permissionsResource: PermissionsResource + private permissionsResource: PermissionsResource, + private serverConfigResource: ServerConfigResource ) { super([]); this.permissionsResource.onDataUpdate.addHandler(() => this.markOutdated()); } + getEnabledProviders(): string[] { + return this.serverConfigResource.data?.enabledAuthProviders ?? []; + } + + isEnabled(id: string): boolean { + return this.serverConfigResource.data?.enabledAuthProviders.includes(id) ?? false; + } + protected async loader(): Promise { const { providers } = await this.graphQLService.sdk.getAuthProviders(); return providers;