Skip to content

Commit 7f699eb

Browse files
nsemetsrnastyuk
andauthored
Feat/247 view forks (#252)
* feat(view-forks): added view forks feature * feat(view-forks): fixed paginator condition * feat(view-forks): fixed navigation issues after merging with main * feat(view-forks): removed back to analytics button * feat(view-forks): comment out pre-push * feat(view-forks): fixed styled citation bug * feat(view-forks): fixed comments * feat(view-forks): fixed delete fork dialog error * feat(view-forks): fixed node links * feat(view-forks): fixed node link api issues * feat(view-forks): fixed errors after merging --------- Co-authored-by: Roman Nastyuk <rnastyuk@exoft.net>
1 parent baa8ef9 commit 7f699eb

File tree

55 files changed

+862
-235
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+862
-235
lines changed

.husky/pre-push

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ npm run test:check-coverage-thresholds || {
1616
printf "\n\nYou are seeing this error because test coverage increased without updating the jest.config.js thresholds."
1717
#printf "\n\nPlease address them before proceeding.\n\n\n\n"
1818
# exit 1
19-
}
19+
}

src/app/features/moderation/enums/submission-review-status.enum.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export enum SubmissionReviewStatus {
22
Pending = 'pending',
3+
InProgress = 'in_progress',
34
Accepted = 'accepted',
45
Rejected = 'rejected',
56
Withdrawn = 'withdrawn',

src/app/features/project/analytics/analytics.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
[value]="relatedCounts()?.forksCount"
7171
[showButton]="true"
7272
[buttonLabel]="'project.analytics.kpi.viewForks'"
73+
(buttonClick)="navigateToDuplicates()"
7374
></osf-analytics-kpi>
7475

7576
<osf-analytics-kpi

src/app/features/project/analytics/analytics.component.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import { SelectModule } from 'primeng/select';
77
import { map, of } from 'rxjs';
88

99
import { CommonModule, DatePipe } from '@angular/common';
10-
import { ChangeDetectionStrategy, Component, inject, OnInit, Signal, signal } from '@angular/core';
10+
import { ChangeDetectionStrategy, Component, DestroyRef, inject, OnInit, Signal, signal } from '@angular/core';
1111
import { toSignal } from '@angular/core/rxjs-interop';
1212
import { FormsModule } from '@angular/forms';
13-
import { ActivatedRoute } from '@angular/router';
13+
import { ActivatedRoute, Router } from '@angular/router';
1414

1515
import { BarChartComponent, LineChartComponent, PieChartComponent, SubHeaderComponent } from '@osf/shared/components';
1616
import { ResourceType } from '@osf/shared/enums';
@@ -20,7 +20,7 @@ import { DatasetInput } from '@osf/shared/models';
2020
import { AnalyticsKpiComponent } from './components';
2121
import { DATE_RANGE_OPTIONS } from './constants';
2222
import { DateRangeOption } from './models';
23-
import { AnalyticsSelectors, GetMetrics, GetRelatedCounts } from './store';
23+
import { AnalyticsSelectors, ClearAnalytics, GetMetrics, GetRelatedCounts } from './store';
2424
import { analyticsData } from './test-data';
2525

2626
@Component({
@@ -49,6 +49,8 @@ export class AnalyticsComponent implements OnInit {
4949

5050
private readonly datePipe = inject(DatePipe);
5151
private readonly route = inject(ActivatedRoute);
52+
private readonly router = inject(Router);
53+
private readonly destroyRef = inject(DestroyRef);
5254

5355
readonly resourceId = toSignal(this.route.parent?.params.pipe(map((params) => params['id'])) ?? of(undefined));
5456
readonly resourceType: Signal<ResourceType | undefined> = toSignal(
@@ -63,7 +65,11 @@ export class AnalyticsComponent implements OnInit {
6365

6466
protected isMetricsError = select(AnalyticsSelectors.isMetricsError);
6567

66-
protected actions = createDispatchMap({ getMetrics: GetMetrics, getRelatedCounts: GetRelatedCounts });
68+
protected actions = createDispatchMap({
69+
getMetrics: GetMetrics,
70+
getRelatedCounts: GetRelatedCounts,
71+
clearAnalytics: ClearAnalytics,
72+
});
6773

6874
protected visitsLabels: string[] = [];
6975
protected visitsDataset: DatasetInput[] = [];
@@ -83,6 +89,16 @@ export class AnalyticsComponent implements OnInit {
8389
this.setData();
8490
}
8591

92+
constructor() {
93+
this.setupCleanup();
94+
}
95+
96+
setupCleanup(): void {
97+
this.destroyRef.onDestroy(() => {
98+
this.actions.clearAnalytics();
99+
});
100+
}
101+
86102
onRangeChange(range: DateRangeOption) {
87103
this.selectedRange.set(range);
88104
this.actions.getMetrics(this.resourceId(), range.value);
@@ -107,4 +123,8 @@ export class AnalyticsComponent implements OnInit {
107123
this.popularPagesLabels = analytics.popularPages.map((item) => item.title);
108124
this.popularPagesDataset = [{ label: 'Popular pages', data: analytics.popularPages.map((item) => item.count) }];
109125
}
126+
127+
protected navigateToDuplicates() {
128+
this.router.navigate(['duplicates'], { relativeTo: this.route });
129+
}
110130
}

src/app/features/project/analytics/components/analytics-kpi/analytics-kpi.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
@if (showButton()) {
1111
<div>
12-
<p-button severity="secondary" [label]="buttonLabel() | translate"> </p-button>
12+
<p-button severity="secondary" [label]="buttonLabel() | translate" (onClick)="buttonClick.emit()"> </p-button>
1313
</div>
1414
}
1515
</div>

src/app/features/project/analytics/components/analytics-kpi/analytics-kpi.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { TranslatePipe } from '@ngx-translate/core';
33
import { Button } from 'primeng/button';
44
import { Skeleton } from 'primeng/skeleton';
55

6-
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
6+
import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';
77

88
@Component({
99
selector: 'osf-analytics-kpi',
@@ -18,4 +18,5 @@ export class AnalyticsKpiComponent {
1818
buttonLabel = input<string>('');
1919
title = input<string>('');
2020
value = input<number | undefined>(0);
21+
buttonClick = output<void>();
2122
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { AnalyticsKpiComponent } from './analytics-kpi/analytics-kpi.component';
2+
export { ViewDuplicatesComponent } from './view-duplicates/view-duplicates.component';
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<osf-sub-header
2+
[title]="'project.analytics.kpi.forks' | translate"
3+
[showButton]="true"
4+
[buttonLabel]="'project.overview.actions.forkProjectLabel' | translate"
5+
(buttonClick)="handleForkResource()"
6+
/>
7+
8+
<div class="flex flex-column flex-1 bg-white gap-5 p-3 sm:p-4">
9+
@if (!isDuplicatesLoading() && currentResource()) {
10+
@if (!duplicates().length) {
11+
<h3 class="mt-5 text-center">{{ 'project.overview.dialog.fork.noForksMessage' | translate }}</h3>
12+
} @else {
13+
<p>{{ 'project.overview.dialog.fork.forksMessage' | translate }}</p>
14+
15+
@for (duplicate of duplicates(); track duplicate.id) {
16+
@if (duplicate.currentUserPermissions.includes(UserPermissions.Read)) {
17+
<div class="duplicate-wrapper flex flex-column gap-3 p-3 sm:p-4">
18+
<div class="flex justify-content-between align-items-center">
19+
<h2 class="flex gap-2">
20+
<i [ngClass]="duplicate.public ? 'osf-icon-padlock-unlock' : 'osf-icon-padlock'"></i>
21+
{{ duplicate.title }}
22+
</h2>
23+
<div>
24+
@if (duplicate.currentUserPermissions.includes(UserPermissions.Write)) {
25+
<p-button
26+
severity="contrast"
27+
icon="fas fa-ellipsis-vertical"
28+
raised
29+
variant="outlined"
30+
(click)="componentActionMenu.toggle($event)"
31+
>
32+
</p-button>
33+
}
34+
35+
<p-menu appendTo="body" #componentActionMenu [model]="forkActionItems(duplicate.id)" popup>
36+
<ng-template #item let-item>
37+
<a class="p-menu-item-link">{{ item.label | translate }}</a>
38+
</ng-template>
39+
</p-menu>
40+
</div>
41+
</div>
42+
43+
<div class="component-name flex flex-column gap-2">
44+
<div class="flex flex-wrap align-items-center gap-1">
45+
<span class="font-bold">{{ 'common.labels.forked' | translate }}:</span>
46+
<p>{{ duplicate.dateCreated | date: 'MMM d, y, h:mm a' }}</p>
47+
</div>
48+
49+
<div class="flex flex-wrap align-items-center gap-1">
50+
<span class="font-bold">{{ 'common.labels.lastUpdated' | translate }}:</span>
51+
<p>{{ duplicate.dateModified | date: 'MMM d, y, h:mm a' }}</p>
52+
</div>
53+
54+
<div class="flex flex-wrap align-items-center gap-1">
55+
<span class="font-bold">{{ 'common.labels.contributors' | translate }}:</span>
56+
@for (contributor of duplicate.contributors; track contributor.id) {
57+
<div>
58+
<a [href]="contributor.id" target="_blank" class="font-bold"> {{ contributor.fullName }}</a>
59+
<span>{{ $last ? '' : ',' }}</span>
60+
</div>
61+
}
62+
</div>
63+
64+
<div class="component-description">
65+
<div class="flex flex-wrap align-items-center gap-1">
66+
<span class="font-bold">{{ 'common.labels.description' | translate }}:</span>
67+
<osf-truncated-text [text]="duplicate.description" />
68+
</div>
69+
</div>
70+
</div>
71+
<p-button
72+
[label]="'common.buttons.view' | translate"
73+
severity="secondary"
74+
[routerLink]="'/project/' + duplicate.id"
75+
/>
76+
</div>
77+
}
78+
}
79+
80+
@if (totalDuplicates() > pageSize) {
81+
<osf-custom-paginator
82+
[totalCount]="totalDuplicates()"
83+
[rows]="pageSize"
84+
[first]="firstIndex()"
85+
(pageChanged)="onPageChange($event)"
86+
/>
87+
}
88+
}
89+
} @else {
90+
<osf-loading-spinner></osf-loading-spinner>
91+
}
92+
</div>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
@use "assets/styles/variables" as var;
2+
@use "assets/styles/mixins" as mix;
3+
4+
:host {
5+
display: flex;
6+
flex-direction: column;
7+
flex: 1;
8+
}
9+
10+
.duplicate-wrapper {
11+
border: 1px solid var.$grey-2;
12+
border-radius: mix.rem(12px);
13+
color: var.$dark-blue-1;
14+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { ViewDuplicatesComponent } from './view-duplicates.component';
4+
5+
describe.skip('ViewForksComponent', () => {
6+
let component: ViewDuplicatesComponent;
7+
let fixture: ComponentFixture<ViewDuplicatesComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
imports: [ViewDuplicatesComponent],
12+
}).compileComponents();
13+
14+
fixture = TestBed.createComponent(ViewDuplicatesComponent);
15+
component = fixture.componentInstance;
16+
fixture.detectChanges();
17+
});
18+
19+
it('should create', () => {
20+
expect(component).toBeTruthy();
21+
});
22+
});

0 commit comments

Comments
 (0)