Skip to content

Commit da9d9dd

Browse files
atarix83Andrea Barbasso
authored andcommitted
[DSC-2354] Optimize in-workflow statistics visualization
# Conflicts: # src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts # src/app/my-dspace-page/my-dspace-page.component.html # src/app/shared/object-collection/object-collection.component.html # src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts # src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component.html # src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component.html # src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-task-search-result/claimed-declined-task-search-result-list-element.component.html # src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.html # src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts # src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component.ts # src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.html # src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.html # src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.html # src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.html # src/app/shared/object-list/object-list.component.html # src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html # src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts # src/app/shared/object-list/themed-object-list.component.ts # src/app/shared/search/search-results/search-results.component.html # src/app/shared/search/search-results/themed-search-results.component.ts # src/app/shared/search/search.component.ts # src/app/shared/search/themed-search.component.ts # src/app/shared/shared.module.ts
1 parent bf4e02d commit da9d9dd

35 files changed

Lines changed: 222 additions & 69 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
@@ -41,4 +41,5 @@ export enum FeatureID {
4141
EPersonForgotPassword = 'epersonForgotPassword',
4242
ShowClaimItem = 'showClaimItem',
4343
CanCorrectItem = 'canCorrectItem',
44+
CanViewInWorkflowSinceStatistics = 'canViewInWorkflowSinceStatistics',
4445
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
[selectable]="(currentConfiguration$ | async) === workflowType"
1414
[selectionConfig]="{ repeatable: true, listId: listId }"
1515
(deselectObject)="onDeselectObject($event)"
16-
(selectObject)="onSelectObject($event)">
16+
(selectObject)="onSelectObject($event)"
17+
[showWorkflowStatistics]="true">
1718
<!-- Using *ngIf breaks the projection, so we are using hidden instead -->
1819
<ds-my-dspace-bulk-action [hidden]="(currentConfiguration$ | async) !== workflowType"
1920
bulkActions

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
@@ -154,6 +154,11 @@ export class ObjectCollectionComponent implements OnInit {
154154
*/
155155
@Input() showCorrection = false;
156156

157+
/**
158+
* A boolean representing if to show workflow statistics
159+
*/
160+
@Input() showWorkflowStatistics;
161+
157162
/**
158163
* Whether or not to show an alert for hidden related items
159164
*/
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: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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+
standalone: true,
32+
styleUrls: ['./in-workflow-statistics.component.scss'],
33+
})
34+
export class InWorkflowStatisticsComponent implements OnInit {
35+
36+
@Input() item: Item;
37+
38+
canViewInWorkflowSinceStatistics$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
39+
canViewInWorkflowForDate$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
40+
canViewInWorkflowSinceDate$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
41+
inWorkflowFor$: BehaviorSubject<string> = new BehaviorSubject<string>(null);
42+
inWorkflowSince$: BehaviorSubject<string> = new BehaviorSubject<string>(null);
43+
44+
constructor(
45+
private authorizationService: AuthorizationDataService,
46+
private itemDataService: ItemDataService,
47+
) {
48+
}
49+
50+
ngOnInit(): void {
51+
this.canViewInWorkflowSinceStatistics().pipe(take(1))
52+
.subscribe((result: boolean) => {
53+
if (result) {
54+
this.initWorkflowDates();
55+
}
56+
this.canViewInWorkflowSinceStatistics$.next(result);
57+
});
58+
}
59+
60+
public canViewInWorkflowSinceStatistics(): Observable<boolean> {
61+
if (hasValue(this.item?.self)) {
62+
return this.isUserAuthorizedToViewItemInWorkflow(this.item.self);
63+
} else {
64+
// If self link has no value we fetch again the item from the rest.
65+
// Since at this stage the item has most likely already been fetched we will get it from the cache
66+
return this.itemDataService.findById(this.item.id).pipe(
67+
getFirstCompletedRemoteData(),
68+
map(data => data.payload.self),
69+
switchMap(selfLink => this.isUserAuthorizedToViewItemInWorkflow(selfLink)),
70+
);
71+
}
72+
}
73+
74+
public getDateForArchivedItem(itemStartDate: string, dateAccessioned: string) {
75+
const itemStartDateConverted: Date = parseISO(itemStartDate);
76+
const dateAccessionedConverted: Date = parseISO(dateAccessioned);
77+
const days: number = Math.max(0, Math.floor(differenceInDays(dateAccessionedConverted, itemStartDateConverted)));
78+
const remainingMilliseconds: number = differenceInMilliseconds(dateAccessionedConverted, itemStartDateConverted) - days * 24 * 60 * 60 * 1000;
79+
const hours: number = Math.max(0, Math.floor(remainingMilliseconds / (60 * 60 * 1000)));
80+
return `${days} d ${hours} h`;
81+
}
82+
83+
public getDateForItem(itemStartDate: string) {
84+
const itemStartDateConverted: Date = parseISO(itemStartDate);
85+
const days: number = Math.max(0, Math.floor(differenceInDays(Date.now(), itemStartDateConverted)));
86+
const remainingMilliseconds: number = differenceInMilliseconds(Date.now(), itemStartDateConverted) - days * 24 * 60 * 60 * 1000;
87+
const hours: number = Math.max(0, Math.floor(remainingMilliseconds / (60 * 60 * 1000)));
88+
return `${days} d ${hours} h`;
89+
}
90+
91+
initWorkflowDates(): void {
92+
if (this.item) {
93+
if (this.item.isArchived) {
94+
if (this.item.hasMetadata('dspace.workflow.startDateTime') && this.item.hasMetadata('dc.date.accessioned')) {
95+
this.canViewInWorkflowForDate$.next(true);
96+
this.inWorkflowFor$.next(
97+
this.getDateForArchivedItem(this.item.firstMetadataValue('dspace.workflow.startDateTime'), this.item.firstMetadataValue('dc.date.accessioned')),
98+
);
99+
}
100+
} else if (this.item.hasMetadata('dspace.workflow.startDateTime')) {
101+
this.canViewInWorkflowSinceDate$.next(true);
102+
this.inWorkflowSince$.next(
103+
this.getDateForItem(this.item.firstMetadataValue('dspace.workflow.startDateTime')),
104+
);
105+
}
106+
}
107+
}
108+
109+
private isUserAuthorizedToViewItemInWorkflow(selfLink: string): Observable<boolean> {
110+
return this.authorizationService.isAuthorized(FeatureID.CanViewInWorkflowSinceStatistics, selfLink);
111+
}
112+
}

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
@@ -80,6 +80,11 @@ export class ListableObjectComponentLoaderComponent extends AbstractComponentLoa
8080
*/
8181
@Input() showCorrection = false;
8282

83+
/**
84+
* A boolean representing if to show workflow statistics
85+
*/
86+
@Input() showWorkflowStatistics: boolean;
87+
8388
/**
8489
* The value to display for this element
8590
*/
@@ -130,6 +135,7 @@ export class ListableObjectComponentLoaderComponent extends AbstractComponentLoa
130135
'showMetrics',
131136
'showThumbnails',
132137
'showCorrection',
138+
'showWorkflowStatistics',
133139
'context',
134140
'viewMode',
135141
'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
@@ -64,6 +64,11 @@ export class AbstractListableElementComponent<T extends ListableObject> {
6464
*/
6565
@Input() showThumbnails: boolean;
6666

67+
/**
68+
* A boolean representing if to show workflow statistics
69+
*/
70+
@Input() showWorkflowStatistics = false;
71+
6772
/**
6873
* The context we matched on to get this component
6974
*/

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)