Skip to content

serval-admin: onboarding-requests: add export spreadsheet#3954

Merged
RaymondLuong3 merged 2 commits into
masterfrom
task/ob-export
Jun 18, 2026
Merged

serval-admin: onboarding-requests: add export spreadsheet#3954
RaymondLuong3 merged 2 commits into
masterfrom
task/ob-export

Conversation

@marksvc

@marksvc marksvc commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

This patch adds an "Export CSV" button to the Serval Administration,
Onboarding Requests tab. A similar button and feature can be found on
the Serval Builds tab.

The parseDate function was moved out into app/shared/utils.ts to be
reused.

Exporting the Onboarding Request data is helpful for our internal analyses.

Screenshot showing the "Export CSV" button, with "Export TSV" as an alternate option in the drop-down:
image

Screenshot showing Export button in context, on the Onboarding Requests tab:
image


Open in Devin Review


This change is Reviewable

@marksvc marksvc requested a review from Copilot June 16, 2026 20:44
@marksvc marksvc added the e2e Run e2e tests for this pull request label Jun 16, 2026
@marksvc marksvc marked this pull request as draft June 16, 2026 20:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds spreadsheet export capability to the Serval Administration → Onboarding Requests tab, and refactors a date-parsing helper into shared utilities for reuse across the client app.

Changes:

  • Added CSV/TSV export UI and an export service to generate separated-value content and filenames.
  • Extracted parseDate into app/shared/utils.ts and updated existing Serval build report type interpretation to use it.
  • Added unit tests for parseDate and the new onboarding-requests export service.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/SIL.XForge.Scripture/ClientApp/src/app/shared/utils.ts Adds shared parseDate() utility.
src/SIL.XForge.Scripture/ClientApp/src/app/shared/utils.spec.ts Adds tests covering parseDate() behavior.
src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-build-report.ts Switches DTO type interpretation to use shared parseDate().
src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/onboarding-requests/onboarding-requests.component.ts Wires export actions into the onboarding requests UI.
src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/onboarding-requests/onboarding-requests.component.html Adds export button + menu to trigger CSV/TSV downloads.
src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/onboarding-requests/onboarding-requests.component.scss Styles the new filter/export bar and button group.
src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/onboarding-requests/onboarding-requests-export.service.ts Implements CSV/TSV generation + filename construction for exports.
src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/onboarding-requests/onboarding-requests-export.service.spec.ts Adds unit tests for export formatting, fallbacks, and filename generation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +303 to +307
/**
* Parses a value into a Date, returning undefined if the value is null, not a string/number, or not a valid date.
*/
export function parseDate(value: unknown): Date | undefined {
if (value instanceof Date) return value;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revised.

Comment on lines +20 to +26
<button mat-raised-button color="primary" class="export-csv-button" (click)="exportCsv()">
<mat-icon>download</mat-icon>
<span class="export-item-label">
Export CSV
<app-info text="Download a .csv (comma-separated values) spreadsheet of the table data"></app-info>
</span>
</button>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the pattern we have for the other serval admin components

Comment on lines +32 to +38
<button mat-menu-item (click)="exportTsv()">
<mat-icon>download</mat-icon>
<span class="export-item-label">
Export TSV
<app-info text="Download a .tsv (tab-separated values) spreadsheet of the table data"></app-info>
</span>
</button>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the pattern we already have with other serval admin components.

Comment on lines +27 to +29
<button mat-raised-button color="primary" class="export-menu-button" [matMenuTriggerFor]="exportMenu">
<mat-icon>arrow_drop_down</mat-icon>
</button>
Comment on lines +66 to +70
requests.map(async request => {
const sfProjectId = request.submission.projectId;
const projectDoc = await this.servalAdministrationService.get(sfProjectId);
const projectShortName = projectDoc?.data?.shortName ?? sfProjectId;
return [

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't plan to optimize fetching projects in the Onboarding Requests export at this time. I set escapeFormulae to true.

Comment on lines +176 to +188
private async export(extension: 'csv' | 'tsv'): Promise<void> {
const requests = this.filteredRequests;
if (requests.length === 0) {
this.noticeService.show('No data to export.');
return;
}

const content =
extension === 'csv' ? await this.exportService.createCsv(requests) : await this.exportService.createTsv(requests);
const mimeType = extension === 'csv' ? 'text/csv;charset=utf-8;' : 'text/tab-separated-values;charset=utf-8;';
const blob = new Blob([content], { type: mimeType });
saveAs(blob, this.exportService.exportFilename(extension));
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(global error handling)

@marksvc marksvc temporarily deployed to screenshot_diff June 16, 2026 20:51 — with GitHub Actions Inactive
@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.42857% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.88%. Comparing base (175b5be) to head (0b0a367).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...boarding-requests/onboarding-requests.component.ts 0.00% 12 Missing ⚠️
...ing-requests/onboarding-requests-export.service.ts 93.54% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3954      +/-   ##
==========================================
- Coverage   80.88%   80.88%   -0.01%     
==========================================
  Files         634      635       +1     
  Lines       41036    41076      +40     
  Branches     6661     6693      +32     
==========================================
+ Hits        33193    33223      +30     
- Misses       6807     6815       +8     
- Partials     1036     1038       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@marksvc marksvc temporarily deployed to screenshot_diff June 17, 2026 16:05 — with GitHub Actions Inactive
@marksvc marksvc marked this pull request as ready for review June 17, 2026 16:21
@RaymondLuong3 RaymondLuong3 self-assigned this Jun 18, 2026

@RaymondLuong3 RaymondLuong3 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RaymondLuong3 reviewed 8 files and all commit messages, made 3 comments, and resolved 2 discussions.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on marksvc).


src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/onboarding-requests/onboarding-requests-export.service.ts line 79 at r2 (raw file):

          assigneeNames.get(request.assigneeId) ?? '',
          request.id,
          sfProjectId

It would be better if we could assign these entries to a model, and then have a helper function to extra the data in the correct order depending on the expected order of the output file. That way things are guaranteed to be in the correct order. This can come in a follow up PR if desired.

Code quote:

          this.onboardingRequestService.getResolution(request.resolution).label,
          request.submission.formData.name,
          request.submission.formData.translationLanguageIsoCode,
          projectShortName,
          request.submission.formData.translationLanguageName,
          assigneeNames.get(request.assigneeId) ?? '',
          request.id,
          sfProjectId

Comment on lines +20 to +26
<button mat-raised-button color="primary" class="export-csv-button" (click)="exportCsv()">
<mat-icon>download</mat-icon>
<span class="export-item-label">
Export CSV
<app-info text="Download a .csv (comma-separated values) spreadsheet of the table data"></app-info>
</span>
</button>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the pattern we have for the other serval admin components

Comment on lines +32 to +38
<button mat-menu-item (click)="exportTsv()">
<mat-icon>download</mat-icon>
<span class="export-item-label">
Export TSV
<app-info text="Download a .tsv (tab-separated values) spreadsheet of the table data"></app-info>
</span>
</button>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the pattern we already have with other serval admin components.

@RaymondLuong3 RaymondLuong3 removed the e2e Run e2e tests for this pull request label Jun 18, 2026
marksvc added 2 commits June 18, 2026 13:34
This patch adds an "Export CSV" button to the Serval Administration,
Onboarding Requests tab. A similar button and feature can be found on
the Serval Builds tab.

The parseDate function was moved out into app/shared/utils.ts to be
reused.
@RaymondLuong3 RaymondLuong3 merged commit 08fa982 into master Jun 18, 2026
25 of 26 checks passed
@RaymondLuong3 RaymondLuong3 deleted the task/ob-export branch June 18, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants