fix group tests and fix issues with the process detail page

This commit is contained in:
Art Lowel
2021-01-25 15:39:56 +01:00
parent 634836158b
commit 3b67efe09d
8 changed files with 97 additions and 56 deletions

View File

@@ -150,7 +150,7 @@ describe('MembersListComponent', () => {
})); }));
it('should show list of eperson members of current active group', () => { it('should show list of eperson members of current active group', () => {
const epersonIdsFound = fixture.debugElement.queryAll(By.css('#members$ tr td:first-child')); const epersonIdsFound = fixture.debugElement.queryAll(By.css('#ePeopleMembersOfGroup tr td:first-child'));
expect(epersonIdsFound.length).toEqual(1); expect(epersonIdsFound.length).toEqual(1);
epersonMembers.map((eperson: EPerson) => { epersonMembers.map((eperson: EPerson) => {
expect(epersonIdsFound.find((foundEl) => { expect(epersonIdsFound.find((foundEl) => {

View File

@@ -1,12 +1,20 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick, waitForAsync } from '@angular/core/testing'; import {
ComponentFixture,
fakeAsync,
flush,
inject,
TestBed,
tick,
waitForAsync
} from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule, By } from '@angular/platform-browser'; import { BrowserModule, By } from '@angular/platform-browser';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { Observable, of as observableOf } from 'rxjs'; import { Observable, of as observableOf, BehaviorSubject } from 'rxjs';
import { RestResponse } from '../../../../../core/cache/response.models'; import { RestResponse } from '../../../../../core/cache/response.models';
import { buildPaginatedList, PaginatedList } from '../../../../../core/data/paginated-list.model'; import { buildPaginatedList, PaginatedList } from '../../../../../core/data/paginated-list.model';
import { RemoteData } from '../../../../../core/data/remote-data'; import { RemoteData } from '../../../../../core/data/remote-data';
@@ -17,12 +25,16 @@ import { FormBuilderService } from '../../../../../shared/form/builder/form-buil
import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service';
import { GroupMock, GroupMock2 } from '../../../../../shared/testing/group-mock'; import { GroupMock, GroupMock2 } from '../../../../../shared/testing/group-mock';
import { SubgroupsListComponent } from './subgroups-list.component'; import { SubgroupsListComponent } from './subgroups-list.component';
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; import {
createSuccessfulRemoteDataObject$,
createSuccessfulRemoteDataObject
} from '../../../../../shared/remote-data.utils';
import { RouterMock } from '../../../../../shared/mocks/router.mock'; import { RouterMock } from '../../../../../shared/mocks/router.mock';
import { getMockFormBuilderService } from '../../../../../shared/mocks/form-builder-service.mock'; import { getMockFormBuilderService } from '../../../../../shared/mocks/form-builder-service.mock';
import { getMockTranslateService } from '../../../../../shared/mocks/translate.service.mock'; import { getMockTranslateService } from '../../../../../shared/mocks/translate.service.mock';
import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock'; import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock';
import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub'; import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub';
import { map } from 'rxjs/operators';
describe('SubgroupsListComponent', () => { describe('SubgroupsListComponent', () => {
let component: SubgroupsListComponent; let component: SubgroupsListComponent;
@@ -43,7 +55,7 @@ describe('SubgroupsListComponent', () => {
ePersonDataServiceStub = {}; ePersonDataServiceStub = {};
groupsDataServiceStub = { groupsDataServiceStub = {
activeGroup: activeGroup, activeGroup: activeGroup,
subgroups: subgroups, subgroups$: new BehaviorSubject(subgroups),
getActiveGroup(): Observable<Group> { getActiveGroup(): Observable<Group> {
return observableOf(this.activeGroup); return observableOf(this.activeGroup);
}, },
@@ -51,7 +63,11 @@ describe('SubgroupsListComponent', () => {
return this.activeGroup; return this.activeGroup;
}, },
findAllByHref(href: string): Observable<RemoteData<PaginatedList<Group>>> { findAllByHref(href: string): Observable<RemoteData<PaginatedList<Group>>> {
return createSuccessfulRemoteDataObject$(buildPaginatedList<Group>(new PageInfo(), this.subgroups)); return this.subgroups$.pipe(
map((currentGroups: Group[]) => {
return createSuccessfulRemoteDataObject(buildPaginatedList<Group>(new PageInfo(), currentGroups));
})
);
}, },
getGroupEditPageRouterLink(group: Group): string { getGroupEditPageRouterLink(group: Group): string {
return '/admin/access-control/groups/' + group.id; return '/admin/access-control/groups/' + group.id;
@@ -63,7 +79,7 @@ describe('SubgroupsListComponent', () => {
return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])); return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []));
}, },
addSubGroupToGroup(parentGroup, subgroup: Group): Observable<RestResponse> { addSubGroupToGroup(parentGroup, subgroup: Group): Observable<RestResponse> {
this.subgroups = [...this.subgroups, subgroup]; this.subgroups$.next([...this.subgroups$.getValue(), subgroup]);
return observableOf(new RestResponse(true, 200, 'Success')); return observableOf(new RestResponse(true, 200, 'Success'));
}, },
clearGroupsRequests() { clearGroupsRequests() {
@@ -73,11 +89,11 @@ describe('SubgroupsListComponent', () => {
// empty // empty
}, },
deleteSubGroupFromGroup(parentGroup, subgroup: Group): Observable<RestResponse> { deleteSubGroupFromGroup(parentGroup, subgroup: Group): Observable<RestResponse> {
this.subgroups = this.subgroups.find((group: Group) => { this.subgroups$.next(this.subgroups$.getValue().filter((group: Group) => {
if (group.id !== subgroup.id) { if (group.id !== subgroup.id) {
return group; return group;
} }
}); }));
return observableOf(new RestResponse(true, 200, 'Success')); return observableOf(new RestResponse(true, 200, 'Success'));
} }
}; };
@@ -120,7 +136,7 @@ describe('SubgroupsListComponent', () => {
})); }));
it('should show list of subgroups of current active group', () => { it('should show list of subgroups of current active group', () => {
const groupIdsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup$ tr td:first-child')); const groupIdsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup tr td:first-child'));
expect(groupIdsFound.length).toEqual(1); expect(groupIdsFound.length).toEqual(1);
activeGroup.subgroups.map((group: Group) => { activeGroup.subgroups.map((group: Group) => {
expect(groupIdsFound.find((foundEl) => { expect(groupIdsFound.find((foundEl) => {
@@ -132,7 +148,7 @@ describe('SubgroupsListComponent', () => {
describe('if first group delete button is pressed', () => { describe('if first group delete button is pressed', () => {
let groupsFound; let groupsFound;
beforeEach(fakeAsync(() => { beforeEach(fakeAsync(() => {
const addButton = fixture.debugElement.query(By.css('#subgroupsOfGroup$ tbody .deleteButton')); const addButton = fixture.debugElement.query(By.css('#subgroupsOfGroup tbody .deleteButton'));
addButton.triggerEventHandler('click', { addButton.triggerEventHandler('click', {
preventDefault: () => {/**/ preventDefault: () => {/**/
} }
@@ -141,7 +157,7 @@ describe('SubgroupsListComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
})); }));
it('one less subgroup in list from 1 to 0 (of 2 total groups)', () => { it('one less subgroup in list from 1 to 0 (of 2 total groups)', () => {
groupsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup$ tbody tr')); groupsFound = fixture.debugElement.queryAll(By.css('#subgroupsOfGroup tbody tr'));
expect(groupsFound.length).toEqual(0); expect(groupsFound.length).toEqual(0);
}); });
}); });
@@ -151,15 +167,15 @@ describe('SubgroupsListComponent', () => {
let groupsFound; let groupsFound;
beforeEach(fakeAsync(() => { beforeEach(fakeAsync(() => {
component.search({ query: '' }); component.search({ query: '' });
groupsFound = fixture.debugElement.queryAll(By.css('#searchResults$ tbody tr')); groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr'));
})); }));
it('should display all groups', () => { it('should display all groups', () => {
fixture.detectChanges(); fixture.detectChanges();
groupsFound = fixture.debugElement.queryAll(By.css('#searchResults$ tbody tr')); groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr'));
expect(groupsFound.length).toEqual(2); expect(groupsFound.length).toEqual(2);
groupsFound = fixture.debugElement.queryAll(By.css('#searchResults$ tbody tr')); groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr'));
const groupIdsFound = fixture.debugElement.queryAll(By.css('#searchResults$ tbody tr td:first-child')); const groupIdsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr td:first-child'));
allGroups.map((group: Group) => { allGroups.map((group: Group) => {
expect(groupIdsFound.find((foundEl) => { expect(groupIdsFound.find((foundEl) => {
return (foundEl.nativeElement.textContent.trim() === group.uuid); return (foundEl.nativeElement.textContent.trim() === group.uuid);
@@ -170,7 +186,7 @@ describe('SubgroupsListComponent', () => {
describe('if group is already a subgroup', () => { describe('if group is already a subgroup', () => {
it('should have delete button, else it should have add button', () => { it('should have delete button, else it should have add button', () => {
fixture.detectChanges(); fixture.detectChanges();
groupsFound = fixture.debugElement.queryAll(By.css('#searchResults$ tbody tr')); groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr'));
const getSubgroups = groupsDataServiceStub.getSubgroups().subgroups; const getSubgroups = groupsDataServiceStub.getSubgroups().subgroups;
if (getSubgroups !== undefined && getSubgroups.length > 0) { if (getSubgroups !== undefined && getSubgroups.length > 0) {
groupsFound.map((foundGroupRowElement) => { groupsFound.map((foundGroupRowElement) => {

View File

@@ -15,7 +15,7 @@ import {
} from '../../../../../core/shared/operators'; } from '../../../../../core/shared/operators';
import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service';
import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model';
import { EPerson } from '../../../../../core/eperson/models/eperson.model'; import { NoContent } from '../../../../../core/shared/NoContent.model';
/** /**
* Keys to keep track of specific subscriptions * Keys to keep track of specific subscriptions
@@ -264,7 +264,7 @@ export class SubgroupsListComponent implements OnInit, OnDestroy {
* @param nameObject Object request was about * @param nameObject Object request was about
* @param activeGroup Group currently being edited * @param activeGroup Group currently being edited
*/ */
showNotifications(messageSuffix: string, response: Observable<RemoteData<Group>>, nameObject: string, activeGroup: Group) { showNotifications(messageSuffix: string, response: Observable<RemoteData<Group|NoContent>>, nameObject: string, activeGroup: Group) {
response.pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData<Group>) => { response.pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData<Group>) => {
if (rd.hasSucceeded) { if (rd.hasSucceeded) {
this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.success.' + messageSuffix, { name: nameObject })); this.notificationsService.success(this.translateService.get(this.messagePrefix + '.notification.success.' + messageSuffix, { name: nameObject }));

View File

@@ -339,7 +339,7 @@ export abstract class DataService<T extends CacheableObject> implements UpdateDa
this.createAndSendGetRequest(requestHref$, useCachedVersionIfAvailable); this.createAndSendGetRequest(requestHref$, useCachedVersionIfAvailable);
return this.rdbService.buildSingle<T>(href$, ...linksToFollow).pipe( return this.rdbService.buildSingle<T>(requestHref$, ...linksToFollow).pipe(
reRequestStaleRemoteData(reRequestOnStale, () => reRequestStaleRemoteData(reRequestOnStale, () =>
this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)) this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow))
); );

View File

@@ -284,13 +284,13 @@ describe('RequestService', () => {
it('should track it on it\'s way to the store', () => { it('should track it on it\'s way to the store', () => {
spyOn(serviceAsAny, 'trackRequestsOnTheirWayToTheStore'); spyOn(serviceAsAny, 'trackRequestsOnTheirWayToTheStore');
spyOn(serviceAsAny, 'isCachedOrPending').and.returnValue(false); spyOn(serviceAsAny, 'shouldDispatchRequest').and.returnValue(true);
service.send(request); service.send(request);
expect(serviceAsAny.trackRequestsOnTheirWayToTheStore).toHaveBeenCalledWith(request); expect(serviceAsAny.trackRequestsOnTheirWayToTheStore).toHaveBeenCalledWith(request);
}); });
describe('and it isn\'t cached or pending', () => { describe('and it isn\'t cached or pending', () => {
beforeEach(() => { beforeEach(() => {
spyOn(serviceAsAny, 'isCachedOrPending').and.returnValue(false); spyOn(serviceAsAny, 'shouldDispatchRequest').and.returnValue(true);
}); });
it('should dispatch the request', () => { it('should dispatch the request', () => {
@@ -301,7 +301,7 @@ describe('RequestService', () => {
}); });
describe('and it is already cached or pending', () => { describe('and it is already cached or pending', () => {
beforeEach(() => { beforeEach(() => {
spyOn(serviceAsAny, 'isCachedOrPending').and.returnValue(true); spyOn(serviceAsAny, 'shouldDispatchRequest').and.returnValue(false);
}); });
it('shouldn\'t dispatch the request', () => { it('shouldn\'t dispatch the request', () => {
@@ -335,7 +335,7 @@ describe('RequestService', () => {
}); });
describe('isCachedOrPending', () => { describe('shouldDispatchRequest', () => {
describe('when the request is cached', () => { describe('when the request is cached', () => {
describe('in the ObjectCache', () => { describe('in the ObjectCache', () => {
beforeEach(() => { beforeEach(() => {
@@ -344,9 +344,9 @@ describe('RequestService', () => {
spyOn(serviceAsAny, 'hasByUUID').and.returnValue(true); spyOn(serviceAsAny, 'hasByUUID').and.returnValue(true);
}); });
it('should return true for GetRequest', () => { it('should return false for GetRequest', () => {
const result = serviceAsAny.isCachedOrPending(testGetRequest); const result = serviceAsAny.shouldDispatchRequest(testGetRequest, true);
const expected = true; const expected = false;
expect(result).toEqual(expected); expect(result).toEqual(expected);
}); });
@@ -357,9 +357,9 @@ describe('RequestService', () => {
spyOn(serviceAsAny, 'hasByHref').and.returnValues(true); spyOn(serviceAsAny, 'hasByHref').and.returnValues(true);
spyOn(serviceAsAny, 'hasByUUID').and.returnValue(false); spyOn(serviceAsAny, 'hasByUUID').and.returnValue(false);
}); });
it('should return true', () => { it('should return false', () => {
const result = serviceAsAny.isCachedOrPending(testGetRequest); const result = serviceAsAny.shouldDispatchRequest(testGetRequest, true);
const expected = true; const expected = false;
expect(result).toEqual(expected); expect(result).toEqual(expected);
}); });
@@ -371,9 +371,9 @@ describe('RequestService', () => {
spyOn(service, 'isPending').and.returnValue(true); spyOn(service, 'isPending').and.returnValue(true);
}); });
it('should return true', () => { it('should return false', () => {
const result = serviceAsAny.isCachedOrPending(testGetRequest); const result = serviceAsAny.shouldDispatchRequest(testGetRequest, true);
const expected = true; const expected = false;
expect(result).toEqual(expected); expect(result).toEqual(expected);
}); });
@@ -386,9 +386,9 @@ describe('RequestService', () => {
spyOn(serviceAsAny, 'hasByUUID').and.returnValue(false); spyOn(serviceAsAny, 'hasByUUID').and.returnValue(false);
}); });
it('should return false', () => { it('should return true', () => {
const result = serviceAsAny.isCachedOrPending(testGetRequest); const result = serviceAsAny.shouldDispatchRequest(testGetRequest, true);
const expected = false; const expected = true;
expect(result).toEqual(expected); expect(result).toEqual(expected);
}); });

View File

@@ -142,10 +142,16 @@ export class RequestService {
} }
/** /**
* Check if a request is currently pending * Check if a GET request is currently pending
*/ */
isPending(request: GetRequest): boolean { isPending(request: GetRequest): boolean {
// first check requests that haven't made it to the store yet // If the request is not a GET request, it will never be considered pending, because you may
// want to execute the exact same e.g. POST multiple times
if (request.method !== RestRequestMethod.GET) {
return false;
}
// check requests that haven't made it to the store yet
if (this.requestsOnTheirWayToTheStore.includes(request.href)) { if (this.requestsOnTheirWayToTheStore.includes(request.href)) {
return true; return true;
} }
@@ -232,7 +238,7 @@ export class RequestService {
console.warn(`${JSON.stringify(request, null, 2)} is not a GET request. In general only GET requests should reuse cached data.`); console.warn(`${JSON.stringify(request, null, 2)} is not a GET request. In general only GET requests should reuse cached data.`);
} }
if (!useCachedVersionIfAvailable || !this.isCachedOrPending(request)) { if (this.shouldDispatchRequest(request, useCachedVersionIfAvailable)) {
this.dispatchRequest(request); this.dispatchRequest(request);
if (request.method === RestRequestMethod.GET) { if (request.method === RestRequestMethod.GET) {
this.trackRequestsOnTheirWayToTheStore(request); this.trackRequestsOnTheirWayToTheStore(request);
@@ -301,25 +307,38 @@ export class RequestService {
} }
/** /**
* Check if a request is in the cache or if it's still pending * Check if a GET request is in the cache or if it's still pending
* @param {GetRequest} request The request to check * @param {GetRequest} request The request to check
* @param {boolean} useCachedVersionIfAvailable Whether or not to allow the use of a cached version
* @returns {boolean} True if the request is cached or still pending * @returns {boolean} True if the request is cached or still pending
*/ */
public isCachedOrPending(request: GetRequest): boolean { public shouldDispatchRequest(request: GetRequest, useCachedVersionIfAvailable: boolean): boolean {
if (this.isPending(request)) { // if it's not a GET request
if (request.method !== RestRequestMethod.GET) {
return true;
// if it is a GET request, check it isn't pending
} else if (this.isPending(request)) {
return false;
// if it is pending, check if we're allowed to use a cached version
} else if (!useCachedVersionIfAvailable) {
return true; return true;
} else { } else {
// if we are, check the request cache
const urlWithoutEmbedParams = getUrlWithoutEmbedParams(request.href); const urlWithoutEmbedParams = getUrlWithoutEmbedParams(request.href);
if (this.hasByHref(urlWithoutEmbedParams) === true) { if (this.hasByHref(urlWithoutEmbedParams) === true) {
return true; return false;
} else { } else {
// if it isn't in the request cache, check the object cache
let inObjCache = false; let inObjCache = false;
this.objectCache.getByHref(urlWithoutEmbedParams) this.objectCache.getByHref(urlWithoutEmbedParams)
.subscribe((entry: ObjectCacheEntry) => { .subscribe((entry: ObjectCacheEntry) => {
// if the object cache has a match, check if the request that the object came with is
// still valid
inObjCache = this.hasByUUID(entry.requestUUID); inObjCache = this.hasByUUID(entry.requestUUID);
}).unsubscribe(); }).unsubscribe();
return inObjCache; // we should send the request if it isn't cached
return !inObjCache;
} }
} }
} }

View File

@@ -132,7 +132,7 @@ export class GroupDataService extends DataService<Group> {
* @param activeGroup Group we want to delete subgroup from * @param activeGroup Group we want to delete subgroup from
* @param subgroup Subgroup we want to delete from activeGroup * @param subgroup Subgroup we want to delete from activeGroup
*/ */
deleteSubGroupFromGroup(activeGroup: Group, subgroup: Group): Observable<RemoteData<Group>> { deleteSubGroupFromGroup(activeGroup: Group, subgroup: Group): Observable<RemoteData<NoContent>> {
const requestId = this.requestService.generateRequestId(); const requestId = this.requestService.generateRequestId();
const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.subgroupsEndpoint + '/' + subgroup.id); const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.subgroupsEndpoint + '/' + subgroup.id);
this.requestService.send(deleteRequest); this.requestService.send(deleteRequest);
@@ -162,7 +162,7 @@ export class GroupDataService extends DataService<Group> {
* @param activeGroup Group we want to delete member from * @param activeGroup Group we want to delete member from
* @param ePerson EPerson we want to delete from members of given activeGroup * @param ePerson EPerson we want to delete from members of given activeGroup
*/ */
deleteMemberFromGroup(activeGroup: Group, ePerson: EPerson): Observable<RemoteData<Group>> { deleteMemberFromGroup(activeGroup: Group, ePerson: EPerson): Observable<RemoteData<NoContent>> {
const requestId = this.requestService.generateRequestId(); const requestId = this.requestService.generateRequestId();
const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.ePersonsEndpoint + '/' + ePerson.id); const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.ePersonsEndpoint + '/' + ePerson.id);
this.requestService.send(deleteRequest); this.requestService.send(deleteRequest);

View File

@@ -11,7 +11,11 @@ import { ProcessDataService } from '../../core/data/processes/process-data.servi
import { RemoteData } from '../../core/data/remote-data'; import { RemoteData } from '../../core/data/remote-data';
import { Bitstream } from '../../core/shared/bitstream.model'; import { Bitstream } from '../../core/shared/bitstream.model';
import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { getFirstSucceededRemoteDataPayload, redirectOn4xx } from '../../core/shared/operators'; import {
getFirstSucceededRemoteDataPayload,
redirectOn4xx,
getFirstSucceededRemoteData
} from '../../core/shared/operators';
import { URLCombiner } from '../../core/url-combiner/url-combiner'; import { URLCombiner } from '../../core/url-combiner/url-combiner';
import { AlertType } from '../../shared/alert/aletr-type'; import { AlertType } from '../../shared/alert/aletr-type';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
@@ -51,7 +55,7 @@ export class ProcessDetailComponent implements OnInit {
/** /**
* The Process's Output logs * The Process's Output logs
*/ */
outputLogs$: Observable<string>; outputLogs$: BehaviorSubject<string> = new BehaviorSubject(undefined);
/** /**
* Boolean on whether or not to show the output logs * Boolean on whether or not to show the output logs
@@ -105,6 +109,7 @@ export class ProcessDetailComponent implements OnInit {
* Sets the outputLogs when retrieved and sets the showOutputLogs boolean to show them and hide the button. * Sets the outputLogs when retrieved and sets the showOutputLogs boolean to show them and hide the button.
*/ */
showProcessOutputLogs() { showProcessOutputLogs() {
console.log('showProcessOutputLogs');
this.retrievingOutputLogs$.next(true); this.retrievingOutputLogs$.next(true);
this.zone.runOutsideAngular(() => { this.zone.runOutsideAngular(() => {
const processOutputRD$: Observable<RemoteData<Bitstream>> = this.processRD$.pipe( const processOutputRD$: Observable<RemoteData<Bitstream>> = this.processRD$.pipe(
@@ -114,15 +119,15 @@ export class ProcessDetailComponent implements OnInit {
}) })
); );
this.outputLogFileUrl$ = processOutputRD$.pipe( this.outputLogFileUrl$ = processOutputRD$.pipe(
getFirstSucceededRemoteData(),
tap((processOutputFileRD: RemoteData<Bitstream>) => { tap((processOutputFileRD: RemoteData<Bitstream>) => {
if (processOutputFileRD.statusCode === 204) { if (processOutputFileRD.statusCode === 204) {
this.zone.run(() => this.retrievingOutputLogs$.next(false)); this.zone.run(() => this.retrievingOutputLogs$.next(false));
this.showOutputLogs = true; this.showOutputLogs = true;
} }
}), }),
getFirstSucceededRemoteDataPayload(), switchMap((processOutput: RemoteData<Bitstream>) => {
mergeMap((processOutput: Bitstream) => { const url = processOutput.payload._links.content.href;
const url = processOutput._links.content.href;
return this.authService.getShortlivedToken().pipe(take(1), return this.authService.getShortlivedToken().pipe(take(1),
map((token: string) => { map((token: string) => {
return hasValue(token) ? new URLCombiner(url, `?authentication-token=${token}`).toString() : url; return hasValue(token) ? new URLCombiner(url, `?authentication-token=${token}`).toString() : url;
@@ -130,13 +135,14 @@ export class ProcessDetailComponent implements OnInit {
}) })
); );
}); });
this.outputLogs$ = this.outputLogFileUrl$.pipe(take(1), this.outputLogFileUrl$.pipe(take(1),
mergeMap((url: string) => { switchMap((url: string) => {
return this.getTextFile(url); return this.getTextFile(url);
}), }),
finalize(() => this.zone.run(() => this.retrievingOutputLogs$.next(false))), finalize(() => this.zone.run(() => this.retrievingOutputLogs$.next(false)))
); ).subscribe((logs: string) => {
this.outputLogs$.pipe(take(1)).subscribe(); this.outputLogs$.next(logs);
});
} }
getTextFile(filename: string): Observable<string> { getTextFile(filename: string): Observable<string> {