Skip to content

Commit 8b1ac9c

Browse files
Andrea Barbassovins01-4science
authored andcommitted
Merged in task/dspace-cris-2023_02_x/DSC-2354 (pull request DSpace#3179)
[DSC-2354] Optimize in-workflow statistics visualization Approved-by: Vincenzo Mecca
2 parents 03836ef + 22a2b87 commit 8b1ac9c

36 files changed

Lines changed: 222 additions & 40 deletions

File tree

src/app/core/data/feature-authorization/feature-id.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ export enum FeatureID {
3939
EPersonForgotPassword = 'epersonForgotPassword',
4040
ShowClaimItem = 'showClaimItem',
4141
CanCorrectItem = 'canCorrectItem',
42+
CanViewInWorkflowSinceStatistics = 'canViewInWorkflowSinceStatistics',
4243
}

src/app/my-dspace-page/my-dspace-page.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
[selectionConfig]="{ repeatable: true, listId: listId }"
1515
(deselectObject)="onDeselectObject($event)"
1616
(selectObject)="onSelectObject($event)"
17-
>
18-
<ds-my-dspace-bulk-action
17+
[showWorkflowStatistics]="true">
18+
<!-- Using *ngIf breaks the projection, so we are using hidden instead -->
19+
<ds-my-dspace-bulk-action [hidden]="(currentConfiguration$ | async) !== workflowType"
1920
bulkActions
2021
[listId]="listId"
21-
*ngIf="(currentConfiguration$ | async) === workflowType"
2222
></ds-my-dspace-bulk-action>
2323
<ds-my-dspace-new-bulk-import additionalSearchFormOptions></ds-my-dspace-new-bulk-import>
2424
</ds-search>

src/app/shared/object-collection/object-collection.component.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
[showPaginator]="showPaginator"
1313
[showThumbnails]="showThumbnails"
1414
[showCorrection]="showCorrection"
15+
[showWorkflowStatistics]="showWorkflowStatistics"
1516
(paginationChange)="onPaginationChange($event)"
1617
(pageChange)="onPageChange($event)"
1718
(pageSizeChange)="onPageSizeChange($event)"
@@ -43,6 +44,7 @@
4344
[showMetrics]="showMetrics"
4445
[showPaginator]="showPaginator"
4546
[showThumbnails]="showThumbnails"
47+
[showWorkflowStatistics]="showWorkflowStatistics"
4648
(paginationChange)="onPaginationChange($event)"
4749
(pageChange)="onPageChange($event)"
4850
(pageSizeChange)="onPageSizeChange($event)"
@@ -62,6 +64,7 @@
6264
[showMetrics]="showMetrics"
6365
[showPaginator]="showPaginator"
6466
[showThumbnails]="showThumbnails"
67+
[showWorkflowStatistics]="showWorkflowStatistics"
6568
(contentChange)="contentChange.emit($event)"
6669
*ngIf="(currentMode$ | async) === viewModeEnum.DetailedListElement">
6770
</ds-object-detail>

src/app/shared/object-collection/object-collection.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ export class ObjectCollectionComponent implements OnInit {
135135
*/
136136
@Input() showCorrection = false;
137137

138+
/**
139+
* A boolean representing if to show workflow statistics
140+
*/
141+
@Input() showWorkflowStatistics;
142+
138143
/**
139144
* Whether or not to show an alert for hidden related items
140145
*/
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<div *ngIf="canViewInWorkflowSinceStatistics$ | async" >
2+
<div *ngIf="canViewInWorkflowForDate$ | async">
3+
{{'mydspace.results.in-workflow-for' | translate}} {{inWorkflowFor$ | async}}
4+
</div>
5+
<div *ngIf="canViewInWorkflowSinceDate$ | async">
6+
{{'mydspace.results.in-workflow-since' | translate}} {{inWorkflowSince$ | async}}
7+
</div>
8+
</div>

src/app/shared/object-collection/shared/in-workflow-statistics/in-workflow-statistics.component.scss

Whitespace-only changes.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import {
2+
Component,
3+
Input,
4+
OnInit,
5+
} from '@angular/core';
6+
import {
7+
differenceInDays,
8+
differenceInMilliseconds,
9+
parseISO,
10+
} from 'date-fns';
11+
import {
12+
BehaviorSubject,
13+
Observable,
14+
switchMap,
15+
} from 'rxjs';
16+
import {
17+
map,
18+
take,
19+
} from 'rxjs/operators';
20+
21+
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
22+
import { FeatureID } from '../../../../core/data/feature-authorization/feature-id';
23+
import { ItemDataService } from '../../../../core/data/item-data.service';
24+
import { Item } from '../../../../core/shared/item.model';
25+
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
26+
import { hasValue } from '../../../empty.util';
27+
28+
@Component({
29+
selector: 'ds-in-workflow-statistics',
30+
templateUrl: './in-workflow-statistics.component.html',
31+
styleUrls: ['./in-workflow-statistics.component.scss'],
32+
})
33+
export class InWorkflowStatisticsComponent implements OnInit {
34+
35+
@Input() item: Item;
36+
37+
canViewInWorkflowSinceStatistics$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
38+
canViewInWorkflowForDate$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
39+
canViewInWorkflowSinceDate$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
40+
inWorkflowFor$: BehaviorSubject<string> = new BehaviorSubject<string>(null);
41+
inWorkflowSince$: BehaviorSubject<string> = new BehaviorSubject<string>(null);
42+
43+
constructor(
44+
private authorizationService: AuthorizationDataService,
45+
private itemDataService: ItemDataService,
46+
) {
47+
}
48+
49+
ngOnInit(): void {
50+
this.canViewInWorkflowSinceStatistics().pipe(take(1))
51+
.subscribe((result: boolean) => {
52+
if (result) {
53+
this.initWorkflowDates();
54+
}
55+
this.canViewInWorkflowSinceStatistics$.next(result);
56+
});
57+
}
58+
59+
public canViewInWorkflowSinceStatistics(): Observable<boolean> {
60+
if (hasValue(this.item?.self)) {
61+
return this.isUserAuthorizedToViewItemInWorkflow(this.item.self);
62+
} else {
63+
// If self link has no value we fetch again the item from the rest.
64+
// Since at this stage the item has most likely already been fetched we will get it from the cache
65+
return this.itemDataService.findById(this.item.id).pipe(
66+
getFirstCompletedRemoteData(),
67+
map(data => data.payload.self),
68+
switchMap(selfLink => this.isUserAuthorizedToViewItemInWorkflow(selfLink)),
69+
);
70+
}
71+
}
72+
73+
public getDateForArchivedItem(itemStartDate: string, dateAccessioned: string) {
74+
const itemStartDateConverted: Date = parseISO(itemStartDate);
75+
const dateAccessionedConverted: Date = parseISO(dateAccessioned);
76+
const days: number = Math.max(0, Math.floor(differenceInDays(dateAccessionedConverted, itemStartDateConverted)));
77+
const remainingMilliseconds: number = differenceInMilliseconds(dateAccessionedConverted, itemStartDateConverted) - days * 24 * 60 * 60 * 1000;
78+
const hours: number = Math.max(0, Math.floor(remainingMilliseconds / (60 * 60 * 1000)));
79+
return `${days} d ${hours} h`;
80+
}
81+
82+
public getDateForItem(itemStartDate: string) {
83+
const itemStartDateConverted: Date = parseISO(itemStartDate);
84+
const days: number = Math.max(0, Math.floor(differenceInDays(Date.now(), itemStartDateConverted)));
85+
const remainingMilliseconds: number = differenceInMilliseconds(Date.now(), itemStartDateConverted) - days * 24 * 60 * 60 * 1000;
86+
const hours: number = Math.max(0, Math.floor(remainingMilliseconds / (60 * 60 * 1000)));
87+
return `${days} d ${hours} h`;
88+
}
89+
90+
initWorkflowDates(): void {
91+
if (this.item) {
92+
if (this.item.isArchived) {
93+
if (this.item.hasMetadata('dspace.workflow.startDateTime') && this.item.hasMetadata('dc.date.accessioned')) {
94+
this.canViewInWorkflowForDate$.next(true);
95+
this.inWorkflowFor$.next(
96+
this.getDateForArchivedItem(this.item.firstMetadataValue('dspace.workflow.startDateTime'), this.item.firstMetadataValue('dc.date.accessioned')),
97+
);
98+
}
99+
} else if (this.item.hasMetadata('dspace.workflow.startDateTime')) {
100+
this.canViewInWorkflowSinceDate$.next(true);
101+
this.inWorkflowSince$.next(
102+
this.getDateForItem(this.item.firstMetadataValue('dspace.workflow.startDateTime')),
103+
);
104+
}
105+
}
106+
}
107+
108+
private isUserAuthorizedToViewItemInWorkflow(selfLink: string): Observable<boolean> {
109+
return this.authorizationService.isAuthorized(FeatureID.CanViewInWorkflowSinceStatistics, selfLink);
110+
}
111+
}

src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges
8585
*/
8686
@Input() showCorrection = false;
8787

88+
/**
89+
* A boolean representing if to show workflow statistics
90+
*/
91+
@Input() showWorkflowStatistics: boolean;
92+
8893
/**
8994
* The value to display for this element
9095
*/
@@ -139,6 +144,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges
139144
'showMetrics',
140145
'showThumbnails',
141146
'showCorrection',
147+
'showWorkflowStatistics',
142148
'context',
143149
'viewMode',
144150
'value',

src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ export class AbstractListableElementComponent<T extends ListableObject> {
5757
*/
5858
@Input() showThumbnails: boolean;
5959

60+
/**
61+
* A boolean representing if to show workflow statistics
62+
*/
63+
@Input() showWorkflowStatistics = false;
64+
6065
/**
6166
* The context we matched on to get this component
6267
*/

src/app/shared/object-detail/object-detail.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
[showLabel]="showLabel"
2424
[showMetrics]="showMetrics"
2525
[showThumbnails]="showThumbnails"
26+
[showWorkflowStatistics]="showWorkflowStatistics"
2627
(contentChange)="contentChange.emit($event)"></ds-listable-object-component-loader>
2728
</div>
2829
</div>

0 commit comments

Comments
 (0)