From ea912013771689f340c0a76f143d97c4677231d1 Mon Sep 17 00:00:00 2001 From: futa-ikeda Date: Tue, 25 Nov 2025 17:07:18 -0500 Subject: [PATCH 1/8] fix(preprints): Fix for preprint file upload bug --- .../store/preprint-stepper/preprint-stepper.state.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/app/features/preprints/store/preprint-stepper/preprint-stepper.state.ts b/src/app/features/preprints/store/preprint-stepper/preprint-stepper.state.ts index b3b3559f8..d915e5782 100644 --- a/src/app/features/preprints/store/preprint-stepper/preprint-stepper.state.ts +++ b/src/app/features/preprints/store/preprint-stepper/preprint-stepper.state.ts @@ -172,9 +172,14 @@ export class PreprintStepperState { ctx.setState(patch({ preprintFile: patch({ isLoading: true }) })); - return this.fileService - .updateFileContent(action.file, uploadedFile.links.upload) - .pipe(switchMap(() => this.fileService.renameEntry(uploadedFile.links.upload, action.file.name, 'replace'))); + return this.fileService.updateFileContent(action.file, uploadedFile.links.upload).pipe( + switchMap(() => { + if (uploadedFile.name !== action.file.name) { + return this.fileService.renameEntry(uploadedFile.links.upload, action.file.name, 'replace'); + } + return EMPTY; + }) + ); } @Action(FetchPreprintPrimaryFile) From 7187cffe8e4a28e6fcb8dab3b80fe0fe7a752d79 Mon Sep 17 00:00:00 2001 From: Yuhuai Liu Date: Tue, 2 Dec 2025 17:23:05 -0500 Subject: [PATCH 2/8] feat(forking): Change resourceType --- .../project-overview-toolbar.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.ts b/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.ts index 2ef801f41..812e20ef2 100644 --- a/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.ts +++ b/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.ts @@ -66,7 +66,7 @@ export class ProjectOverviewToolbarComponent { isPublic = signal(false); isBookmarked = signal(false); - resourceType = ResourceType.Registration; + resourceType = ResourceType.Project; bookmarksCollectionId = select(BookmarksSelectors.getBookmarksCollectionId); bookmarks = select(BookmarksSelectors.getBookmarks); From 6ace0becf138918288ad2d8cff01fc768325684a Mon Sep 17 00:00:00 2001 From: Yuhuai Liu Date: Wed, 3 Dec 2025 10:16:21 -0500 Subject: [PATCH 3/8] feat(project-overview-toolbar): fix test --- .../project-overview-toolbar.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts b/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts index 7bf548355..4e3da221d 100644 --- a/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts +++ b/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts @@ -179,7 +179,7 @@ describe('ProjectOverviewToolbarComponent', () => { }); it('should have resourceType set to Registration', () => { - expect(component.resourceType).toBe(ResourceType.Registration); + expect(component.resourceType).toBe(ResourceType.Project); }); }); }); From 55a424b34b7425b33c0c73f0bce5d2a832545ad2 Mon Sep 17 00:00:00 2001 From: Yuhuai Liu Date: Wed, 3 Dec 2025 10:30:19 -0500 Subject: [PATCH 4/8] Update src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts Co-authored-by: nsemets --- .../project-overview-toolbar.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts b/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts index 4e3da221d..76bfdb06a 100644 --- a/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts +++ b/src/app/features/project/overview/components/project-overview-toolbar/project-overview-toolbar.component.spec.ts @@ -178,7 +178,7 @@ describe('ProjectOverviewToolbarComponent', () => { expect(component.ResourceType).toBe(ResourceType); }); - it('should have resourceType set to Registration', () => { + it('should have resourceType set to Project', () => { expect(component.resourceType).toBe(ResourceType.Project); }); }); From 0cab0b18854c1def885af481294fe853484e8c4a Mon Sep 17 00:00:00 2001 From: Vlad0n20 Date: Fri, 5 Dec 2025 15:56:28 +0200 Subject: [PATCH 5/8] feat(admin-institutions): add last updated on institution summary tab --- .../institutions-summary.component.html | 7 +++ .../institutions-summary.component.scss | 18 +++++++ .../institutions-summary.component.ts | 10 +++- src/app/shared/pipes/report-date.pipe.spec.ts | 48 +++++++++++++++++ src/app/shared/pipes/report-date.pipe.ts | 51 +++++++++++++++++++ src/assets/i18n/en.json | 1 + 6 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/app/shared/pipes/report-date.pipe.spec.ts create mode 100644 src/app/shared/pipes/report-date.pipe.ts diff --git a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html index 750c68efb..3c6cf402a 100644 --- a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html +++ b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html @@ -4,6 +4,13 @@ } @else {
+ @if (summaryMetrics()?.reportYearmonth) { +
+ {{ 'adminInstitutions.summary.lastUpdated' | translate }}: + {{ summaryMetrics()!.reportYearmonth | reportDate }} +
+ } +
@for (item of statisticsData; track $index) { diff --git a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.scss b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.scss index c09d87014..ea03c6095 100644 --- a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.scss +++ b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.scss @@ -25,3 +25,21 @@ width: 100%; } } + +.last-updated-section { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; // 14px + color: var(--text-color-secondary); + padding: 0.75rem 0; + + .last-updated-label { + font-weight: 600; + } + + .last-updated-date { + color: var(--text-color); + font-weight: 500; + } +} diff --git a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.ts b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.ts index 4d89b1140..82ad52d3d 100644 --- a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.ts +++ b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.ts @@ -10,6 +10,7 @@ import { LoadingSpinnerComponent } from '@osf/shared/components/loading-spinner/ import { StatisticCardComponent } from '@osf/shared/components/statistic-card/statistic-card.component'; import { DatasetInput } from '@osf/shared/models/charts/dataset-input'; import { SelectOption } from '@osf/shared/models/select-option.model'; +import { ReportDatePipe } from '@osf/shared/pipes/report-date.pipe'; import { DoughnutChartComponent } from '@shared/components/doughnut-chart/doughnut-chart.component'; import { @@ -23,7 +24,14 @@ import { @Component({ selector: 'osf-institutions-summary', - imports: [StatisticCardComponent, LoadingSpinnerComponent, DoughnutChartComponent, BarChartComponent, TranslatePipe], + imports: [ + StatisticCardComponent, + LoadingSpinnerComponent, + DoughnutChartComponent, + BarChartComponent, + TranslatePipe, + ReportDatePipe, + ], templateUrl: './institutions-summary.component.html', styleUrl: './institutions-summary.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/src/app/shared/pipes/report-date.pipe.spec.ts b/src/app/shared/pipes/report-date.pipe.spec.ts new file mode 100644 index 000000000..efe087a72 --- /dev/null +++ b/src/app/shared/pipes/report-date.pipe.spec.ts @@ -0,0 +1,48 @@ +import { ReportDatePipe } from './report-date.pipe'; + +describe('ReportDatePipe', () => { + let pipe: ReportDatePipe; + + beforeEach(() => { + pipe = new ReportDatePipe(); + }); + + it('should create an instance', () => { + expect(pipe).toBeTruthy(); + }); + + it('should transform "2024-08" to "August 1, 2024"', () => { + expect(pipe.transform('2024-08')).toBe('August 1, 2024'); + }); + + it('should transform "2024-12" to "December 1, 2024"', () => { + expect(pipe.transform('2024-12')).toBe('December 1, 2024'); + }); + + it('should transform "2025-01" to "January 1, 2025"', () => { + expect(pipe.transform('2025-01')).toBe('January 1, 2025'); + }); + + it('should return empty string for null', () => { + expect(pipe.transform(null)).toBe(''); + }); + + it('should return empty string for undefined', () => { + expect(pipe.transform(undefined)).toBe(''); + }); + + it('should return empty string for empty string', () => { + expect(pipe.transform('')).toBe(''); + }); + + it('should return empty string for invalid format', () => { + expect(pipe.transform('invalid')).toBe(''); + expect(pipe.transform('2024')).toBe(''); + expect(pipe.transform('2024-')).toBe(''); + }); + + it('should return empty string for invalid month', () => { + expect(pipe.transform('2024-13')).toBe(''); + expect(pipe.transform('2024-00')).toBe(''); + }); +}); diff --git a/src/app/shared/pipes/report-date.pipe.ts b/src/app/shared/pipes/report-date.pipe.ts new file mode 100644 index 000000000..d64f89b80 --- /dev/null +++ b/src/app/shared/pipes/report-date.pipe.ts @@ -0,0 +1,51 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +/** + * Transforms a report yearmonth string from "YYYY-MM" format to "Month Day, Year" format + * Example: "2024-08" -> "August 1, 2024" + */ +@Pipe({ + name: 'reportDate', + standalone: true, +}) +export class ReportDatePipe implements PipeTransform { + private readonly monthNames = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + + transform(yearMonth: string | null | undefined): string { + if (!yearMonth) { + return ''; + } + + // Input format: "YYYY-MM" (e.g., "2024-08") + const [yearStr, monthStr] = yearMonth.split('-'); + + if (!yearStr || !monthStr) { + return ''; + } + + const year = parseInt(yearStr, 10); + const month = parseInt(monthStr, 10); + + if (isNaN(year) || isNaN(month) || month < 1 || month > 12) { + return ''; + } + + const monthName = this.monthNames[month - 1]; + + // Output format: "Month 1, Year" (e.g., "August 1, 2024") + return `${monthName} 1, ${year}`; + } +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index ba89a6abf..333c36e74 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -2836,6 +2836,7 @@ }, "summary": { "title": "Summary", + "lastUpdated": "Last Updated", "totalUsersByDepartment": "Total Users by Department", "publicPrivateProjects": "Public vs Private Projects", "publicEmbargoedRegistrations": "Public vs Embargoed Registrations", From aa3382c0e8a5985a96343fedb0a8d23b9fa138e5 Mon Sep 17 00:00:00 2001 From: Vlad0n20 Date: Mon, 8 Dec 2025 15:22:51 +0200 Subject: [PATCH 6/8] fix(admin-institutions): remove report-date pipe and use primeflex classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace custom ReportDatePipe with Angular's DatePipe - Remove custom SCSS styles in institutions-summary component - Use PrimeFlex utility classes for styling - Delete report-date.pipe.ts and its test file 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../institutions-summary.component.html | 22 ++++---- .../institutions-summary.component.scss | 40 --------------- .../institutions-summary.component.ts | 4 +- src/app/shared/pipes/report-date.pipe.spec.ts | 48 ----------------- src/app/shared/pipes/report-date.pipe.ts | 51 ------------------- 5 files changed, 13 insertions(+), 152 deletions(-) delete mode 100644 src/app/shared/pipes/report-date.pipe.spec.ts delete mode 100644 src/app/shared/pipes/report-date.pipe.ts diff --git a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html index 3c6cf402a..2cd78c344 100644 --- a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html +++ b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html @@ -5,21 +5,21 @@ } @else {
@if (summaryMetrics()?.reportYearmonth) { -
- {{ 'adminInstitutions.summary.lastUpdated' | translate }}: - {{ summaryMetrics()!.reportYearmonth | reportDate }} +
+ {{ 'adminInstitutions.summary.lastUpdated' | translate }}: + {{ summaryMetrics()!.reportYearmonth + '-01' | date: 'MMMM d, y' }}
}
@for (item of statisticsData; track $index) { - + }
@if (departmentLabels().length > 0) { -
+
0) { -
+
0) { -
+
0) { -
+
0) { -
+
0) { -
+
0) { -
+
{ - let pipe: ReportDatePipe; - - beforeEach(() => { - pipe = new ReportDatePipe(); - }); - - it('should create an instance', () => { - expect(pipe).toBeTruthy(); - }); - - it('should transform "2024-08" to "August 1, 2024"', () => { - expect(pipe.transform('2024-08')).toBe('August 1, 2024'); - }); - - it('should transform "2024-12" to "December 1, 2024"', () => { - expect(pipe.transform('2024-12')).toBe('December 1, 2024'); - }); - - it('should transform "2025-01" to "January 1, 2025"', () => { - expect(pipe.transform('2025-01')).toBe('January 1, 2025'); - }); - - it('should return empty string for null', () => { - expect(pipe.transform(null)).toBe(''); - }); - - it('should return empty string for undefined', () => { - expect(pipe.transform(undefined)).toBe(''); - }); - - it('should return empty string for empty string', () => { - expect(pipe.transform('')).toBe(''); - }); - - it('should return empty string for invalid format', () => { - expect(pipe.transform('invalid')).toBe(''); - expect(pipe.transform('2024')).toBe(''); - expect(pipe.transform('2024-')).toBe(''); - }); - - it('should return empty string for invalid month', () => { - expect(pipe.transform('2024-13')).toBe(''); - expect(pipe.transform('2024-00')).toBe(''); - }); -}); diff --git a/src/app/shared/pipes/report-date.pipe.ts b/src/app/shared/pipes/report-date.pipe.ts deleted file mode 100644 index d64f89b80..000000000 --- a/src/app/shared/pipes/report-date.pipe.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; - -/** - * Transforms a report yearmonth string from "YYYY-MM" format to "Month Day, Year" format - * Example: "2024-08" -> "August 1, 2024" - */ -@Pipe({ - name: 'reportDate', - standalone: true, -}) -export class ReportDatePipe implements PipeTransform { - private readonly monthNames = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', - ]; - - transform(yearMonth: string | null | undefined): string { - if (!yearMonth) { - return ''; - } - - // Input format: "YYYY-MM" (e.g., "2024-08") - const [yearStr, monthStr] = yearMonth.split('-'); - - if (!yearStr || !monthStr) { - return ''; - } - - const year = parseInt(yearStr, 10); - const month = parseInt(monthStr, 10); - - if (isNaN(year) || isNaN(month) || month < 1 || month > 12) { - return ''; - } - - const monthName = this.monthNames[month - 1]; - - // Output format: "Month 1, Year" (e.g., "August 1, 2024") - return `${monthName} 1, ${year}`; - } -} From 467b6d9f220666aab6f30213284c3d7a819659fa Mon Sep 17 00:00:00 2001 From: Vlad0n20 Date: Mon, 8 Dec 2025 17:45:10 +0200 Subject: [PATCH 7/8] Revert institutions-summary.component.scss --- .../institutions-summary.component.scss | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.scss b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.scss index da0c027b5..c09d87014 100644 --- a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.scss +++ b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.scss @@ -1,5 +1,27 @@ +@use "styles/variables" as var; + :host { display: flex; flex-direction: column; flex: 1; } + +.width-25 { + width: calc(25% - 1.5rem); + + @media (max-width: var.$breakpoint-sm) { + width: calc(50% - 0.5rem); + } +} + +.width-33 { + width: calc(33% - 1rem); + + @media (max-width: var.$breakpoint-lg) { + width: calc(50% - 1rem); + } + + @media (max-width: var.$breakpoint-sm) { + width: 100%; + } +} From 0f02b6f70f317de44e619e50d2fd5af357efbc3e Mon Sep 17 00:00:00 2001 From: Vlad0n20 Date: Tue, 9 Dec 2025 15:57:03 +0200 Subject: [PATCH 8/8] Revert institutions-summary.component.html --- .../institutions-summary.component.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html index 2cd78c344..2ab7923dd 100644 --- a/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html +++ b/src/app/features/admin-institutions/pages/institutions-summary/institutions-summary.component.html @@ -13,13 +13,13 @@
@for (item of statisticsData; track $index) { - + }
@if (departmentLabels().length > 0) { -
+
0) { -
+
0) { -
+
0) { -
+
0) { -
+
0) { -
+
0) { -
+