Skip to content

Commit cc309be

Browse files
authored
[ENG-9632] Optimize project initial load (#749)
- Ticket: [ENG-9632] - Feature flag: n/a ## Summary of Changes 1. Optimized initial loading for project overview. 2. Updated meta tags for project. 3. Add unit tests.
1 parent 5bf7d6c commit cc309be

File tree

91 files changed

+2043
-1257
lines changed

Some content is hidden

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

91 files changed

+2043
-1257
lines changed

jest.config.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,8 @@ module.exports = {
6969
testPathIgnorePatterns: [
7070
'<rootDir>/src/environments',
7171
'<rootDir>/src/app/app.config.ts',
72-
'<rootDir>/src/app/app.routes.ts',
7372
'<rootDir>/src/app/features/files/pages/file-detail',
7473
'<rootDir>/src/app/features/project/addons/',
75-
'<rootDir>/src/app/features/project/overview/',
7674
'<rootDir>/src/app/features/project/registrations',
7775
'<rootDir>/src/app/features/project/wiki',
7876
'<rootDir>/src/app/features/registry/components',

src/app/core/constants/ngxs-states.constant.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { UserEmailsState } from '@core/store/user-emails';
44
import { InstitutionsAdminState } from '@osf/features/admin-institutions/store';
55
import { FilesState } from '@osf/features/files/store';
66
import { MetadataState } from '@osf/features/metadata/store';
7-
import { ProjectOverviewState } from '@osf/features/project/overview/store';
87
import { AddonsState } from '@osf/shared/stores/addons';
98
import { BannersState } from '@osf/shared/stores/banners';
109
import { ContributorsState } from '@osf/shared/stores/contributors';
@@ -26,7 +25,6 @@ export const STATES = [
2625
InstitutionsState,
2726
InstitutionsAdminState,
2827
InstitutionsSearchState,
29-
ProjectOverviewState,
3028
WikiState,
3129
LicensesState,
3230
RegionsState,

src/app/core/services/help-scout.service.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('HelpScoutService', () => {
1414
if (selector === UserSelectors.isAuthenticated) {
1515
return authSignal;
1616
}
17-
return signal(null); // fallback
17+
return signal(null);
1818
}),
1919
};
2020
let service: HelpScoutService;

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { ViewOnlyLinkMessageComponent } from '@osf/shared/components/view-only-l
1717
import { IS_WEB } from '@osf/shared/helpers/breakpoints.tokens';
1818

1919
import { MOCK_ANALYTICS_METRICS, MOCK_RELATED_COUNTS } from '@testing/mocks/analytics.mock';
20-
import { MOCK_RESOURCE_OVERVIEW } from '@testing/mocks/resource.mock';
2120
import { OSFTestingModule } from '@testing/osf.testing.module';
2221
import { ActivatedRouteMockBuilder } from '@testing/providers/route-provider.mock';
2322
import { RouterMockBuilder } from '@testing/providers/router-provider.mock';
@@ -29,7 +28,7 @@ describe('Component: Analytics', () => {
2928
let routerMock: ReturnType<RouterMockBuilder['build']>;
3029
let activatedRouteMock: ReturnType<ActivatedRouteMockBuilder['build']>;
3130

32-
const resourceId = MOCK_RESOURCE_OVERVIEW.id;
31+
const resourceId = 'ex212';
3332
const metrics = { ...MOCK_ANALYTICS_METRICS, id: resourceId };
3433
const relatedCounts = { ...MOCK_RELATED_COUNTS, id: resourceId };
3534
const metricsSelector = AnalyticsSelectors.getMetrics(resourceId);
@@ -60,13 +59,6 @@ describe('Component: Analytics', () => {
6059
],
6160
providers: [
6261
provideMockStore({
63-
selectors: [
64-
{ selector: metricsSelector, value: metrics },
65-
{ selector: relatedCountsSelector, value: relatedCounts },
66-
{ selector: AnalyticsSelectors.isMetricsLoading, value: false },
67-
{ selector: AnalyticsSelectors.isRelatedCountsLoading, value: false },
68-
{ selector: AnalyticsSelectors.isMetricsError, value: false },
69-
],
7062
signals: [
7163
{ selector: metricsSelector, value: metrics },
7264
{ selector: relatedCountsSelector, value: relatedCounts },

src/app/features/analytics/components/view-duplicates/view-duplicates.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ <h2 class="flex align-items-center gap-2">
5959
<p>{{ duplicate.dateModified | date: 'MMM d, y, h:mm a' }}</p>
6060
</div>
6161

62-
<div class="flex flex-wrap align-items-center gap-1">
62+
<div class="flex align-items-start gap-1">
6363
<span class="font-bold">{{ 'common.labels.contributors' | translate }}:</span>
6464

6565
<osf-contributors-list [contributors]="duplicate.bibliographicContributors ?? []"></osf-contributors-list>

src/app/features/analytics/components/view-duplicates/view-duplicates.component.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ describe('Component: View Duplicates', () => {
100100
it('should update currentPage when page is defined', () => {
101101
const event: PaginatorState = { page: 1 } as PaginatorState;
102102
component.onPageChange(event);
103-
expect(component.currentPage()).toBe('2');
103+
expect(component.currentPage()).toBe(2);
104104
});
105105

106106
it('should not update currentPage when page is undefined', () => {
107-
component.currentPage.set('5');
107+
component.currentPage.set(5);
108108
const event: PaginatorState = { page: undefined } as PaginatorState;
109109
component.onPageChange(event);
110-
expect(component.currentPage()).toBe('5');
110+
expect(component.currentPage()).toBe(5);
111111
});
112112
});

src/app/features/analytics/components/view-duplicates/view-duplicates.component.ts

Lines changed: 16 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import { toSignal } from '@angular/core/rxjs-interop';
2323
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
2424

2525
import { UserSelectors } from '@core/store/user';
26-
import { DeleteComponentDialogComponent, ForkDialogComponent } from '@osf/features/project/overview/components';
26+
import { DeleteComponentDialogComponent } from '@osf/features/project/overview/components/delete-component-dialog/delete-component-dialog.component';
27+
import { ForkDialogComponent } from '@osf/features/project/overview/components/fork-dialog/fork-dialog.component';
2728
import { ClearProjectOverview, GetProjectById, ProjectOverviewSelectors } from '@osf/features/project/overview/store';
2829
import { ClearRegistry, GetRegistryById, RegistrySelectors } from '@osf/features/registry/store/registry';
2930
import { ContributorsListComponent } from '@osf/shared/components/contributors-list/contributors-list.component';
@@ -39,23 +40,21 @@ import { LoaderService } from '@osf/shared/services/loader.service';
3940
import { GetResourceWithChildren } from '@osf/shared/stores/current-resource';
4041
import { ClearDuplicates, DuplicatesSelectors, GetAllDuplicates } from '@osf/shared/stores/duplicates';
4142
import { BaseNodeModel } from '@shared/models/nodes/base-node.model';
42-
import { ToolbarResource } from '@shared/models/toolbar-resource.model';
4343

4444
@Component({
4545
selector: 'osf-view-duplicates',
4646
imports: [
47-
SubHeaderComponent,
48-
TranslatePipe,
4947
Button,
5048
Menu,
49+
RouterLink,
50+
IconComponent,
51+
SubHeaderComponent,
5152
TruncatedTextComponent,
52-
DatePipe,
5353
LoadingSpinnerComponent,
54-
RouterLink,
5554
CustomPaginatorComponent,
56-
IconComponent,
5755
ContributorsListComponent,
5856
DatePipe,
57+
TranslatePipe,
5958
],
6059
templateUrl: './view-duplicates.component.html',
6160
styleUrl: './view-duplicates.component.scss',
@@ -69,8 +68,6 @@ export class ViewDuplicatesComponent {
6968
private destroyRef = inject(DestroyRef);
7069
private project = select(ProjectOverviewSelectors.getProject);
7170
private registration = select(RegistrySelectors.getRegistry);
72-
private isProjectAnonymous = select(ProjectOverviewSelectors.isProjectAnonymous);
73-
private isRegistryAnonymous = select(RegistrySelectors.isRegistryAnonymous);
7471

7572
duplicates = select(DuplicatesSelectors.getDuplicates);
7673
isDuplicatesLoading = select(DuplicatesSelectors.getDuplicatesLoading);
@@ -80,8 +77,8 @@ export class ViewDuplicatesComponent {
8077
readonly pageSize = 10;
8178
readonly UserPermissions = UserPermissions;
8279

83-
currentPage = signal<string>('1');
84-
firstIndex = computed(() => (parseInt(this.currentPage()) - 1) * this.pageSize);
80+
currentPage = signal<number>(1);
81+
firstIndex = computed(() => (this.currentPage() - 1) * this.pageSize);
8582

8683
readonly forkActionItems = (resourceId: string) => [
8784
{
@@ -142,33 +139,13 @@ export class ViewDuplicatesComponent {
142139
const resource = this.currentResource();
143140

144141
if (resource) {
145-
this.actions.getDuplicates(resource.id, resource.type, parseInt(this.currentPage()), this.pageSize);
142+
this.actions.getDuplicates(resource.id, resource.type, this.currentPage(), this.pageSize);
146143
}
147144
});
148145

149146
this.setupCleanup();
150147
}
151148

152-
toolbarResource = computed(() => {
153-
const resource = this.currentResource();
154-
const resourceType = this.resourceType();
155-
if (resource && resourceType) {
156-
const isAnonymous =
157-
resourceType === ResourceType.Project ? this.isProjectAnonymous() : this.isRegistryAnonymous();
158-
159-
return {
160-
id: resource.id,
161-
isPublic: resource.isPublic,
162-
storage: undefined,
163-
viewOnlyLinksCount: 0,
164-
forksCount: resource.forksCount,
165-
resourceType: resourceType,
166-
isAnonymous,
167-
} as ToolbarResource;
168-
}
169-
return null;
170-
});
171-
172149
showMoreOptions(duplicate: BaseNodeModel) {
173150
return (
174151
duplicate.currentUserPermissions.includes(UserPermissions.Admin) ||
@@ -191,32 +168,29 @@ export class ViewDuplicatesComponent {
191168
}
192169

193170
handleForkResource(): void {
194-
const toolbarResource = this.toolbarResource();
171+
const currentResource = this.currentResource();
195172

196-
if (toolbarResource) {
173+
if (currentResource) {
197174
this.customDialogService
198175
.open(ForkDialogComponent, {
199176
header: 'project.overview.dialog.fork.headerProject',
200177
width: '450px',
201178
data: {
202-
resource: toolbarResource,
179+
resourceId: currentResource.id,
203180
resourceType: this.resourceType(),
204181
},
205182
})
206183
.onClose.subscribe((result) => {
207184
if (result?.success) {
208-
const resource = this.currentResource();
209-
if (resource) {
210-
this.actions.getDuplicates(resource.id, resource.type, parseInt(this.currentPage()), this.pageSize);
211-
}
185+
this.actions.getDuplicates(currentResource.id, currentResource.type, this.currentPage(), this.pageSize);
212186
}
213187
});
214188
}
215189
}
216190

217191
onPageChange(event: PaginatorState): void {
218192
if (event.page !== undefined) {
219-
const pageNumber = (event.page + 1).toString();
193+
const pageNumber = event.page + 1;
220194
this.currentPage.set(pageNumber);
221195
}
222196
}
@@ -246,15 +220,15 @@ export class ViewDuplicatesComponent {
246220
componentId: id,
247221
resourceType: resourceType,
248222
isForksContext: true,
249-
currentPage: parseInt(this.currentPage()),
223+
currentPage: this.currentPage(),
250224
pageSize: this.pageSize,
251225
},
252226
})
253227
.onClose.subscribe((result) => {
254228
if (result?.success) {
255229
const resource = this.currentResource();
256230
if (resource) {
257-
this.actions.getDuplicates(resource.id, resource.type, parseInt(this.currentPage()), this.pageSize);
231+
this.actions.getDuplicates(resource.id, resource.type, this.currentPage(), this.pageSize);
258232
}
259233
}
260234
});

src/app/features/analytics/components/view-linked-projects/view-linked-projects.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ <h2 class="flex align-items-center gap-2">
2727
<p>{{ duplicate.dateModified | date: 'MMM d, y, h:mm a' }}</p>
2828
</div>
2929

30-
<div class="flex flex-wrap align-items-center gap-1">
30+
<div class="flex align-items-start gap-1">
3131
<span class="font-bold">{{ 'common.labels.contributors' | translate }}:</span>
3232

3333
<osf-contributors-list [contributors]="duplicate.bibliographicContributors ?? []"></osf-contributors-list>

src/app/features/analytics/components/view-linked-projects/view-linked-projects.component.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ describe('Component: View Duplicates', () => {
7474
it('should update currentPage when page is defined', () => {
7575
const event: PaginatorState = { page: 1 } as PaginatorState;
7676
component.onPageChange(event);
77-
expect(component.currentPage()).toBe('2');
77+
expect(component.currentPage()).toBe(2);
7878
});
7979

8080
it('should not update currentPage when page is undefined', () => {
81-
component.currentPage.set('5');
81+
component.currentPage.set(5);
8282
const event: PaginatorState = { page: undefined } as PaginatorState;
8383
component.onPageChange(event);
84-
expect(component.currentPage()).toBe('5');
84+
expect(component.currentPage()).toBe(5);
8585
});
8686
});

src/app/features/analytics/components/view-linked-projects/view-linked-projects.component.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ export class ViewLinkedProjectsComponent {
6363

6464
readonly pageSize = 10;
6565

66-
currentPage = signal<string>('1');
67-
firstIndex = computed(() => (parseInt(this.currentPage()) - 1) * this.pageSize);
66+
currentPage = signal<number>(1);
67+
firstIndex = computed(() => this.currentPage() - 1 * this.pageSize);
6868

6969
readonly resourceId = toSignal(this.route.parent?.params.pipe(map((params) => params['id'])) ?? of(undefined));
7070
readonly resourceType: Signal<ResourceType | undefined> = toSignal(
@@ -107,7 +107,7 @@ export class ViewLinkedProjectsComponent {
107107
const resource = this.currentResource();
108108

109109
if (resource) {
110-
this.actions.getLinkedProjects(resource.id, resource.type, parseInt(this.currentPage()), this.pageSize);
110+
this.actions.getLinkedProjects(resource.id, resource.type, this.currentPage(), this.pageSize);
111111
}
112112
});
113113

@@ -116,7 +116,7 @@ export class ViewLinkedProjectsComponent {
116116

117117
onPageChange(event: PaginatorState): void {
118118
if (event.page !== undefined) {
119-
const pageNumber = (event.page + 1).toString();
119+
const pageNumber = event.page + 1;
120120
this.currentPage.set(pageNumber);
121121
}
122122
}

0 commit comments

Comments
 (0)