0">
-
-
+ |
+
{{ 'resource-policies.table.headers.title.for.' + resourceType | translate }} {{resourceUUID}}
-
-
+
+
+
+
+
|
+
+
+
+
+
+ |
{{'resource-policies.table.headers.id' | translate}} |
{{'resource-policies.table.headers.name' | translate}} |
{{'resource-policies.table.headers.policyType' | translate}} |
@@ -23,29 +46,39 @@
-
+
+
+
+
+
+
+ |
- {{policy.id}}
- |
- {{policy.name}} |
- {{policy.policyType}} |
- {{policy.action}} |
-
- {{getEPersonName(policy) | async}}
+ | {{entry.policy.name}} |
+ {{entry.policy.policyType}} |
+ {{entry.policy.action}} |
+
+ {{getEPersonName(entry.policy) | async}}
|
- |
-
- {{getGroupName(policy) | async}}
-
+ |
+
+ {{getGroupName(entry.policy) | async}}
+
{{'resource-policies.table.headers.edit' | translate}}
|
- |
- {{policy.startDate}} |
- {{policy.endDate}} |
+ |
+ {{formatDate(entry.policy.startDate)}} |
+ {{formatDate(entry.policy.endDate)}} |
|
diff --git a/src/app/shared/resource-policies/resource-policies.component.ts b/src/app/shared/resource-policies/resource-policies.component.ts
index 257657afdd..8ad11315a4 100644
--- a/src/app/shared/resource-policies/resource-policies.component.ts
+++ b/src/app/shared/resource-policies/resource-policies.component.ts
@@ -1,26 +1,32 @@
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
-import { BehaviorSubject, Observable, Subscription } from 'rxjs';
-import { filter, map, startWith, take } from 'rxjs/operators';
+import { BehaviorSubject, from as observableFrom, Observable, Subscription } from 'rxjs';
+import { concatMap, distinctUntilChanged, filter, map, reduce, scan, startWith, take } from 'rxjs/operators';
+import { TranslateService } from '@ngx-translate/core';
import { ResourcePolicyService } from '../../core/resource-policy/resource-policy.service';
-import { PaginatedList } from '../../core/data/paginated-list';
import {
getFirstSucceededRemoteDataPayload,
getFirstSucceededRemoteDataWithNotEmptyPayload,
getSucceededRemoteData
} from '../../core/shared/operators';
-import { RemoteData } from '../../core/data/remote-data';
import { ResourcePolicy } from '../../core/resource-policy/models/resource-policy.model';
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
import { Group } from '../../core/eperson/models/group.model';
import { GroupDataService } from '../../core/eperson/group-data.service';
-import { hasValue, isNotEmpty } from '../empty.util';
+import { hasValue, isEmpty, isNotEmpty } from '../empty.util';
import { EPerson } from '../../core/eperson/models/eperson.model';
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
-import { followLink } from '../utils/follow-link-config.model';
import { RequestService } from '../../core/data/request.service';
+import { NotificationsService } from '../notifications/notifications.service';
+import { dateToString, stringToNgbDateStruct } from '../date.util';
+
+interface ResourcePolicyCheckboxEntry {
+ id: string;
+ policy: ResourcePolicy;
+ checked: boolean
+}
@Component({
selector: 'ds-resource-policies',
@@ -51,11 +57,17 @@ export class ResourcePoliciesComponent implements OnInit, OnDestroy {
private isActive: boolean;
/**
- * The list of policies for given resource
- * @type {Observable
>>}
+ * A boolean representing if a submission delete operation is pending
+ * @type {BehaviorSubject}
*/
- private resourcePolicies$: BehaviorSubject>> =
- new BehaviorSubject>>({} as any);
+ private processingDelete$ = new BehaviorSubject(false);
+
+ /**
+ * The list of policies for given resource
+ * @type {BehaviorSubject}
+ */
+ private resourcePoliciesEntries$: BehaviorSubject =
+ new BehaviorSubject([]);
/**
* Array to track all subscriptions and unsubscribe them onDestroy
@@ -70,20 +82,24 @@ export class ResourcePoliciesComponent implements OnInit, OnDestroy {
* @param {DSONameService} dsoNameService
* @param {EPersonDataService} ePersonService
* @param {GroupDataService} groupService
+ * @param {NotificationsService} notificationsService
* @param {RequestService} requestService
* @param {ResourcePolicyService} resourcePolicyService
* @param {ActivatedRoute} route
* @param {Router} router
+ * @param {TranslateService} translate
*/
constructor(
private cdr: ChangeDetectorRef,
private dsoNameService: DSONameService,
private ePersonService: EPersonDataService,
private groupService: GroupDataService,
+ private notificationsService: NotificationsService,
private requestService: RequestService,
private resourcePolicyService: ResourcePolicyService,
private route: ActivatedRoute,
- private router: Router
+ private router: Router,
+ private translate: TranslateService
) {
}
@@ -92,22 +108,144 @@ export class ResourcePoliciesComponent implements OnInit, OnDestroy {
*/
ngOnInit(): void {
this.isActive = true;
+ this.initResourcePolicyLIst();
+ }
+
+ canDelete(): Observable {
+ return observableFrom(this.resourcePoliciesEntries$.value).pipe(
+ filter((entry: ResourcePolicyCheckboxEntry) => entry.checked),
+ reduce((acc: any, value: any) => [...acc, ...value], []),
+ map((entries: ResourcePolicyCheckboxEntry[]) => isNotEmpty(entries)),
+ distinctUntilChanged()
+ )
+ }
+
+ deleteSelectedResourcePolicies(): void {
+ this.processingDelete$.next(true);
+ const policiesToDelete: ResourcePolicyCheckboxEntry[] = this.resourcePoliciesEntries$.value
+ .filter((entry: ResourcePolicyCheckboxEntry) => entry.checked);
+ observableFrom(policiesToDelete).pipe(
+ concatMap((entry: ResourcePolicyCheckboxEntry) => this.resourcePolicyService.delete(entry.policy.id)),
+ scan((acc: any, value: any) => [...acc, ...value], []),
+ filter((results: boolean[]) => results.length === policiesToDelete.length),
+ take(1),
+ ).subscribe((results: boolean[]) => {
+ const failureResults = results.filter((result: boolean) => !result);
+ if (isEmpty(failureResults)) {
+ this.notificationsService.success(null, this.translate.get('resource-policies.delete.success.content'));
+ } else {
+ this.notificationsService.error(null, this.translate.get('resource-policies.delete.failure.content'));
+ }
+ this.initResourcePolicyLIst();
+ this.processingDelete$.next(false);
+ })
+ }
+
+ /**
+ * Returns a date in simplified format (YYYY-MM-DD).
+ *
+ * @param date
+ * @return a string with formatted date
+ */
+ formatDate(date: string): string {
+ return isNotEmpty(date) ? dateToString(stringToNgbDateStruct(date)) : '';
+ }
+
+ /**
+ * Return the ePerson's name which the given policy is linked to
+ *
+ * @param policy The resource policy
+ */
+ getEPersonName(policy: ResourcePolicy): Observable {
+ // TODO to be reviewed when https://github.com/DSpace/dspace-angular/issues/644 will be resolved
+ return this.ePersonService.findByHref(policy._links.eperson.href).pipe(
+ filter(() => this.isActive),
+ getFirstSucceededRemoteDataWithNotEmptyPayload(),
+ map((eperson: EPerson) => this.dsoNameService.getName(eperson)),
+ startWith('')
+ )
+ }
+
+ /**
+ * Return the group's name which the given policy is linked to
+ *
+ * @param policy The resource policy
+ */
+ getGroupName(policy: ResourcePolicy): Observable {
+ // TODO to be reviewed when https://github.com/DSpace/dspace-angular/issues/644 will be resolved
+ return this.groupService.findByHref(policy._links.group.href).pipe(
+ filter(() => this.isActive),
+ getFirstSucceededRemoteDataWithNotEmptyPayload(),
+ map((group: Group) => this.dsoNameService.getName(group)),
+ startWith('')
+ )
+ }
+
+ /**
+ * Return all resource's policies
+ *
+ * @return an observable that emits all resource's policies
+ */
+ getResourcePolicies(): Observable {
+ return this.resourcePoliciesEntries$.asObservable();
+ }
+
+ /**
+ * Check whether the given policy is linked to a ePerson
+ *
+ * @param policy The resource policy
+ * @return an observable that emits true when the policy is linked to a ePerson, false otherwise
+ */
+ hasEPerson(policy): Observable {
+ // TODO to be reviewed when https://github.com/DSpace/dspace-angular/issues/644 will be resolved
+ return this.ePersonService.findByHref(policy._links.eperson.href).pipe(
+ filter(() => this.isActive),
+ getFirstSucceededRemoteDataPayload(),
+ map((eperson: EPerson) => isNotEmpty(eperson))
+ )
+ }
+
+ /**
+ * Check whether the given policy is linked to a group
+ *
+ * @param policy The resource policy
+ * @return an observable that emits true when the policy is linked to a group, false otherwise
+ */
+ hasGroup(policy): Observable {
+ // TODO to be reviewed when https://github.com/DSpace/dspace-angular/issues/644 will be resolved
+ return this.groupService.findByHref(policy._links.group.href).pipe(
+ filter(() => this.isActive),
+ getFirstSucceededRemoteDataPayload(),
+ map((group: Group) => isNotEmpty(group))
+ )
+ }
+
+ initResourcePolicyLIst() {
+ // TODO to be reviewed when https://github.com/DSpace/dspace-angular/issues/644 will be resolved
this.requestService.removeByHrefSubstring(this.resourceUUID);
- this.resourcePolicyService.searchByResource(this.resourceUUID, null,
- followLink('eperson'), followLink('group')).pipe(
+ this.resourcePolicyService.searchByResource(this.resourceUUID).pipe(
filter(() => this.isActive),
getSucceededRemoteData(),
take(1)
).subscribe((result) => {
- this.resourcePolicies$.next(result);
+ const entries = result.payload.page.map((policy: ResourcePolicy) => ({
+ id: policy.id,
+ policy: policy,
+ checked: false
+ }));
+ this.resourcePoliciesEntries$.next(entries);
+ this.cdr.detectChanges();
});
+ }
+ isProcessingDelete(): Observable {
+ return this.processingDelete$.asObservable();
}
/**
* Redirect to resource policy creation page
*/
- createResourcePolicy(): void {
+ redirectToResourcePolicyCreatePage(): void {
this.router.navigate([`../create`], {
relativeTo: this.route,
queryParams: {
@@ -122,7 +260,7 @@ export class ResourcePoliciesComponent implements OnInit, OnDestroy {
*
* @param policy The resource policy
*/
- editResourcePolicy(policy: ResourcePolicy): void {
+ redirectToResourcePolicyEditPage(policy: ResourcePolicy): void {
this.router.navigate([`../edit`], {
relativeTo: this.route,
queryParams: {
@@ -131,79 +269,15 @@ export class ResourcePoliciesComponent implements OnInit, OnDestroy {
})
}
- /**
- * Return the ePerson's name which the given policy is linked to
- *
- * @param policy The resource policy
- */
- getEPersonName(policy: ResourcePolicy): Observable {
- return policy.eperson.pipe(
- filter(() => this.isActive),
- getFirstSucceededRemoteDataWithNotEmptyPayload(),
- map((eperson: EPerson) => this.dsoNameService.getName(eperson)),
- startWith('')
- )
- }
-
- /**
- * Return the group's name which the given policy is linked to
- *
- * @param policy The resource policy
- */
- getGroupName(policy: ResourcePolicy): Observable {
- return policy.group.pipe(
- filter(() => this.isActive),
- getFirstSucceededRemoteDataWithNotEmptyPayload(),
- map((group: Group) => this.dsoNameService.getName(group)),
- startWith('')
- )
- }
-
- /**
- * Return all resource's policies
- *
- * @return an observable that emits all resource's policies
- */
- getResourcePolicies(): Observable>> {
- return this.resourcePolicies$.asObservable();
- }
-
- /**
- * Check whether the given policy is linked to a ePerson
- *
- * @param policy The resource policy
- * @return an observable that emits true when the policy is linked to a ePerson, false otherwise
- */
- hasEPerson(policy): Observable {
- return policy.eperson.pipe(
- filter(() => this.isActive),
- getFirstSucceededRemoteDataPayload(),
- map((eperson: EPerson) => isNotEmpty(eperson))
- )
- }
-
- /**
- * Check whether the given policy is linked to a group
- *
- * @param policy The resource policy
- * @return an observable that emits true when the policy is linked to a group, false otherwise
- */
- hasGroup(policy): Observable {
- return policy.group.pipe(
- filter(() => this.isActive),
- getFirstSucceededRemoteDataPayload(),
- map((group: Group) => isNotEmpty(group))
- )
- }
-
/**
* Redirect to group edit page
*
* @param policy The resource policy
*/
redirectToGroupEditPage(policy: ResourcePolicy): void {
+ this.requestService.removeByHrefSubstring(policy._links.group.href);
this.subs.push(
- policy.group.pipe(
+ this.groupService.findByHref(policy._links.group.href).pipe(
filter(() => this.isActive),
getFirstSucceededRemoteDataPayload(),
map((group: Group) => group.id)
@@ -211,6 +285,21 @@ export class ResourcePoliciesComponent implements OnInit, OnDestroy {
)
}
+ /**
+ * Select/unselect all checkbox in the list
+ */
+ selectAllCheckbox(event: any): void {
+ const checked = event.target.checked;
+ this.resourcePoliciesEntries$.value.forEach((entry: ResourcePolicyCheckboxEntry) => entry.checked = checked);
+ }
+
+ /**
+ * Select/unselect checkbox
+ */
+ selectCheckbox(policyEntry: ResourcePolicyCheckboxEntry, checked: boolean) {
+ policyEntry.checked = checked;
+ }
+
/**
* Unsubscribe from all subscriptions
*/
@@ -220,4 +309,5 @@ export class ResourcePoliciesComponent implements OnInit, OnDestroy {
.filter((subscription) => hasValue(subscription))
.forEach((subscription) => subscription.unsubscribe())
}
+
}