Skip to content

Commit

Permalink
Merge branch 'dspace-cris-2023_02_x' into task/dspace-cris-2023.02.06…
Browse files Browse the repository at this point in the history
…/DSC-2036

# Conflicts:
#	package.json
  • Loading branch information
atarix83 committed Nov 22, 2024
2 parents 57a52ad + 001de85 commit 4f4fe7b
Show file tree
Hide file tree
Showing 62 changed files with 1,219 additions and 60 deletions.
4 changes: 0 additions & 4 deletions config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -400,10 +400,6 @@ themes:
attributes:
rel: manifest
href: assets/dspace/images/favicons/manifest.webmanifest
- tagName: link
attributes:
rel: stylesheet
href: "https://fonts.googleapis.com/icon?family=Material+Icons"

# The default bundles that should always be displayed as suggestions when you upload a new bundle
bundle:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dspace-angular",
"version": "2023.02.06.01",
"version": "2023.02.07-SNAPSHOT",
"scripts": {
"ng": "ng",
"config:watch": "nodemon",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ <h4 class="mt-4 mb-4">{{ object.name }} (<em>{{object.type}}</em>)</h4>

</ng-container>

<h4 class="mt-4 mb-4" *ngIf="(auditsRD$ | async).statusCode === 404">{{'audit.object.overview.disabled.message' | translate}}</h4>
<h4 class="mt-4 mb-4" *ngIf="(auditsRD$ | async)?.statusCode === 404">{{'audit.object.overview.disabled.message' | translate}}</h4>

</ng-container>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core';

import { combineLatest, Observable } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
import { combineLatest, Observable, of, switchMap } from 'rxjs';
import { map, mergeMap, take } from 'rxjs/operators';

import { RemoteData } from '../../core/data/remote-data';
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
Expand All @@ -18,6 +18,10 @@ import { AuthService } from '../../core/auth/auth.service';
import { PaginatedList } from '../../core/data/paginated-list.model';
import { PaginationService } from '../../core/pagination/pagination.service';
import { redirectOn4xx } from '../../core/shared/authorized.operators';
import { CollectionDataService } from '../../core/data/collection-data.service';
import { Collection } from '../../core/shared/collection.model';
import { Item } from '../../core/shared/item.model';
import { COLLECTION_PAGE_LINKS_TO_FOLLOW } from '../../collection-page/collection-page.resolver';

/**
* Component displaying a list of all audit about a object in a paginated table
Expand All @@ -31,7 +35,7 @@ export class ObjectAuditOverviewComponent implements OnInit {
/**
* The object extracted from the route.
*/
object;
object: Item;

/**
* List of all audits
Expand Down Expand Up @@ -62,14 +66,17 @@ export class ObjectAuditOverviewComponent implements OnInit {
*/
dateFormat = 'yyyy-MM-dd HH:mm:ss';

owningCollection$: Observable<Collection>;

constructor(protected authService: AuthService,
protected route: ActivatedRoute,
protected router: Router,
protected auditService: AuditDataService,
protected itemService: ItemDataService,
protected authorizationService: AuthorizationDataService,
protected paginationService: PaginationService) {
}
protected paginationService: PaginationService,
protected collectionDataService: CollectionDataService
) {}

ngOnInit(): void {
this.route.paramMap.pipe(
Expand All @@ -78,6 +85,15 @@ export class ObjectAuditOverviewComponent implements OnInit {
redirectOn4xx(this.router, this.authService)
).subscribe((rd) => {
this.object = rd.payload;
this.owningCollection$ = this.collectionDataService.findOwningCollectionFor(
this.object,
true,
false,
...COLLECTION_PAGE_LINKS_TO_FOLLOW
).pipe(
getFirstCompletedRemoteData(),
map(data => data?.payload)
);
this.setAudits();
});
}
Expand All @@ -88,17 +104,35 @@ export class ObjectAuditOverviewComponent implements OnInit {
setAudits() {
const config$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config, this.pageConfig);
const isAdmin$ = this.isCurrentUserAdmin();
this.auditsRD$ = combineLatest([isAdmin$, config$]).pipe(
mergeMap(([isAdmin, config]) => {
const parentCommunity$ = this.owningCollection$.pipe(
switchMap(collection => collection.parentCommunity),
getFirstCompletedRemoteData(),
map(data => data?.payload)
);


this.auditsRD$ = combineLatest([isAdmin$, config$, this.owningCollection$, parentCommunity$]).pipe(
mergeMap(([isAdmin, config, owningCollection, parentCommunity]) => {
if (isAdmin) {
return this.auditService.findByObject(this.object.id, config);
return this.auditService.findByObject(this.object.id, config, owningCollection.id, parentCommunity.id);
}

return of(null);
})
);
}

isCurrentUserAdmin(): Observable<boolean> {
return this.authorizationService.isAuthorized(FeatureID.AdministratorOf, undefined, undefined);
return combineLatest([
this.authorizationService.isAuthorized(FeatureID.IsCollectionAdmin),
this.authorizationService.isAuthorized(FeatureID.IsCommunityAdmin),
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
]).pipe(
map(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin]) => {
return isCollectionAdmin || isCommunityAdmin || isSiteAdmin;
}),
take(1),
);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/app/breadcrumbs/breadcrumbs.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</ng-template>

<ng-template #activeBreadcrumb let-text="text">
<li class="breadcrumb-item active" aria-current="page"><div class="breadcrumb-item-limiter"><div class="text-truncate">{{text | translate}}</div></div></li>
<li class="breadcrumb-item active" aria-current="page"><div class="breadcrumb-item-limiter"><span class="text-truncate" [innerHTML]="text | translate"></span></div></li>
</ng-template>
</ng-container>

16 changes: 14 additions & 2 deletions src/app/core/audit/audit-data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { SearchDataImpl } from '../data/base/search-data';
import { DeleteDataImpl } from '../data/base/delete-data';
import { FindAllData, FindAllDataImpl } from '../data/base/find-all-data';
import { DSONameService } from '../breadcrumbs/dso-name.service';
import { hasValue } from '../../shared/empty.util';

export const AUDIT_PERSON_NOT_AVAILABLE = 'n/a';

Expand Down Expand Up @@ -60,12 +61,23 @@ export class AuditDataService extends IdentifiableDataService<Audit>{
*
* @param objectId The objectId id
* @param options The [[FindListOptions]] object
* @param collUuid The Uuid of the collection
* @param commUuid The Uuid of the community
* @return Observable<RemoteData<PaginatedList<Audit>>>
*/
findByObject(objectId: string, options: FindListOptions = {}): Observable<RemoteData<PaginatedList<Audit>>> {
findByObject(objectId: string, options: FindListOptions = {}, collUuid?: string, commUuid?: string): Observable<RemoteData<PaginatedList<Audit>>> {
const searchMethod = AUDIT_FIND_BY_OBJECT_SEARCH_METHOD;
const searchParams = [new RequestParam('object', objectId)];

if (hasValue(commUuid)) {
searchParams.push(new RequestParam('commUuid', commUuid));
}

if (hasValue(collUuid)) {
searchParams.push(new RequestParam('collUuid', collUuid));
}
const optionsWithObject = Object.assign(new FindListOptions(), options, {
searchParams: [new RequestParam('object', objectId)]
searchParams
});
return this.searchData.searchBy(searchMethod, optionsWithObject, true, true, followLink('eperson'));
}
Expand Down
7 changes: 5 additions & 2 deletions src/app/core/data/collection-data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,12 @@ export class CollectionDataService extends ComColDataService<Collection> {
/**
* Returns {@link RemoteData} of {@link Collection} that is the owning collection of the given item
* @param item Item we want the owning collection of
* @param useCachedVersionIfAvailable
* @param reRequestOnStale
* @param linksToFollow
*/
findOwningCollectionFor(item: Item): Observable<RemoteData<Collection>> {
return this.findByHref(item._links.owningCollection.href);
findOwningCollectionFor(item: Item, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<Collection>[]): Observable<RemoteData<Collection>> {
return this.findByHref(item._links.owningCollection.href, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export abstract class SubmissionParentBreadcrumbResolver implements Resolve<Brea
*/
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<BreadcrumbConfig<SubmissionObject>> {
return this.dataService.findById(route.params.id,
true,
false,
false,
...SUBMISSION_LINKS_TO_FOLLOW,
).pipe(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div [class]="field.styleValue">
<span [innerHTML]="processHtml(metadataValue.value)" class="text-value"></span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';

import { TranslateLoader, TranslateModule } from '@ngx-translate/core';

import { HtmlComponent } from './html.component';
import { Item } from '../../../../../../../core/shared/item.model';
import { TranslateLoaderMock } from '../../../../../../../shared/mocks/translate-loader.mock';
import { DsDatePipe } from '../../../../../../pipes/ds-date.pipe';
import { LayoutField } from '../../../../../../../core/layout/models/box.model';
import { MetadataValue } from '../../../../../../../core/shared/metadata.models';

describe('HtmlComponent', () => {
let component: HtmlComponent;
let fixture: ComponentFixture<HtmlComponent>;

const metadataValue = Object.assign(new MetadataValue(), {
'value': 'test item title',
'language': null,
'authority': null,
'confidence': -1,
'place': 0
});

const testItem = Object.assign(new Item(),
{
type: 'item',
metadata: {
'dc.title': [metadataValue]
},
uuid: 'test-item-uuid',
}
);


const mockField: LayoutField = {
'metadata': 'dc.title',
'label': 'Title',
'rendering': 'html',
'fieldType': 'METADATA',
'style': null,
'styleLabel': 'test-style-label',
'styleValue': 'test-style-value',
'labelAsHeading': false,
'valuesInline': true
};

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
}), BrowserAnimationsModule],
providers: [
{ provide: 'fieldProvider', useValue: mockField },
{ provide: 'itemProvider', useValue: testItem },
{ provide: 'metadataValueProvider', useValue: metadataValue },
{ provide: 'renderingSubTypeProvider', useValue: '' },
{ provide: 'tabNameProvider', useValue: '' },
],
declarations: [HtmlComponent, DsDatePipe]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(HtmlComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('check metadata rendering', (done) => {
const spanValueFound = fixture.debugElement.queryAll(By.css('span.text-value'));
expect(spanValueFound.length).toBe(1);
expect(spanValueFound[0].nativeElement.textContent).toContain(metadataValue.value);
done();
});

it('check value style', (done) => {
const spanValueFound = fixture.debugElement.queryAll(By.css('.test-style-value'));
expect(spanValueFound.length).toBe(1);
done();
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Component } from '@angular/core';

import { FieldRenderingType, MetadataBoxFieldRendering } from '../metadata-box.decorator';
import { RenderingTypeValueModelComponent } from '../rendering-type-value.model';

/**
* This component renders the text metadata fields
*/
@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'span[ds-html]',
templateUrl: './html.component.html',
styleUrls: ['./html.component.scss']
})
@MetadataBoxFieldRendering(FieldRenderingType.HTML)
export class HtmlComponent extends RenderingTypeValueModelComponent {

/**
* If the metadata value does not contain HTML tags then replace newline character with <br>
* @param text
*/
processHtml(text: string): string {
const htmlTagRegex = /<.*?>/;
return htmlTagRegex.test(text) ? text.replace(/\n/, '<br>') : text;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div [class]="field.styleValue">
<ds-truncatable [id]="truncatableId">
<ds-truncatable-part [id]="truncatableId" [minLines]="8">
<span [innerHTML]="processHtml(metadataValue.value)" class="text-value"></span>
</ds-truncatable-part>
</ds-truncatable>
</div>
Loading

0 comments on commit 4f4fe7b

Please sign in to comment.