mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
65717: Edit-bitstreams bundle upload button + bitstream-upload component changes to include bundles
This commit is contained in:
@@ -270,12 +270,14 @@
|
|||||||
"home.top-level-communities.head": "Communities in DSpace",
|
"home.top-level-communities.head": "Communities in DSpace",
|
||||||
"home.top-level-communities.help": "Select a community to browse its collections.",
|
"home.top-level-communities.help": "Select a community to browse its collections.",
|
||||||
|
|
||||||
"item.bitstreams.upload.bundle-name": "Bundle Name",
|
"item.bitstreams.upload.bundle": "Bundle",
|
||||||
|
"item.bitstreams.upload.bundles.empty": "This item doesn\'t contain any bundles to upload a bitstream to.",
|
||||||
"item.bitstreams.upload.drop-message": "Drop a file to upload",
|
"item.bitstreams.upload.drop-message": "Drop a file to upload",
|
||||||
"item.bitstreams.upload.failed": "Upload failed. Please verify the content before retrying.",
|
"item.bitstreams.upload.failed": "Upload failed. Please verify the content before retrying.",
|
||||||
"item.bitstreams.upload.item": "Item: ",
|
"item.bitstreams.upload.item": "Item: ",
|
||||||
"item.bitstreams.upload.title": "Upload bitstream",
|
"item.bitstreams.upload.title": "Upload bitstream",
|
||||||
|
|
||||||
|
"item.edit.bitstreams.bundle.edit.buttons.upload": "Upload",
|
||||||
"item.edit.bitstreams.bundle.name": "BUNDLE: {{ name }}",
|
"item.edit.bitstreams.bundle.name": "BUNDLE: {{ name }}",
|
||||||
"item.edit.bitstreams.discard-button": "Discard",
|
"item.edit.bitstreams.discard-button": "Discard",
|
||||||
"item.edit.bitstreams.edit.buttons.download": "Download",
|
"item.edit.bitstreams.edit.buttons.download": "Download",
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<div class="container">
|
<div class="container" *ngVar="(bundlesRD$ | async)?.payload?.page as bundles">
|
||||||
<div class="row">
|
<ng-container *ngIf="bundles">
|
||||||
|
<div class="row" *ngIf="bundles.length > 0">
|
||||||
<div class="col-12 mb-4">
|
<div class="col-12 mb-4">
|
||||||
<h2>{{'item.bitstreams.upload.title' | translate}}</h2>
|
<h2>{{'item.bitstreams.upload.title' | translate}}</h2>
|
||||||
<ng-container *ngVar="(itemRD$ | async)?.payload as item">
|
<ng-container *ngVar="(itemRD$ | async)?.payload as item">
|
||||||
@@ -10,11 +11,10 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label for="bundleName" class="font-weight-bold">{{'item.bitstreams.upload.bundle-name' | translate}}</label>
|
<label for="bundleName" class="font-weight-bold">{{'item.bitstreams.upload.bundle' | translate}}</label>
|
||||||
<input id="bundleName"
|
<select id="bundleName" class="form-control" [(ngModel)]="selectedBundleId" (change)="setUploadUrl()">
|
||||||
[(ngModel)]="uploadProperties.bundleName"
|
<option *ngFor="let bundle of bundles" [value]="bundle.id">{{bundle.name}}</option>
|
||||||
type="text"
|
</select>
|
||||||
class="form-control" />
|
|
||||||
<ds-uploader class="w-100"
|
<ds-uploader class="w-100"
|
||||||
[dropMsg]="'item.bitstreams.upload.drop-message'"
|
[dropMsg]="'item.bitstreams.upload.drop-message'"
|
||||||
[dropOverDocumentMsg]="'item.bitstreams.upload.drop-message'"
|
[dropOverDocumentMsg]="'item.bitstreams.upload.drop-message'"
|
||||||
@@ -25,4 +25,12 @@
|
|||||||
(onUploadError)="onUploadError()"></ds-uploader>
|
(onUploadError)="onUploadError()"></ds-uploader>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" *ngIf="bundles.length === 0">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="alert alert-info w-100 d-inline-block" role="alert">
|
||||||
|
{{'item.bitstreams.upload.bundles.empty' | translate}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,17 +2,20 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/
|
|||||||
import { Observable } from 'rxjs/internal/Observable';
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
import { Item } from '../../../core/shared/item.model';
|
import { Item } from '../../../core/shared/item.model';
|
||||||
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
|
import { map, switchMap, take } from 'rxjs/operators';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { UploaderOptions } from '../../../shared/uploader/uploader-options.model';
|
import { UploaderOptions } from '../../../shared/uploader/uploader-options.model';
|
||||||
import { Subscription } from 'rxjs/internal/Subscription';
|
import { Subscription } from 'rxjs/internal/Subscription';
|
||||||
import { hasValue, hasValueOperator } from '../../../shared/empty.util';
|
import { hasValue, isEmpty } from '../../../shared/empty.util';
|
||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
import { AuthService } from '../../../core/auth/auth.service';
|
import { AuthService } from '../../../core/auth/auth.service';
|
||||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { UploaderProperties } from '../../../shared/uploader/uploader-properties.model';
|
|
||||||
import { getBitstreamModulePath } from '../../../app-routing.module';
|
import { getBitstreamModulePath } from '../../../app-routing.module';
|
||||||
|
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||||
|
import { Bundle } from '../../../core/shared/bundle.model';
|
||||||
|
import { BundleDataService } from '../../../core/data/bundle-data.service';
|
||||||
|
import { getRemoteDataPayload, getSucceededRemoteData } from '../../../core/shared/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-upload-bitstream',
|
selector: 'ds-upload-bitstream',
|
||||||
@@ -29,12 +32,23 @@ export class UploadBitstreamComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
itemRD$: Observable<RemoteData<Item>>;
|
itemRD$: Observable<RemoteData<Item>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item's bundles
|
||||||
|
*/
|
||||||
|
bundlesRD$: Observable<RemoteData<PaginatedList<Bundle>>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID of the currently selected bundle to upload a bitstream to
|
||||||
|
*/
|
||||||
|
selectedBundleId: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The uploader configuration options
|
* The uploader configuration options
|
||||||
* @type {UploaderOptions}
|
* @type {UploaderOptions}
|
||||||
*/
|
*/
|
||||||
uploadFilesOptions: UploaderOptions = {
|
uploadFilesOptions: UploaderOptions = {
|
||||||
url: '',
|
// URL needs to contain something to not produce any errors. This will be replaced once a bundle has been selected.
|
||||||
|
url: 'placeholder',
|
||||||
authToken: null,
|
authToken: null,
|
||||||
disableMultipart: false,
|
disableMultipart: false,
|
||||||
itemAlias: null
|
itemAlias: null
|
||||||
@@ -46,16 +60,10 @@ export class UploadBitstreamComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
subs: Subscription[] = [];
|
subs: Subscription[] = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Properties to send with the upload request
|
|
||||||
*/
|
|
||||||
uploadProperties = Object.assign(new UploaderProperties(), {
|
|
||||||
bundleName: 'ORIGINAL'
|
|
||||||
});
|
|
||||||
|
|
||||||
constructor(protected route: ActivatedRoute,
|
constructor(protected route: ActivatedRoute,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected itemService: ItemDataService,
|
protected itemService: ItemDataService,
|
||||||
|
protected bundleService: BundleDataService,
|
||||||
protected authService: AuthService,
|
protected authService: AuthService,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService) {
|
||||||
@@ -63,25 +71,36 @@ export class UploadBitstreamComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.itemRD$ = this.route.data.pipe(map((data) => data.item));
|
this.itemRD$ = this.route.data.pipe(map((data) => data.item));
|
||||||
this.subs.push(
|
this.bundlesRD$ = this.itemRD$.pipe(
|
||||||
this.route.queryParams.pipe(
|
switchMap((itemRD: RemoteData<Item>) => itemRD.payload.bundles)
|
||||||
map((params) => params.bundleName),
|
|
||||||
hasValueOperator(),
|
|
||||||
distinctUntilChanged()
|
|
||||||
).subscribe((bundleName: string) => {
|
|
||||||
this.uploadProperties.bundleName = bundleName;
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
this.subs.push(
|
this.selectedBundleId = this.route.snapshot.queryParams.bundle;
|
||||||
this.itemRD$.pipe(
|
if (isEmpty(this.selectedBundleId)) {
|
||||||
map((itemRD: RemoteData<Item>) => itemRD.payload),
|
this.bundlesRD$.pipe(
|
||||||
switchMap((item: Item) => this.itemService.getBitstreamsEndpoint(item.id)),
|
getSucceededRemoteData(),
|
||||||
distinctUntilChanged()
|
getRemoteDataPayload(),
|
||||||
).subscribe((url: string) => {
|
take(1)
|
||||||
this.uploadFilesOptions.url = url;
|
).subscribe((bundles: PaginatedList<Bundle>) => {
|
||||||
|
if (bundles.page.length > 0) {
|
||||||
|
this.selectedBundleId = bundles.page[0].id;
|
||||||
|
this.setUploadUrl();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setUploadUrl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the upload url to match the selected bundle ID
|
||||||
|
*/
|
||||||
|
setUploadUrl() {
|
||||||
|
this.bundleService.getBitstreamsEndpoint(this.selectedBundleId).pipe(take(1)).subscribe((href: string) => {
|
||||||
|
this.uploadFilesOptions.url = href;
|
||||||
|
if (isEmpty(this.uploadFilesOptions.authToken)) {
|
||||||
this.uploadFilesOptions.authToken = this.authService.buildAuthHeader();
|
this.uploadFilesOptions.authToken = this.authService.buildAuthHeader();
|
||||||
})
|
}
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -24,6 +24,7 @@ import { EditRelationshipListComponent } from './item-relationships/edit-relatio
|
|||||||
import { AbstractItemUpdateComponent } from './abstract-item-update/abstract-item-update.component';
|
import { AbstractItemUpdateComponent } from './abstract-item-update/abstract-item-update.component';
|
||||||
import { ItemMoveComponent } from './item-move/item-move.component';
|
import { ItemMoveComponent } from './item-move/item-move.component';
|
||||||
import { ItemEditBitstreamBundleComponent } from './item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component';
|
import { ItemEditBitstreamBundleComponent } from './item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component';
|
||||||
|
import { BundleDataService } from '../../core/data/bundle-data.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module that contains all components related to the Edit Item page administrator functionality
|
* Module that contains all components related to the Edit Item page administrator functionality
|
||||||
@@ -58,6 +59,9 @@ import { ItemEditBitstreamBundleComponent } from './item-bitstreams/item-edit-bi
|
|||||||
EditRelationshipListComponent,
|
EditRelationshipListComponent,
|
||||||
ItemCollectionMapperComponent,
|
ItemCollectionMapperComponent,
|
||||||
ItemMoveComponent,
|
ItemMoveComponent,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
BundleDataService
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class EditItemPageModule {
|
export class EditItemPageModule {
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table *ngIf="bundles?.length > 0" class="table table-responsive table-striped table-bordered mt-4">
|
<table *ngIf="item && bundles?.length > 0" class="table table-responsive table-striped table-bordered mt-4">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{'item.edit.bitstreams.headers.name' | translate}}</th>
|
<th>{{'item.edit.bitstreams.headers.name' | translate}}</th>
|
||||||
@@ -33,7 +33,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<ds-item-edit-bitstream-bundle *ngFor="let bundle of bundles"
|
<ds-item-edit-bitstream-bundle *ngFor="let bundle of bundles"
|
||||||
[url]="url"
|
[url]="url"
|
||||||
[bundle]="bundle">
|
[bundle]="bundle"
|
||||||
|
[item]="item">
|
||||||
</ds-item-edit-bitstream-bundle>
|
</ds-item-edit-bitstream-bundle>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -1,6 +1,16 @@
|
|||||||
<ng-template #bundleView>
|
<ng-template #bundleView>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4">{{'item.edit.bitstreams.bundle.name' | translate:{ name: bundle.name } }}</td>
|
<td colspan="3" class="font-weight-bold">{{'item.edit.bitstreams.bundle.name' | translate:{ name: bundle.name } }}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div class="btn-group bundle-action-buttons">
|
||||||
|
<button [routerLink]="['/items/', item.id, 'bitstreams', 'new']"
|
||||||
|
[queryParams]="{bundle: bundle.id}"
|
||||||
|
class="btn btn-outline-success btn-sm"
|
||||||
|
title="{{'item.edit.bitstreams.bundle.edit.buttons.upload' | translate}}">
|
||||||
|
<i class="fas fa-upload fa-fw"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<ng-container *ngVar="((updates$ | async) | dsObjectValues) as updateValues">
|
<ng-container *ngVar="((updates$ | async) | dsObjectValues) as updateValues">
|
||||||
<tr *ngFor="let updateValue of updateValues"
|
<tr *ngFor="let updateValue of updateValues"
|
||||||
|
@@ -6,6 +6,7 @@ import { FieldUpdates } from '../../../../core/data/object-updates/object-update
|
|||||||
import { toBitstreamsArray } from '../../../../core/shared/item-bitstreams-utils';
|
import { toBitstreamsArray } from '../../../../core/shared/item-bitstreams-utils';
|
||||||
import { switchMap } from 'rxjs/operators';
|
import { switchMap } from 'rxjs/operators';
|
||||||
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||||
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-item-edit-bitstream-bundle',
|
selector: 'ds-item-edit-bitstream-bundle',
|
||||||
@@ -26,6 +27,11 @@ export class ItemEditBitstreamBundleComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
@Input() bundle: Bundle;
|
@Input() bundle: Bundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item the bundle belongs to
|
||||||
|
*/
|
||||||
|
@Input() item: Item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current url of this page
|
* The current url of this page
|
||||||
*/
|
*/
|
||||||
|
@@ -13,6 +13,7 @@ import { HttpClient } from '@angular/common/http';
|
|||||||
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
||||||
import { FindAllOptions } from './request.models';
|
import { FindAllOptions } from './request.models';
|
||||||
import { Observable } from 'rxjs/internal/Observable';
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service responsible for fetching/sending data from/to the REST API on the bundles endpoint
|
* A service responsible for fetching/sending data from/to the REST API on the bundles endpoint
|
||||||
@@ -20,6 +21,7 @@ import { Observable } from 'rxjs/internal/Observable';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class BundleDataService extends DataService<Bundle> {
|
export class BundleDataService extends DataService<Bundle> {
|
||||||
protected linkPath = 'bundles';
|
protected linkPath = 'bundles';
|
||||||
|
protected bitstreamsEndpoint = 'bitstreams';
|
||||||
protected forceBypassCache = false;
|
protected forceBypassCache = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -43,4 +45,14 @@ export class BundleDataService extends DataService<Bundle> {
|
|||||||
getBrowseEndpoint(options: FindAllOptions = {}, linkPath?: string): Observable<string> {
|
getBrowseEndpoint(options: FindAllOptions = {}, linkPath?: string): Observable<string> {
|
||||||
return this.halService.getEndpoint(this.linkPath);
|
return this.halService.getEndpoint(this.linkPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the bitstreams endpoint for a bundle
|
||||||
|
* @param bundleId
|
||||||
|
*/
|
||||||
|
getBitstreamsEndpoint(bundleId: string): Observable<string> {
|
||||||
|
return this.getBrowseEndpoint().pipe(
|
||||||
|
switchMap((href: string) => this.halService.getEndpoint(this.bitstreamsEndpoint, `${href}/${bundleId}`))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user