mirror of
https://github.com/ceph/ceph
synced 2026-08-01 22:45:39 +00:00
Merge pull request #70544 from rhcs-dashboard/switcher
mgr/dashboard: rgw gateway switcher read-only for resource page Reviewed-by: Afreen Misbah <afreen@ibm.com>
This commit is contained in:
commit
ff681c5884
@ -1,32 +1,70 @@
|
||||
<ng-container
|
||||
*ngIf="{
|
||||
@if (
|
||||
{
|
||||
ftMap: featureToggleMap$ | async,
|
||||
daemons: rgwDaemonService.daemons$ | async,
|
||||
selectedDaemon: rgwDaemonService.selectedDaemon$ | async
|
||||
} as data"
|
||||
>
|
||||
<ng-container
|
||||
*ngIf="
|
||||
data.ftMap && data.ftMap.rgw && permissions.rgw.read && isRgwRoute && data.daemons.length > 1
|
||||
"
|
||||
>
|
||||
<div class="cd-context-bar pt-3 pb-3">
|
||||
};
|
||||
as data
|
||||
) {
|
||||
@if (
|
||||
data.ftMap && data.ftMap.rgw && permissions.rgw.read && isRgwRoute && data.daemons.length > 1
|
||||
) {
|
||||
<div
|
||||
class="cd-context-bar cds-pt-5 cds-pb-5"
|
||||
[class.cds-pl-5]="isRgwResourcePage"
|
||||
>
|
||||
<span
|
||||
class="me-1"
|
||||
class="cds-mr-2"
|
||||
i18n
|
||||
>Object gateway:</span
|
||||
>
|
||||
<div
|
||||
ngbDropdown
|
||||
placement="bottom-left"
|
||||
class="d-inline-block ms-2"
|
||||
>
|
||||
|
||||
@if (!isRgwResourcePage) {
|
||||
<div
|
||||
ngbDropdown
|
||||
placement="bottom-left"
|
||||
class="cds-ml-3"
|
||||
style="display: inline-block"
|
||||
>
|
||||
<button
|
||||
ngbDropdownToggle
|
||||
class="btn btn-outline-info ctx-bar-selected-rgw-daemon"
|
||||
i18n-title
|
||||
title="Object gateway"
|
||||
type="button"
|
||||
>
|
||||
{{ data.selectedDaemon.id }}
|
||||
<cds-tag
|
||||
type="blue"
|
||||
size="sm"
|
||||
>{{ data.selectedDaemon.zonegroup_name }}</cds-tag
|
||||
>
|
||||
</button>
|
||||
<div ngbDropdownMenu>
|
||||
@for (daemon of data.daemons; track daemon.id) {
|
||||
<button
|
||||
ngbDropdownItem
|
||||
class="ctx-bar-available-rgw-daemon"
|
||||
(click)="onDaemonSelection(daemon)"
|
||||
type="button"
|
||||
>
|
||||
{{ daemon.id }}
|
||||
<cds-tag
|
||||
type="blue"
|
||||
size="sm"
|
||||
>{{ daemon.zonegroup_name }}</cds-tag
|
||||
>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<button
|
||||
ngbDropdownToggle
|
||||
class="btn btn-outline-info ctx-bar-selected-rgw-daemon"
|
||||
i18n-title
|
||||
title="Object gateway"
|
||||
type="button"
|
||||
disabled
|
||||
>
|
||||
{{ data.selectedDaemon.id }}
|
||||
<cds-tag
|
||||
@ -35,24 +73,7 @@
|
||||
>{{ data.selectedDaemon.zonegroup_name }}</cds-tag
|
||||
>
|
||||
</button>
|
||||
<div ngbDropdownMenu>
|
||||
<ng-container *ngFor="let daemon of data.daemons">
|
||||
<button
|
||||
ngbDropdownItem
|
||||
class="ctx-bar-available-rgw-daemon"
|
||||
(click)="onDaemonSelection(daemon)"
|
||||
type="button"
|
||||
>
|
||||
{{ daemon.id }}
|
||||
<cds-tag
|
||||
type="blue"
|
||||
size="sm"
|
||||
>{{ daemon.zonegroup_name }}</cds-tag
|
||||
>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,4 +100,36 @@ describe('ContextComponent', () => {
|
||||
expect(selectedDaemon.textContent).toEqual(' daemon3 zonegroup3');
|
||||
component.ngOnDestroy();
|
||||
}));
|
||||
|
||||
it('should show a read-only selected daemon on RGW resource page', fakeAsync(() => {
|
||||
component.isRgwRoute = true;
|
||||
component.isRgwResourcePage = true;
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
const req = httpTesting.expectOne('api/rgw/daemon');
|
||||
req.flush(daemonList);
|
||||
fixture.detectChanges();
|
||||
|
||||
const selectedDaemon = fixture.debugElement.nativeElement.querySelector(
|
||||
'.ctx-bar-selected-rgw-daemon'
|
||||
);
|
||||
const availableDaemons = fixture.debugElement.nativeElement.querySelectorAll(
|
||||
'.ctx-bar-available-rgw-daemon'
|
||||
);
|
||||
|
||||
expect(selectedDaemon.disabled).toBe(true);
|
||||
expect(availableDaemons.length).toEqual(0);
|
||||
component.ngOnDestroy();
|
||||
}));
|
||||
|
||||
it('should detect a RGW resource page from a hash route on reload', () => {
|
||||
expect(component['getRoutePath']('http://localhost/#/rgw/accounts/test-account/overview')).toBe(
|
||||
'/rgw/accounts/test-account/overview'
|
||||
);
|
||||
expect(
|
||||
component['isRgwAccountsResourcePage'](
|
||||
component['getRoutePath']('http://localhost/#/rgw/accounts/test-account/overview')
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -27,9 +27,11 @@ export class ContextComponent implements OnInit, OnDestroy {
|
||||
private rgwUserUrlPrefix = '/rgw/user';
|
||||
private rgwBuckerUrlPrefix = '/rgw/bucket';
|
||||
private rgwAccountsUrlPrefix = '/rgw/accounts';
|
||||
private rgwAccountsResourcePagePattern = /^\/rgw\/accounts\/[^/]+\/(overview|roles)(?:$|[?#])/;
|
||||
private rgwMultisiteSyncPolicyPrefix = '/rgw/multisite/sync-policy';
|
||||
permissions: Permissions;
|
||||
featureToggleMap$: FeatureTogglesMap$;
|
||||
isRgwResourcePage = this.isRgwAccountsResourcePage(this.getRoutePath(document.location.href));
|
||||
isRgwRoute =
|
||||
document.location.href.includes(this.rgwUserUrlPrefix) ||
|
||||
document.location.href.includes(this.rgwBuckerUrlPrefix) ||
|
||||
@ -51,15 +53,16 @@ export class ContextComponent implements OnInit, OnDestroy {
|
||||
this.subs.add(
|
||||
this.router.events
|
||||
.pipe(filter((event: Event) => event instanceof NavigationEnd))
|
||||
.subscribe(
|
||||
() =>
|
||||
(this.isRgwRoute = [
|
||||
this.rgwBuckerUrlPrefix,
|
||||
this.rgwUserUrlPrefix,
|
||||
this.rgwAccountsUrlPrefix,
|
||||
this.rgwMultisiteSyncPolicyPrefix
|
||||
].some((urlPrefix) => this.router.url.startsWith(urlPrefix)))
|
||||
)
|
||||
.subscribe(() => {
|
||||
const currentRoute = this.getRoutePath(this.router.url);
|
||||
this.isRgwRoute = [
|
||||
this.rgwBuckerUrlPrefix,
|
||||
this.rgwUserUrlPrefix,
|
||||
this.rgwAccountsUrlPrefix,
|
||||
this.rgwMultisiteSyncPolicyPrefix
|
||||
].some((urlPrefix) => this.router.url.startsWith(urlPrefix));
|
||||
this.isRgwResourcePage = this.isRgwAccountsResourcePage(currentRoute);
|
||||
})
|
||||
);
|
||||
// Set daemon list polling only when in RGW route:
|
||||
this.subs.add(
|
||||
@ -84,4 +87,13 @@ export class ContextComponent implements OnInit, OnDestroy {
|
||||
this.router.navigate([currentUrl]);
|
||||
});
|
||||
}
|
||||
|
||||
private isRgwAccountsResourcePage(url: string): boolean {
|
||||
return this.rgwAccountsResourcePagePattern.test(url);
|
||||
}
|
||||
|
||||
private getRoutePath(url: string): string {
|
||||
const hashIndex = url.indexOf('#');
|
||||
return hashIndex === -1 ? url : url.slice(hashIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,10 @@
|
||||
padding-left: layout.$spacing-06;
|
||||
}
|
||||
|
||||
.cds-pl-5 {
|
||||
padding-left: layout.$spacing-05;
|
||||
}
|
||||
|
||||
.cds-pl-4 {
|
||||
padding-left: layout.$spacing-04;
|
||||
}
|
||||
@ -33,6 +37,10 @@
|
||||
padding-top: layout.$spacing-05;
|
||||
}
|
||||
|
||||
.cds-pb-5 {
|
||||
padding-bottom: layout.$spacing-05;
|
||||
}
|
||||
|
||||
.cds-pr-4 {
|
||||
padding-right: layout.$spacing-04;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user