[CST-4499] Version history (WIP) - New version modal and other changes

This commit is contained in:
Davide Negretti
2021-09-09 00:57:44 +02:00
parent 72bfab16df
commit d402ab7dcf
10 changed files with 170 additions and 23 deletions

View File

@@ -8,19 +8,22 @@ import { CoreState } from '../core.reducers';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { HttpClient } from '@angular/common/http'; import { HttpClient, HttpHeaders } from '@angular/common/http';
import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
import { FindListOptions } from './request.models'; import { FindListOptions, PostRequest } from './request.models';
import { Observable } from 'rxjs'; import { Observable, of } from 'rxjs';
import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
import { RemoteData } from './remote-data'; import { RemoteData } from './remote-data';
import { PaginatedList } from './paginated-list.model'; import { PaginatedList } from './paginated-list.model';
import { Version } from '../shared/version.model'; import { Version } from '../shared/version.model';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap, take } from 'rxjs/operators';
import { dataService } from '../cache/builders/build-decorators'; import { dataService } from '../cache/builders/build-decorators';
import { VERSION_HISTORY } from '../shared/version-history.resource-type'; import { VERSION_HISTORY } from '../shared/version-history.resource-type';
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
import { VersionDataService } from './version-data.service'; import { VersionDataService } from './version-data.service';
import { MetadataMap } from '../shared/metadata.models';
import { Bundle } from '../shared/bundle.model';
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
/** /**
* Service responsible for handling requests related to the VersionHistory object * Service responsible for handling requests related to the VersionHistory object
@@ -79,4 +82,18 @@ export class VersionHistoryDataService extends DataService<VersionHistory> {
return this.versionDataService.findAllByHref(hrefObs, undefined, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); return this.versionDataService.findAllByHref(hrefObs, undefined, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
} }
public createVersion(itemHref: string, summary: string): Observable<RemoteData<Version>> {
const requestId = this.requestService.generateRequestId();
const requestOptions: HttpOptions = Object.create({});
let requestHeaders = new HttpHeaders();
requestHeaders = requestHeaders.append('Content-Type', 'text/uri-list');
requestOptions.headers = requestHeaders;
const href = 'BASE' + 'api/versioning/versions?summary=' + summary; // TODO
console.error("MISSING BASE URL");
const body = itemHref;
const request = new PostRequest(this.requestService.generateRequestId(), href, itemHref, requestOptions);
this.requestService.send(request);
return this.rdbService.buildFromRequestUUID(requestId);
}
} }

View File

@@ -0,0 +1 @@
<p>item-versions-delete-modal works!</p>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemVersionsDeleteModalComponent } from './item-versions-delete-modal.component';
describe('ItemVersionsDeleteModalComponent', () => {
let component: ItemVersionsDeleteModalComponent;
let fixture: ComponentFixture<ItemVersionsDeleteModalComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ItemVersionsDeleteModalComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ItemVersionsDeleteModalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'ds-item-versions-delete-modal',
templateUrl: './item-versions-delete-modal.component.html',
styleUrls: ['./item-versions-delete-modal.component.scss']
})
export class ItemVersionsDeleteModalComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@@ -1,11 +1,30 @@
<div> <div>
<div class="modal-header">{{'item.version.modal.create.header' | translate}} <div class="modal-header"><h5>{{'item.version.create.modal.header' | translate}}</h5>
<button type="button" class="close" (click)="closeModal()" aria-label="Close"> <button type="button" class="close" (click)="onModalClose()" aria-label="Close">
<span aria-hidden="true">×</span> <span aria-hidden="true">×</span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<!--<h5 *ngIf="header" class="px-2">{{header | translate}}</h5>--> <!--<h5 *ngIf="header" class="px-2">{{header | translate}}</h5>-->
NEW VERSION <p>{{ "item.version.create.modal.text" | translate : {version: versionNumber} }}</p>
<div class="form-group">
<label for="summary">{{'item.version.create.modal.form.summary.label' | translate }}:</label>
<input type="text" id="summary" required class="form-control" [(ngModel)]="newVersionSummary"
placeholder="{{'item.version.create.modal.form.summary.placeholder' | translate }}"/>
</div>
</div>
<div class="modal-footer">
<!-- <div class="btn-group">-->
<button class="btn btn-danger btn-sm"
(click)="onModalClose()"
title="{{'item.version.create.modal.button.discard.tooltip' | translate}}">
<i class="fas fa-times fa-fw"></i> Cancel
</button>
<button class="btn btn-success btn-sm"
(click)="onModalSubmit()"
title="{{'item.version.create.modal.button.create.tooltip' | translate}}">
<i class="fas fa-check fa-fw"></i> OK
</button>
<!-- </div>-->
</div> </div>
</div> </div>

View File

@@ -8,13 +8,24 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
}) })
export class ItemVersionsSummaryModalComponent implements OnInit { export class ItemVersionsSummaryModalComponent implements OnInit {
constructor( versionNumber: number;
protected activeModal: NgbActiveModal,) { } newVersionSummary: string;
closeModal() { constructor(
this.activeModal.close(); protected activeModal: NgbActiveModal,
) {
} }
onModalClose() {
this.activeModal.dismiss('item.version.create.message.failure');
}
onModalSubmit() {
this.activeModal.close(this.newVersionSummary);
}
ngOnInit(): void { ngOnInit(): void {
// TODO delete if unused
} }
} }

View File

@@ -2,11 +2,12 @@ import { Component, Input, OnInit } from '@angular/core';
import { Item } from '../../../core/shared/item.model'; import { Item } from '../../../core/shared/item.model';
import { Version } from '../../../core/shared/version.model'; import { Version } from '../../../core/shared/version.model';
import { RemoteData } from '../../../core/data/remote-data'; import { RemoteData } from '../../../core/data/remote-data';
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subject } from 'rxjs';
import { VersionHistory } from '../../../core/shared/version-history.model'; import { VersionHistory } from '../../../core/shared/version-history.model';
import { import {
getAllSucceededRemoteData, getAllSucceededRemoteData,
getAllSucceededRemoteDataPayload, getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, getFirstSucceededRemoteData,
getFirstSucceededRemoteDataPayload,
getRemoteDataPayload getRemoteDataPayload
} from '../../../core/shared/operators'; } from '../../../core/shared/operators';
import { map, startWith, switchMap } from 'rxjs/operators'; import { map, startWith, switchMap } from 'rxjs/operators';
@@ -22,6 +23,8 @@ import { getItemPageRoute } from '../../../item-page/item-page-routing-paths';
import { FormBuilder } from '@angular/forms'; import { FormBuilder } from '@angular/forms';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ItemVersionsSummaryModalComponent } from './item-versions-summary-modal/item-versions-summary-modal.component'; import { ItemVersionsSummaryModalComponent } from './item-versions-summary-modal/item-versions-summary-modal.component';
import { NotificationsService } from '../../notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({
selector: 'ds-item-versions', selector: 'ds-item-versions',
@@ -90,7 +93,7 @@ export class ItemVersionsComponent implements OnInit {
* The page options to use for fetching the versions * The page options to use for fetching the versions
* Start at page 1 and always use the set page size * Start at page 1 and always use the set page size
*/ */
options = Object.assign(new PaginationComponentOptions(),{ options = Object.assign(new PaginationComponentOptions(), {
id: 'ivo', id: 'ivo',
currentPage: 1, currentPage: 1,
pageSize: this.pageSize pageSize: this.pageSize
@@ -114,14 +117,13 @@ export class ItemVersionsComponent implements OnInit {
private paginationService: PaginationService, private paginationService: PaginationService,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private modalService: NgbModal, private modalService: NgbModal,
) { private notificationsService: NotificationsService,
private translateService: TranslateService,
) {
} }
versionBeingEdited: number;
summary = 'test'; // TODO delete // summaryForm = this.formBuilder.group({summary: 's'});
summaryForm = this.formBuilder.group({summary: 's'});
onSummarySubmit() { // TODO submit onSummarySubmit() { // TODO submit
console.log('SUBMITTING ' + this.summary); console.log('SUBMITTING ' + this.summary);
@@ -146,7 +148,38 @@ export class ItemVersionsComponent implements OnInit {
} }
createNewVersion(version) { createNewVersion(version) {
this.modalService.open(ItemVersionsSummaryModalComponent); const successMessageKey = 'item.version.create.message.success';
const failureMessageKey = 'item.version.create.message.failure';
const activeModal = this.modalService.open(ItemVersionsSummaryModalComponent);
activeModal.componentInstance.versionNumber = version.version;
activeModal.result.then((modalResult) => {
const summary = modalResult;
version.item.pipe(getFirstSucceededRemoteDataPayload()).subscribe((item) => {
const itemHref = item._links.self.href;
// TODO crea versione
this.versionHistoryService.createVersion(itemHref, summary).pipe(getFirstCompletedRemoteData()).subscribe((postResult) => {
const newVersion = postResult.payload;
const newVersionNumber = newVersion.version;
console.log("SUCCESS " + newVersionNumber);
console.log('RESPONSE = ' + JSON.stringify(postResult));
this.notificationsService.success(null, this.translateService.get(successMessageKey, {version: newVersionNumber}));
this.refreshSubject.next();
});
// TODO success
// error
this.notificationsService.error(null, this.translateService.get(failureMessageKey));
});
}).catch((msg) => {
this.notificationsService.warning(null, this.translateService.get(failureMessageKey));
}
);
} }
@@ -171,9 +204,14 @@ export class ItemVersionsComponent implements OnInit {
this.versionsRD$ = observableCombineLatest(versionHistory$, currentPagination).pipe( this.versionsRD$ = observableCombineLatest(versionHistory$, currentPagination).pipe(
switchMap(([versionHistory, options]: [VersionHistory, PaginationComponentOptions]) => switchMap(([versionHistory, options]: [VersionHistory, PaginationComponentOptions]) =>
this.versionHistoryService.getVersions(versionHistory.id, this.versionHistoryService.getVersions(versionHistory.id,
new PaginatedSearchOptions({pagination: Object.assign({}, options, { currentPage: options.currentPage })}), new PaginatedSearchOptions({pagination: Object.assign({}, options, {currentPage: options.currentPage})}),
true, true, followLink('item'), followLink('eperson'))) true, true, followLink('item'), followLink('eperson')))
); );
/* TODO fix error and restore refresh
The response for 'http://localhost:8080/server/api/versioning/versionhistories/1/versions?page=0&size=1'
has the self link 'http://localhost:8080/server/api/versioning/versionhistories/1/versions?page=0&embed=item&size=1'.
These don't match. This could mean there's an issue with the REST endpoint
*/
this.hasEpersons$ = this.versionsRD$.pipe( this.hasEpersons$ = this.versionsRD$.pipe(
getAllSucceededRemoteData(), getAllSucceededRemoteData(),
getRemoteDataPayload(), getRemoteDataPayload(),

View File

@@ -235,6 +235,7 @@ import { TextMenuItemComponent } from './menu/menu-item/text-menu-item.component
import { ThemedConfigurationSearchPageComponent } from '../search-page/themed-configuration-search-page.component'; import { ThemedConfigurationSearchPageComponent } from '../search-page/themed-configuration-search-page.component';
import { SearchNavbarComponent } from '../search-navbar/search-navbar.component'; import { SearchNavbarComponent } from '../search-navbar/search-navbar.component';
import { ItemVersionsSummaryModalComponent } from './item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component'; import { ItemVersionsSummaryModalComponent } from './item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component';
import { ItemVersionsDeleteModalComponent } from './item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component';
/** /**
* Declaration needed to make sure all decorator functions are called in time * Declaration needed to make sure all decorator functions are called in time
@@ -588,7 +589,8 @@ const DIRECTIVES = [
...DIRECTIVES, ...DIRECTIVES,
...SHARED_ITEM_PAGE_COMPONENTS, ...SHARED_ITEM_PAGE_COMPONENTS,
...SHARED_SEARCH_PAGE_COMPONENTS, ...SHARED_SEARCH_PAGE_COMPONENTS,
ItemVersionsSummaryModalComponent ItemVersionsSummaryModalComponent,
ItemVersionsDeleteModalComponent
], ],
providers: [ providers: [
...PROVIDERS ...PROVIDERS

View File

@@ -1995,7 +1995,26 @@
"item.version.notice": "This is not the latest version of this item. The latest version can be found <a href='{{destination}}'>here</a>.", "item.version.notice": "This is not the latest version of this item. The latest version can be found <a href='{{destination}}'>here</a>.",
"item.version.modal.create.header": "Create new version",
"item.version.create.modal.header": "Create new version",
"item.version.create.modal.text": "Create a new version for this item starting from version {{version}}",
"item.version.create.modal.button.create": "Create",
"item.version.create.modal.button.create.tooltip": "Create new version",
"item.version.create.modal.button.discard": "Discard",
"item.version.create.modal.button.discard.tooltip": "Do not create new version",
"item.version.create.modal.form.summary.label": "Summary",
"item.version.create.modal.form.summary.placeholder": "Insert the summary for the new version",
"item.version.create.message.success" : "New version has been created with version number {{version}}",
"item.version.create.message.failure" : "New version has not been created",
"journal.listelement.badge": "Journal", "journal.listelement.badge": "Journal",