65240: ComCol logo delete on bitstreams endpoint + caching issue fixes when editing logos

This commit is contained in:
Kristof De Langhe
2019-10-17 17:59:18 +02:00
parent bfb2ef021a
commit c7bb6ab17c
5 changed files with 85 additions and 33 deletions

View File

@@ -8,6 +8,8 @@ import { TranslateService } from '@ngx-translate/core';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { CommunityDataService } from '../../core/data/community-data.service'; import { CommunityDataService } from '../../core/data/community-data.service';
import { AuthService } from '../../core/auth/auth.service'; import { AuthService } from '../../core/auth/auth.service';
import { RequestService } from '../../core/data/request.service';
import { ObjectCacheService } from '../../core/cache/object-cache.service';
/** /**
* Form used for creating and editing collections * Form used for creating and editing collections
@@ -75,7 +77,9 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> {
protected translate: TranslateService, protected translate: TranslateService,
protected notificationsService: NotificationsService, protected notificationsService: NotificationsService,
protected authService: AuthService, protected authService: AuthService,
protected dsoService: CommunityDataService) { protected dsoService: CommunityDataService,
super(location, formService, translate, notificationsService, authService); protected requestService: RequestService,
protected objectCache: ObjectCacheService) {
super(location, formService, translate, notificationsService, authService, requestService, objectCache);
} }
} }

View File

@@ -9,6 +9,8 @@ import { TranslateService } from '@ngx-translate/core';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { CommunityDataService } from '../../core/data/community-data.service'; import { CommunityDataService } from '../../core/data/community-data.service';
import { AuthService } from '../../core/auth/auth.service'; import { AuthService } from '../../core/auth/auth.service';
import { RequestService } from '../../core/data/request.service';
import { ObjectCacheService } from '../../core/cache/object-cache.service';
/** /**
* Form used for creating and editing communities * Form used for creating and editing communities
@@ -68,7 +70,9 @@ export class CommunityFormComponent extends ComColFormComponent<Community> {
protected translate: TranslateService, protected translate: TranslateService,
protected notificationsService: NotificationsService, protected notificationsService: NotificationsService,
protected authService: AuthService, protected authService: AuthService,
protected dsoService: CommunityDataService) { protected dsoService: CommunityDataService,
super(location, formService, translate, notificationsService, authService); protected requestService: RequestService,
protected objectCache: ObjectCacheService) {
super(location, formService, translate, notificationsService, authService, requestService, objectCache);
} }
} }

View File

@@ -1,6 +1,6 @@
import { distinctUntilChanged, filter, map, mergeMap, share, switchMap, take, tap } from 'rxjs/operators'; import { distinctUntilChanged, filter, map, mergeMap, share, switchMap, take, tap } from 'rxjs/operators';
import { merge as observableMerge, Observable, throwError as observableThrowError } from 'rxjs'; import { merge as observableMerge, Observable, throwError as observableThrowError, combineLatest as observableCombineLatest } from 'rxjs';
import { isEmpty, isNotEmpty } from '../../shared/empty.util'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
import { NormalizedCommunity } from '../cache/models/normalized-community.model'; import { NormalizedCommunity } from '../cache/models/normalized-community.model';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { CommunityDataService } from './community-data.service'; import { CommunityDataService } from './community-data.service';
@@ -8,15 +8,27 @@ import { CommunityDataService } from './community-data.service';
import { DataService } from './data.service'; import { DataService } from './data.service';
import { DeleteRequest, FindAllOptions, FindByIDRequest, RestRequest } from './request.models'; import { DeleteRequest, FindAllOptions, FindByIDRequest, RestRequest } from './request.models';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { configureRequest, getResponseFromEntry } from '../shared/operators'; import {
configureRequest,
getRemoteDataPayload,
getResponseFromEntry,
getSucceededRemoteData
} from '../shared/operators';
import { CacheableObject } from '../cache/object-cache.reducer'; import { CacheableObject } from '../cache/object-cache.reducer';
import { RestResponse } from '../cache/response.models'; import { RestResponse } from '../cache/response.models';
import { Bitstream } from '../shared/bitstream.model';
import { DSpaceObject } from '../shared/dspace-object.model';
export abstract class ComColDataService<T extends CacheableObject> extends DataService<T> { export abstract class ComColDataService<T extends CacheableObject> extends DataService<T> {
protected abstract cds: CommunityDataService; protected abstract cds: CommunityDataService;
protected abstract objectCache: ObjectCacheService; protected abstract objectCache: ObjectCacheService;
protected abstract halService: HALEndpointService; protected abstract halService: HALEndpointService;
/**
* Linkpath of endpoint to delete the logo
*/
protected logoDeleteLinkpath = 'bitstreams';
/** /**
* Get the scoped endpoint URL by fetching the object with * Get the scoped endpoint URL by fetching the object with
* the given scopeID and returning its HAL link with this * the given scopeID and returning its HAL link with this
@@ -71,14 +83,21 @@ export abstract class ComColDataService<T extends CacheableObject> extends DataS
/** /**
* Delete the logo from the community or collection * Delete the logo from the community or collection
* @param id The community or collection's ID * @param dso The object to delete the logo from
*/ */
public deleteLogo(id: string): Observable<RestResponse> { public deleteLogo(dso: DSpaceObject): Observable<RestResponse> {
return this.getLogoEndpoint(id).pipe( const logo$ = (dso as any).logo;
if (hasValue(logo$)) {
return observableCombineLatest(
logo$.pipe(getSucceededRemoteData(), getRemoteDataPayload(), take(1)),
this.halService.getEndpoint(this.logoDeleteLinkpath)
).pipe(
map(([logo, href]: [Bitstream, string]) => `${href}/${logo.id}`),
map((href: string) => new DeleteRequest(this.requestService.generateRequestId(), href)), map((href: string) => new DeleteRequest(this.requestService.generateRequestId(), href)),
configureRequest(this.requestService), configureRequest(this.requestService),
switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)), switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)),
getResponseFromEntry() getResponseFromEntry()
); );
} }
}
} }

View File

@@ -1,13 +1,20 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row">
<div class="col-12 d-inline-block">
<label>{{type.value + '.edit.logo.label' | translate}}</label> <label>{{type.value + '.edit.logo.label' | translate}}</label>
</div>
<ng-container *ngVar="(dso?.logo | async)?.payload as logo"> <ng-container *ngVar="(dso?.logo | async)?.payload as logo">
<div class="col-8 d-inline-block">
<ds-comcol-page-logo [logo]="logo"></ds-comcol-page-logo> <ds-comcol-page-logo [logo]="logo"></ds-comcol-page-logo>
</div>
<div class="col-4 d-inline-block">
<div *ngIf="logo" class="btn-group btn-group-sm float-right" role="group"> <div *ngIf="logo" class="btn-group btn-group-sm float-right" role="group">
<button type="button" class="btn btn-danger" (click)="deleteLogo()"> <button type="button" class="btn btn-danger" (click)="deleteLogo()">
<i class="fas fa-trash" aria-hidden="true"></i> <i class="fas fa-trash" aria-hidden="true"></i>
</button> </button>
</div> </div>
</ng-container> </div>
<div *ngIf="!logo" class="col-12 d-inline-block">
<ds-uploader *ngIf="initializedUploaderOptions | async" <ds-uploader *ngIf="initializedUploaderOptions | async"
[dropMsg]="type.value + '.edit.logo.upload'" [dropMsg]="type.value + '.edit.logo.upload'"
[dropOverDocumentMsg]="type.value + '.edit.logo.upload'" [dropOverDocumentMsg]="type.value + '.edit.logo.upload'"
@@ -15,6 +22,9 @@
[uploadFilesOptions]="uploadFilesOptions" [uploadFilesOptions]="uploadFilesOptions"
(onCompleteItem)="onCompleteItem()" (onCompleteItem)="onCompleteItem()"
(onUploadError)="onUploadError()"></ds-uploader> (onUploadError)="onUploadError()"></ds-uploader>
</div>
</ng-container>
</div>
</div> </div>
<ds-form *ngIf="formModel" <ds-form *ngIf="formModel"
[formId]="'comcol-form-id'" [formId]="'comcol-form-id'"

View File

@@ -23,6 +23,9 @@ import { RemoteData } from '../../../core/data/remote-data';
import { Bitstream } from '../../../core/shared/bitstream.model'; import { Bitstream } from '../../../core/shared/bitstream.model';
import { combineLatest as observableCombineLatest } from 'rxjs'; import { combineLatest as observableCombineLatest } from 'rxjs';
import { RestRequestMethod } from '../../../core/data/rest-request-method'; import { RestRequestMethod } from '../../../core/data/rest-request-method';
import { RequestService } from '../../../core/data/request.service';
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
import { take } from 'rxjs/operators';
/** /**
* A form for creating and editing Communities or Collections * A form for creating and editing Communities or Collections
@@ -74,7 +77,6 @@ export class ComColFormComponent<T extends DSpaceObject> implements OnInit, OnDe
* @type {UploaderOptions} * @type {UploaderOptions}
*/ */
uploadFilesOptions: UploaderOptions = Object.assign(new UploaderOptions(), { uploadFilesOptions: UploaderOptions = Object.assign(new UploaderOptions(), {
disableMultipart: true,
autoUpload: false autoUpload: false
}); });
@@ -112,7 +114,9 @@ export class ComColFormComponent<T extends DSpaceObject> implements OnInit, OnDe
protected formService: DynamicFormService, protected formService: DynamicFormService,
protected translate: TranslateService, protected translate: TranslateService,
protected notificationsService: NotificationsService, protected notificationsService: NotificationsService,
protected authService: AuthService) { protected authService: AuthService,
protected requestService: RequestService,
protected objectCache: ObjectCacheService) {
} }
ngOnInit(): void { ngOnInit(): void {
@@ -204,7 +208,7 @@ export class ComColFormComponent<T extends DSpaceObject> implements OnInit, OnDe
*/ */
deleteLogo() { deleteLogo() {
if (hasValue(this.dso.id)) { if (hasValue(this.dso.id)) {
this.dsoService.deleteLogo(this.dso.id).subscribe((response: RestResponse) => { this.dsoService.deleteLogo(this.dso).subscribe((response: RestResponse) => {
if (response.isSuccessful) { if (response.isSuccessful) {
this.notificationsService.success( this.notificationsService.success(
this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.title'), this.translate.get(this.type.value + '.edit.logo.notifications.delete.success.title'),
@@ -217,14 +221,25 @@ export class ComColFormComponent<T extends DSpaceObject> implements OnInit, OnDe
errorResponse.errorMessage errorResponse.errorMessage
); );
} }
this.refreshCache();
}); });
} }
} }
/**
* Refresh the object's cache to ensure the latest version
*/
private refreshCache() {
(this.dso as any).logo = undefined;
this.requestService.removeByHrefSubstring(this.dso.self);
this.objectCache.remove(this.dso.self);
}
/** /**
* The request was successful, display a success notification * The request was successful, display a success notification
*/ */
public onCompleteItem() { public onCompleteItem() {
this.refreshCache();
this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.logo.notifications.add.success')); this.notificationsService.success(null, this.translate.get(this.type.value + '.edit.logo.notifications.add.success'));
this.finishUpload.emit(); this.finishUpload.emit();
} }