Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(resource): display incoming links (DSP-1846) #507

Merged
merged 8 commits into from Aug 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/app/workspace/resource/incoming.service.ts
Expand Up @@ -176,9 +176,10 @@ FILTER NOT EXISTS {
*
* @param {string} resourceIri the Iri of the resource whose incoming links should be returned.
* @param {number} offset the offset to be used for paging. 0 is the default and is used to get the first page of results.
* @param {boolean} countQuery if set to true, the request returns only the CountQueryResponse; default value is `false`
* @returns {Observable<any>}
*/
getIncomingLinks(resourceIri: string, offset: number): Observable<ReadResourceSequence | ApiResponseError> {
getIncomingLinks(resourceIri: string, offset: number, countQuery: boolean = false): Observable<ReadResourceSequence | CountQueryResponse | ApiResponseError> {
const sparqlQueryStr = `
PREFIX knora-api: <http://api.knora.org/ontology/knora-api/simple/v2#>

Expand Down Expand Up @@ -211,7 +212,7 @@ FILTER NOT EXISTS {
} OFFSET ${offset}
`;

return this._dspApiConnection.v2.search.doExtendedSearch(sparqlQueryStr);
return countQuery ? this._dspApiConnection.v2.search.doExtendedSearchCountQuery(sparqlQueryStr) : this._dspApiConnection.v2.search.doExtendedSearch(sparqlQueryStr);
}
}

30 changes: 30 additions & 0 deletions src/app/workspace/resource/properties/properties.component.html
Expand Up @@ -146,6 +146,36 @@ <h3 class="label mat-title">
</div>
</div>
</div>

<div *ngIf="incomingLinkResources.length > 0">
<div class="property border-top">
<div class="property-label">
<!-- label of the incoming links -->
<h3 class="label mat-subheading-1">
has incoming link
</h3>
</div>
<div class="property-value">
<div *ngIf="loading">
Vijeinath marked this conversation as resolved.
Show resolved Hide resolved
...Loading
</div>
<div *ngIf="!loading">
<!-- the value(s) of the incoming links -->
<div *ngFor="let inRes of incomingLinkResources">
<a [routerLink]="['/resource', inRes.id]" target="_blank">{{inRes.label}}</a>
</div>
<mat-paginator
[length]=numberOffAllIncomingLinkRes
[pageSize]="25"
[hidePageSize]="true"
[pageIndex]="pageEvent.pageIndex"
(page)="goToPage($event)">
</mat-paginator>
</div>
</div>
</div>
</div>

</div>
<ng-template #noProperties>The resource {{resource?.res.resourceClassLabel}} has no defined
properties.</ng-template>
Expand Down
Expand Up @@ -166,6 +166,15 @@
color: rgba(0, 0, 0, 0.54);
}

:host::ng-deep .mat-paginator-container {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ng-deep is deprecated. It would be a better way to define/overwrite component's style in one of the global stylesheets in the assets folder. But for the moment you can keep it as it is.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I keep this for the moment. Is there an alternative?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no alternative for ng-deep and it doesn't appear as if there ever will be an alternative so you'll have to overwrite the component's style either in one of the global style sheets (recommended) or directly in the stylesheet of the component

justify-content: start;
padding: 0;
}

:host::ng-deep .mat-paginator-range-label {
margin: 0;
}

@media screen and (max-width: 768px) {
.properties,
.incoming {
Expand Down
24 changes: 24 additions & 0 deletions src/app/workspace/resource/properties/properties.component.spec.ts
Expand Up @@ -8,6 +8,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import {
ApiResponseData,
ApiResponseError,
Constants,
IHasPropertyWithPropertyDefinition,
Expand All @@ -18,6 +19,7 @@ import {
ProjectsEndpointAdmin,
ReadLinkValue,
ReadResource,
ReadResourceSequence,
ReadValue,
ResourcePropertyDefinition,
SystemPropertyDefinition
Expand All @@ -37,6 +39,7 @@ import { of, Subscription } from 'rxjs';
import { TestConfig } from 'test.config';
import { DspResource } from '../dsp-resource';
import { PropertiesComponent } from './properties.component';
import { IncomingService } from '../incoming.service';

/**
* test host component to simulate parent component.
Expand Down Expand Up @@ -147,6 +150,8 @@ describe('PropertiesComponent', () => {

const userServiceSpy = jasmine.createSpyObj('UserService', ['getUser']);

const incomingServiceSpy = jasmine.createSpyObj('IncomingService', ['getIncomingLinks']);

TestBed.configureTestingModule({
imports: [
ClipboardModule,
Expand Down Expand Up @@ -174,6 +179,10 @@ describe('PropertiesComponent', () => {
provide: UserService,
useValue: userServiceSpy
},
{
provide: IncomingService,
useValue: incomingServiceSpy
},
]
})
.compileComponents();
Expand Down Expand Up @@ -224,13 +233,28 @@ describe('PropertiesComponent', () => {
}
);

const incomingLinksSpy = TestBed.inject(IncomingService);

(incomingLinksSpy as jasmine.SpyObj<IncomingService>).getIncomingLinks.and.callFake(
() => {
const resources = new ReadResource();
const incomingLinks = new ReadResourceSequence([resources], true);
return of(incomingLinks);
}
);

testHostFixture = TestBed.createComponent(TestPropertyParentComponent);
testHostComponent = testHostFixture.componentInstance;
testHostFixture.detectChanges();

expect(testHostComponent).toBeTruthy();
});

it('should get one incoming link', () => {

expect(testHostComponent.propertiesComponent.incomingLinkResources.length).toEqual(1);
});

it('should get the resource testding', () => {

expect(testHostComponent.parentResource).toBeTruthy();
Expand Down
55 changes: 52 additions & 3 deletions src/app/workspace/resource/properties/properties.component.ts
@@ -1,11 +1,10 @@
import { Component, EventEmitter, Inject, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import {
ApiResponseData,
ApiResponseError,
CardinalityUtil,
Constants,
Constants, CountQueryResponse,
DeleteResource,
DeleteResourceResponse,
DeleteValue,
Expand Down Expand Up @@ -41,6 +40,8 @@ import { ConfirmationWithComment, DialogComponent } from 'src/app/main/dialog/di
import { ErrorHandlerService } from 'src/app/main/error/error-handler.service';
import { DspResource } from '../dsp-resource';
import { RepresentationConstants } from '../representation/file-representation';
import { IncomingService } from '../incoming.service';
import { PageEvent } from '@angular/material/paginator';

@Component({
selector: 'app-properties',
Expand Down Expand Up @@ -110,6 +111,11 @@ export class PropertiesComponent implements OnInit, OnChanges, OnDestroy {
project: ReadProject;
user: ReadUser;

incomingLinkResources: ReadResource[] = [];
pageEvent: PageEvent;
numberOffAllIncomingLinkRes: number;
loading = false;

showAllProps = false; // show or hide empty properties

constructor(
Expand All @@ -119,10 +125,17 @@ export class PropertiesComponent implements OnInit, OnChanges, OnDestroy {
private _notification: NotificationService,
private _userService: UserService,
private _valueOperationEventService: ValueOperationEventService,
private _valueService: ValueService
private _valueService: ValueService,
private _incomingService: IncomingService
) { }

ngOnInit(): void {
// reset the page event
this.pageEvent = new PageEvent();
this.pageEvent.pageIndex = 0;

this._getIncomingLinks();

if (this.resource.res) {
// get user permissions
const allPermissions = PermissionUtil.allUserPermissions(
Expand Down Expand Up @@ -215,6 +228,15 @@ export class PropertiesComponent implements OnInit, OnChanges, OnDestroy {
// --> TODO: pop up project preview on hover
}

/**
* goes to the next page of the incoming link pagination
* @param page
*/
goToPage(page: PageEvent) {
this.pageEvent = page;
this._getIncomingLinks();
}

/**
* opens resource
* @param linkValue
Expand Down Expand Up @@ -436,6 +458,33 @@ export class PropertiesComponent implements OnInit, OnChanges, OnDestroy {
localStorage.setItem('showAllProps', JSON.stringify(this.showAllProps));
}

/**
* gets the number of incoming links and gets the incoming links.
* @private
*/
private _getIncomingLinks() {
this.loading = true;

if (this.pageEvent.pageIndex === 0) {
this._incomingService.getIncomingLinks(this.resource.res.id, this.pageEvent.pageIndex, true).subscribe(
(response: CountQueryResponse) => {
this.numberOffAllIncomingLinkRes = response.numberOfResults;
}
);
}

this._incomingService.getIncomingLinks(this.resource.res.id, this.pageEvent.pageIndex).subscribe(
(response: ReadResourceSequence) => {
if (response.resources.length > 0) {
this.incomingLinkResources = response.resources;
}
this.loading = false;
}, (error: ApiResponseError) => {
this.loading = false;
}
);
}

/**
* updates the standoff link value for the resource being displayed.
*
Expand Down