Skip to content

Commit

Permalink
Merged in task/main-cris/DSC-2059 (pull request DSpace#2589)
Browse files Browse the repository at this point in the history
[DSC-2059] remove async functions calls from templates of cris item pages and context menus

Approved-by: Giuseppe Digilio
  • Loading branch information
FrancescoMolinaro authored and atarix83 committed Nov 29, 2024
2 parents 4cb832b + 113a5f8 commit 80b54e3
Show file tree
Hide file tree
Showing 47 changed files with 199 additions and 161 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<button *ngIf="(windowService.isXsOrSm() | async) && showNav" class="navbar-toggler pl-2 float-right" type="button" (click)="toggleNavbar()"
<button *ngIf="(isXsOrSm$ | async) && showNav" class="navbar-toggler pl-2 float-right" type="button" (click)="toggleNavbar()"
aria-controls="collapsingNav" aria-expanded="false" [attr.aria-label]="'nav.toggle' | translate">
<span class="navbar-toggler-icon fas fa-bars fa-fw" aria-hidden="true"></span>
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import {
TranslateLoader,
TranslateModule,
} from '@ngx-translate/core';
import { BehaviorSubject } from 'rxjs';
import {
BehaviorSubject,
of,
} from 'rxjs';

import { CrisLayoutTab } from '../../../../core/layout/models/tab.model';
import { Item } from '../../../../core/shared/item.model';
Expand Down Expand Up @@ -101,6 +104,7 @@ describe('CrisLayoutNavbarComponent', () => {
component.tabs = loaderMultilevelTabs;
component.item = mockItem;
component.activeTab$ = new BehaviorSubject<CrisLayoutTab>(loaderMultilevelTabs[0]);
component.isXsOrSm$ = of(true);
component.ngOnInit();
fixture.detectChanges();
});
Expand All @@ -114,6 +118,7 @@ describe('CrisLayoutNavbarComponent', () => {

beforeEach(() => {
windowServiceStub.setWidth(400);
component.ngOnInit();
fixture.detectChanges();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Output,
} from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { Observable } from 'rxjs';

import { CrisLayoutTab } from '../../../../core/layout/models/tab.model';
import { Item } from '../../../../core/shared/item.model';
Expand Down Expand Up @@ -59,8 +60,11 @@ export class CrisLayoutNavbarComponent extends CrisLayoutTabsComponent implement

windowService = inject(HostWindowService);

isXsOrSm$: Observable<boolean>;

ngOnInit(): void {
this.init();
this.isXsOrSm$ = this.windowService.isXsOrSm();
}

emitSelected(selectedTab) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="wrapper d-flex align-items-stretch" [ngClass]="{'wrapper-close': (isSideBarHidden() | async) !== true,
'container': (hasSidebar() | async) }">
<nav id="sidebar" *ngIf="(hasSidebar() | async) && (isSideBarHidden() | async) !== true && showNav" [ngClass]="{'active': (isSideBarHidden() | async) !== true}">
<div class="wrapper d-flex align-items-stretch" [ngClass]="{'wrapper-close': (isSideBarHidden$ | async) !== true,
'container': (hasSidebar$ | async) }">
<nav id="sidebar" *ngIf="(hasSidebar$ | async) && (isSideBarHidden$ | async) !== true && showNav" [ngClass]="{'active': (isSideBarHidden$ | async) !== true}">
<div>
<ul class="list-unstyled components mb-5">
<ng-container *ngIf="!!(activeTab$ |async)">
Expand All @@ -11,17 +11,17 @@
</div>
</nav>
<div id="content" class="position-relative w-100 pr-0 pt-3 pb-3" [ngClass]="{
'p-0': (hasSidebar() | async) !== true,
'pl-3': (isSideBarHidden() | async) !== true,
'pl-0': (isSideBarHidden() | async) === true
'p-0': (hasSidebar$ | async) !== true,
'pl-3': (isSideBarHidden$ | async) !== true,
'pl-0': (isSideBarHidden$ | async) === true
}">

<div *ngIf="(hasSidebar() | async)">
<div *ngIf="(hasSidebar$ | async)">
<button type="button" class="btn btn-link menu-toggle" (click)="toggleSidebar()">
<i class="fa fa-chevron-circle-{{(isSideBarHidden() | async) ? 'right' : 'left'}} fa-2x" aria-hidden="true"></i>
<i class="fa fa-chevron-circle-{{(isSideBarHidden$ | async) ? 'right' : 'left'}} fa-2x" aria-hidden="true"></i>
</button>
</div>
<div class="d-flex flex-column" [ngClass]="{'pl-4': (hasSidebar() | async)}">
<div class="d-flex flex-column" [ngClass]="{'pl-4': (hasSidebar$ | async)}">
<ng-content></ng-content>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ export class CrisLayoutSidebarComponent extends CrisLayoutTabsComponent implemen
/**
* A boolean representing if to render or not the sidebar menu
*/
private hasSidebar$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
hasSidebar$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

/**
* This parameter define the status of sidebar (hide/show)
*/
private sidebarStatus$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

isSideBarHidden$: Observable<boolean>;

ngOnInit(): void {
this.init();
Expand All @@ -79,6 +80,7 @@ export class CrisLayoutSidebarComponent extends CrisLayoutTabsComponent implemen

// Init the sidebar status
this.sidebarStatus$.next(this.hasSidebar$.value);
this.isSideBarHidden$ = this.isSideBarHidden();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div id="cris-layout-loader">
<div *ngIf="(windowService.isXsOrSm() | async) !== true" class="vertical-layout">
<div *ngIf="(isXsOrSm$ | async) !== true" class="vertical-layout">
<ds-cris-layout-sidebar (selectedTabChange)="selectedTabChanged($event)" [showNav]="tabs.length > 1" [tabs]="tabs" [item]="item">
<div *ngIf="showContextMenu" class="container text-right mb-3" [class.px-0]="tabs?.length > 1">
<ds-context-menu [contextMenuObject]="item" [contextMenuObjectType]="'ITEM'"></ds-context-menu>
Expand All @@ -8,7 +8,7 @@
</ds-cris-layout-sidebar>
</div>

<div *ngIf="(windowService.isXsOrSm() | async)" class="horizontal-layout">
<div *ngIf="(isXsOrSm$ | async)" class="horizontal-layout">
<ds-cris-layout-navbar [showNav]="(tabs.length - leadingTabs.length) > 1" (selectedTabChange)="selectedTabChanged($event)"
[tabs]="tabs" [item]="item"></ds-cris-layout-navbar>
<div class="container pt-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
Component,
Input,
} from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import {
BehaviorSubject,
Observable,
} from 'rxjs';

import { CrisLayoutTab } from '../../../core/layout/models/tab.model';
import { Item } from '../../../core/shared/item.model';
Expand Down Expand Up @@ -54,8 +57,10 @@ export class CrisLayoutVerticalComponent {


selectedTab$: BehaviorSubject<CrisLayoutTab> = new BehaviorSubject<CrisLayoutTab>(null);
isXsOrSm$: Observable<boolean>;

constructor(public windowService: HostWindowService) {
this.isXsOrSm$ = this.windowService.isXsOrSm();
}

selectedTabChanged(tab: CrisLayoutTab) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<ng-container *ngFor="let metric of metricRow.metrics">
<ng-container *ngIf="metric">
<ds-metric-loader [metric]="metric"
[class.d-none]="(isHidden(metric.id) | async)"
[class.d-none]="isHidden(metric.id)"
(hide)="toggleVisibility(metric.id, $event)"></ds-metric-loader>
</ng-container>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import {
Component,
Input,
} from '@angular/core';
import {
BehaviorSubject,
Observable,
of,
} from 'rxjs';
import { BehaviorSubject } from 'rxjs';

import { CrisLayoutMetricRow } from '../../../../../../core/layout/models/tab.model';
import { MetricLoaderComponent } from '../../../../../../shared/metric/metric-loader/metric-loader.component';
Expand Down Expand Up @@ -46,11 +42,11 @@ export class MetricRowComponent {
this.isVisible$.next(newMap);
}

isHidden(metricId): Observable<boolean> {
isHidden(metricId): boolean {
if (this.isVisible$.value.has(metricId)) {
return of(this.isVisible$.value.get(metricId));
return this.isVisible$.value.get(metricId);
} else {
return of(false);
return false;
}
}
}
2 changes: 1 addition & 1 deletion src/app/item-page/alerts/item-alerts.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<span class="align-self-center">{{'item.alerts.withdrawn' | translate}}</span>
<div class="gap-2 d-flex">
<a *ngIf="(isAdministrator$ | async) !== true" routerLink="/home" class="btn btn-primary btn-sm">{{"404.link.home-page" | translate}}</a>
<a *ngIf="showReinstateButton$() | async" class="btn btn-primary btn-sm" (click)="openReinstateModal()">{{ 'item.alerts.reinstate-request' | translate}}</a>
<a *ngIf="showReinstateButton$ | async" class="btn btn-primary btn-sm" (click)="openReinstateModal()">{{ 'item.alerts.reinstate-request' | translate}}</a>
</div>
</div>
</ds-alert>
Expand Down
28 changes: 11 additions & 17 deletions src/app/item-page/alerts/item-alerts.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ describe('ItemAlertsComponent', () => {
beforeEach(waitForAsync(() => {
authorizationService = jasmine.createSpyObj('authorizationService', ['isAuthorized']);
dsoWithdrawnReinstateModalService = jasmine.createSpyObj('dsoWithdrawnReinstateModalService', ['openCreateWithdrawnReinstateModal']);
correctionTypeDataService = jasmine.createSpyObj('correctionTypeDataService', ['findByItem']);
correctionTypeDataService = jasmine.createSpyObj('correctionTypeDataService', {
findByItem: createSuccessfulRemoteDataObject$([]),
});
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), ItemAlertsComponent, NoopAnimationsModule],
providers: [
Expand Down Expand Up @@ -73,6 +75,7 @@ describe('ItemAlertsComponent', () => {
isDiscoverable: true,
});
component.item = item;
(correctionTypeDataService.findByItem).and.returnValue(createSuccessfulRemoteDataObject$([]));
fixture.detectChanges();
});

Expand All @@ -87,6 +90,7 @@ describe('ItemAlertsComponent', () => {
item = Object.assign(new Item(), {
isDiscoverable: false,
});
(correctionTypeDataService.findByItem).and.returnValue(createSuccessfulRemoteDataObject$([]));
component.item = item;
fixture.detectChanges();
});
Expand Down Expand Up @@ -146,23 +150,13 @@ describe('ItemAlertsComponent', () => {
fixture.detectChanges();
});

it('should return true when user is not an admin and there is at least one correction with topic REQUEST_REINSTATE', () => {
testScheduler.run(({ cold, expectObservable }) => {
const isAdminMarble = 'a';
const correctionMarble = 'b';
const expectedMarble = 'c';

const isAdminValues = { a: false };
const correctionValues = { b: correctionRD };
const expectedValues = { c: true };

const isAdmin$ = cold(isAdminMarble, isAdminValues);
const correction$ = cold(correctionMarble, correctionValues);

(authorizationService.isAuthorized).and.returnValue(isAdmin$);
(correctionTypeDataService.findByItem).and.returnValue(correction$);
it('should return true when user is not an admin and there is at least one correction with topic REQUEST_REINSTATE', (done) => {

expectObservable(component.showReinstateButton$()).toBe(expectedMarble, expectedValues);
(authorizationService.isAuthorized).and.returnValue(of(false));
component.ngOnInit();
component.showReinstateButton$.subscribe(value => {
expect(value).toBeTruthy();
done();
});
});

Expand Down
4 changes: 3 additions & 1 deletion src/app/item-page/alerts/item-alerts.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export class ItemAlertsComponent implements OnInit {
public AlertTypeEnum = AlertType;

isAdministrator$: Observable<boolean>;
showReinstateButton$: Observable<boolean>;

constructor(
private authService: AuthorizationDataService,
Expand All @@ -69,14 +70,15 @@ export class ItemAlertsComponent implements OnInit {

ngOnInit() {
this.isAdministrator$ = this.authService.isAuthorized(FeatureID.AdministratorOf);
this.showReinstateButton$ = this.showReinstateButton();
}

/**
* Determines whether to show the reinstate button.
* The button is shown if the user is not an admin and the item has a reinstate request.
* @returns An Observable that emits a boolean value indicating whether to show the reinstate button.
*/
showReinstateButton$(): Observable<boolean> {
showReinstateButton(): Observable<boolean> {
const correction$ = this.correctionTypeDataService.findByItem(this.item.uuid, true).pipe(
getFirstCompletedRemoteData(),
map((correctionTypeRD: RemoteData<PaginatedList<CorrectionType>>) => correctionTypeRD.hasSucceeded ? correctionTypeRD.payload.page : []),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="container">
<ds-alert [type]="'alert-info'" [content]="'item.edit.authorizations.heading'"></ds-alert>
<ds-resource-policies [resourceType]="'item'" [resourceName]="(getItemName() | async)"
[resourceUUID]="(getItemUUID() | async)">
[resourceUUID]="(itemUuid$ | async)">
</ds-resource-policies>
<ng-container *ngFor="let bundle of (bundles$ | async); trackById">
<ds-resource-policies [resourceType]="'bundle'" [resourceUUID]="bundle.id" [resourceName]="bundle.name">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ export class ItemAuthorizationsComponent implements OnInit, OnDestroy {
*/
bitstreamSize = 4;

itemUuid$: Observable<string>;

/**
* The size of the loaded bitstremas at a certain moment
* @private
Expand All @@ -152,6 +154,7 @@ export class ItemAuthorizationsComponent implements OnInit, OnDestroy {
*/
ngOnInit(): void {
this.getBundlesPerItem();
this.itemUuid$ = this.getItemUUID();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
*/
entityType$: BehaviorSubject<ItemType> = new BehaviorSubject(undefined);

get isSaving$(): BehaviorSubject<boolean> {
return this.editItemRelationshipsService.isSaving$;
}
isSaving$: BehaviorSubject<boolean>;

readonly AlertType = AlertType;

Expand All @@ -109,6 +107,7 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
protected editItemRelationshipsService: EditItemRelationshipsService,
) {
super(itemService, objectUpdatesService, router, notificationsService, translateService, route);
this.isSaving$ = this.editItemRelationshipsService.isSaving$;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<ds-metadata-field-wrapper [label]="label | translate">
<div class="collections">
<a *ngFor="let collection of (this.collections$ | async); let last=last;" [routerLink]="['/collections', collection.id]">
<a *ngFor="let collection of (collections$ | async); let last=last;" [routerLink]="['/collections', collection.id]">
<span>{{ dsoNameService.getName(collection) }}</span><span *ngIf="!last" [innerHTML]="separator"></span>
</a>
</div>
Expand Down
Loading

0 comments on commit 80b54e3

Please sign in to comment.