Skip to content

DT-108: Submit Progress Report Application #2879

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
May 23, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7635942
WIP can submit progress report
snf2ye May 19, 2025
e67e342
WIP - Can submit publications and presentations
snf2ye May 19, 2025
f5a6eb5
Typescript
snf2ye May 19, 2025
9d63e68
Add collaborators, closeouts and DMI
snf2ye May 19, 2025
6ae02b0
cleanup
snf2ye May 19, 2025
f926ca4
Don't need preventDefault with the button type
snf2ye May 19, 2025
1195efd
On success or cancel, redirect away from page
snf2ye May 20, 2025
a985dbf
Mismatch between expected form state field name and actually name
snf2ye May 20, 2025
e2def1f
Enabling pulling info from form state based on keys
snf2ye May 20, 2025
f313ad6
wip
snf2ye May 20, 2025
66a6402
revert change
snf2ye May 20, 2025
a1d4dba
Remove extra type and go straight to submitting a DataAccessRequest
snf2ye May 20, 2025
5052e59
Merge branch 'develop' into sh/dt-108
snf2ye May 20, 2025
ee0bf1a
Changes to match previous PR
snf2ye May 20, 2025
ad787a1
some lint errors
snf2ye May 20, 2025
efdac63
update tests
snf2ye May 21, 2025
271f1c7
Closer to working on submit, but not quite there
snf2ye May 21, 2025
9ff1e4d
Merge branch 'develop' into sh/dt-108
snf2ye May 22, 2025
25dd0bc
Review: Pull history into const
snf2ye May 22, 2025
4b55d8b
Update tests to remove institution
snf2ye May 22, 2025
473d9a0
Review: See if we can remove the default array
snf2ye May 22, 2025
2ce2692
Review: clear out options on selecting "no"
snf2ye May 22, 2025
50f3287
Update dar closeout to support yes/no and radio buttons
snf2ye May 22, 2025
2fad729
readonly state for dmi and closeouts
snf2ye May 22, 2025
710fd61
cleanup
snf2ye May 22, 2025
f83329e
Update src/pages/progress_reports/SubmitProgressReport.tsx
snf2ye May 22, 2025
66964e6
Simplify populating state for dmi incident multi-select
snf2ye May 23, 2025
e07a301
Simplified further with copilot
snf2ye May 23, 2025
b5a1d24
linter
snf2ye May 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip
Type the FormState object rather than only using keys
  • Loading branch information
snf2ye committed May 20, 2025
commit f313ad6e6e956210ba0db099a335e8d9cd26cbbf
6 changes: 3 additions & 3 deletions src/pages/dar_application/ProgressReportApplication.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import {DataAccessRequest, Dataset} from 'src/types/model';
import { FormState} from 'src/pages/progress_reports/ProgressReportFormState';
import {FormState, FormStateKey} from 'src/pages/progress_reports/ProgressReportFormState';
import SummarySection from 'src/pages/progress_reports/SummarySection';
import SelectableDatasets from 'src/pages/dar_application/SelectableDatasets';
import CollaboratorChanges from 'src/pages/progress_reports/CollaboratorChanges';
Expand Down Expand Up @@ -32,7 +32,7 @@ export const ProgressReportApplication = ({ dar, parentDar, datasets, history, r

/* required because the datasets state changes during component mount */
useEffect(() => {
onFormChange({ datasetIds: datasets.map((ds) => ds.datasetId) });
onFormChange({ [FormStateKey.DATASET_IDS]: datasets.map((ds) => ds.datasetId) });
}, [datasets]);

return (
Expand All @@ -48,7 +48,7 @@ export const ProgressReportApplication = ({ dar, parentDar, datasets, history, r
disabled={readOnlyMode}
datasets={datasets}
setSelectedDatasets={(selectedDatasets: Dataset[]) => {
onFormChange({ datasetIds: selectedDatasets.map((ds) => ds.datasetId) });
onFormChange({ [FormStateKey.DATASET_IDS]: selectedDatasets.map((ds) => ds.datasetId) });
}}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/progress_reports/CollaboratorChanges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function CollaboratorChanges(props: CollaboratorProps): React.JSX
const [externalCollaborators, setExternalCollaborators] = useState<Collaborator[]>(formState.externalCollaborators || []);

const onCollaboratorChange = (key: string, setState: React.Dispatch<Collaborator[]>, collaborators: Collaborator[]) => {
onFormChange({ [key]: collaborators });
onFormChange({ [key]: collaborators } as Partial<FormState>);
setState(collaborators);
};

Expand Down
15 changes: 7 additions & 8 deletions src/pages/progress_reports/DarCloseout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from 'react';
import { FormField, FormFieldTypes } from 'src/components/forms/forms';
import {FormFieldChange, FormState, FormStateKey} from 'src/pages/progress_reports/ProgressReportFormState';
import {FormState, FormStateKey} from 'src/pages/progress_reports/ProgressReportFormState';
import {CloseOutSupplement} from "src/types/model";
import {getFormStateItem} from "src/pages/progress_reports/ProgressReportUtils";

interface DarCloseoutProps {
readonly readOnly: boolean;
Expand All @@ -25,12 +24,12 @@ export default function DarCloseout(props: DarCloseoutProps): React.JSX.Element
title='5.1 Closeouts'
description={<span>Are you ready to finish work on this project?</span>}
orientation='horizontal'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
{getFormStateItem(formState, FormStateKey.DMI_YES_NO) === true && (
{formState.closeoutYesNo && (
<div>
<p>
By completing this page, upon project close-out, the PI and all approved users agree to destroy all copies, versions, and derivations of the dataset(s) retrieved from NIH-designated controlled-access databases, on both local servers and hardware, and if cloud computing was used, delete the data and cloud images from cloud computing provider storage, virtual machines, databases, and random access archives, except as required by publication practices, institutional policies, or law to retain them.
Expand All @@ -49,9 +48,9 @@ export default function DarCloseout(props: DarCloseoutProps): React.JSX.Element
{ text: 'The project is being superseded by a new project', name: CloseOutSupplement.PROJECT_SUPERSEDED }
]}
disabled={readOnly}
defaultValue={getFormStateItem(formState, FormStateKey.CLOSEOUT_SUPPLEMENT)}
onChange={({ _key, value }: FormFieldChange) => {
onFormChange({ [FormStateKey.CLOSEOUT_SUPPLEMENT]: value });
defaultValue={formState.closeoutSupplement}
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
/>
</div>
Expand Down
45 changes: 22 additions & 23 deletions src/pages/progress_reports/DataManagementIncident.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from 'react';
import { FORM_TEXT_AREA_MAX_LENGTH } from 'src/components/forms/formConstants';
import { FormField, FormFieldTypes } from 'src/components/forms/forms';
import {FormFieldChange, FormState, FormStateKey} from 'src/pages/progress_reports/ProgressReportFormState';
import {getFormStateItem} from "src/pages/progress_reports/ProgressReportUtils";
import {FormState, FormStateKey} from 'src/pages/progress_reports/ProgressReportFormState';

const titleStyle = { fontSize: '24px', fontWeight: 500, color: '#333333' };

Expand All @@ -29,7 +28,7 @@ export default function DataManagementIncident(props: DataManagementIncidentProp
titleStyle={titleStyle}
description='Have there been any incidents related to mismanagement or misuse of data?'
orientation='horizontal'
onChange={({ key, value }: FormFieldChange) => {
onChange={({ key, value }: Partial<FormState>) => {
if (value === false) {
onFormChange({
dmiCombination: false,
Expand All @@ -42,84 +41,84 @@ export default function DataManagementIncident(props: DataManagementIncidentProp
dmiOther: false
});
}
onFormChange({ [key]: value });
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
</div>
{getFormStateItem(formState, FormStateKey.DMI_YES_NO) === true &&
{formState.dmiYesNo &&
<>
<div style={{ marginTop: '20px' }}>
<div>Please select any of the following that describe the nature of this Data Management Incident:</div>
<FormField
id={FormStateKey.DMI_COMBINATION}
type={FormFieldTypes.CHECKBOX}
toggleText='Inappropriate combination or analysis of the requested datasets with unapproved datasets'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
<FormField
id={FormStateKey.DMI_IDENTIFICATION}
type={FormFieldTypes.CHECKBOX}
toggleText='Intentional or accidental identification of participants or generation of data which makes them easily identifiable'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
<FormField
id={FormStateKey.DMI_SHARING}
type={FormFieldTypes.CHECKBOX}
toggleText='Distribution of the data to an individual or institution beyond those specified in the approved Data Access Request (DAR)'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
<FormField
id={FormStateKey.DMI_SECURITY}
type={FormFieldTypes.CHECKBOX}
toggleText='Failure to adhere to NIH Security Best Practices for Controlled-Access Data'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
<FormField
id={FormStateKey.DMI_ACKNOWLEDGEMENT}
type={FormFieldTypes.CHECKBOX}
toggleText='Failure to acknowledge the investigator(s) who generated the data, the funding source, accession numbers of the dataset'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
<FormField
id={FormStateKey.DMI_PUBLICATION}
type={FormFieldTypes.CHECKBOX}
toggleText='Analysis and/or publication of a study using the data for the research purpose other than the approved research use'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
<FormField
id={FormStateKey.DMI_FALSIFICATION}
type={FormFieldTypes.CHECKBOX}
toggleText='Fabrication or falsification of data and/or results'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
<FormField
id={FormStateKey.DMI_OTHER}
type={FormFieldTypes.CHECKBOX}
toggleText='Other: such as inadvertent data release or breach of security'
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
Expand All @@ -133,8 +132,8 @@ export default function DataManagementIncident(props: DataManagementIncidentProp
placeholder={`Please limit your Data Management Incident to ${FORM_TEXT_AREA_MAX_LENGTH} characters.`}
rows={6}
maxLength={FORM_TEXT_AREA_MAX_LENGTH}
onChange={({ key, value }: FormFieldChange) => {
onFormChange({ [key]: value });
onChange={({ key, value }: Partial<FormState>) => {
onFormChange({ [key]: value } as Partial<FormState>);
}}
disabled={readOnly}
/>
Expand Down
59 changes: 38 additions & 21 deletions src/pages/progress_reports/ProgressReportFormState.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,44 @@
import {CloseOutSupplement, Collaborator, DataManagementIncident, Presentation, Publication} from "src/types/model";
import {PublicationOrPresentation} from "src/components/publications_list/PublicationOrPresentation";

export interface FormState {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
progressReportSummary?: string;
intellectualPropertyYesNo?: boolean;
intellectualPropertySummary?: string;
datasetIds?: number[];
publicationsYesNo?: boolean;
publications?: PublicationOrPresentation[];
presentationsYesNo?: boolean;
presentations?: PublicationOrPresentation[];
internalLabStaff?: Collaborator[];
internalCollaborators?: Collaborator[];
externalCollaborators?: Collaborator[];
dmiYesNo?: boolean;
dmiCombination?: boolean;
dmiIdentification?: boolean;
dmiSharing?: boolean;
dmiSecurity?: boolean;
dmiAcknowledgement?: boolean;
dmiPublication?: boolean;
dmiFalsification?: boolean;
dmiOther?: boolean;
dmiDescription?: string;
closeoutYesNo?: boolean;
closeoutSupplement?: CloseOutSupplement;
}

export interface FormFieldChange {
key: string;
value: boolean | string;
export interface ExpectedFormState {
progressReportSummary?: string;
intellectualPropertyYesNo?: boolean;
intellectualPropertySummary?: string;
datasetIds?: number[];
publications?: Publication[];
presentations?: Presentation[];
labCollaborators?: Collaborator[];
internalCollaborators?: Collaborator[];
externalCollaborators?: Collaborator[];
dataManagementIncident?: DataManagementIncident;
closeOutSupplement?: CloseOutSupplement;
}

export enum FormStateKey {
Expand Down Expand Up @@ -36,21 +67,7 @@ export enum FormStateKey {
CLOSEOUT_SUPPLEMENT = 'closeoutSupplement'
}

export interface ExpectedFormState {
progressReportSummary?: string;
intellectualPropertyYesNo?: boolean;
intellectualPropertySummary?: string;
datasetIds?: number[];
publications?: Publication[];
presentations?: Presentation[];
labCollaborators?: Collaborator[];
internalCollaborators?: Collaborator[];
externalCollaborators?: Collaborator[];
dataManagementIncident?: DataManagementIncident;
closeOutSupplement?: CloseOutSupplement;
}

export const DMI_INCIDENT_KEYS = [
export const DMI_INCIDENT_KEYS: FormStateKey[] = [
FormStateKey.DMI_COMBINATION,
FormStateKey.DMI_IDENTIFICATION,
FormStateKey.DMI_SHARING,
Expand All @@ -59,4 +76,4 @@ export const DMI_INCIDENT_KEYS = [
FormStateKey.DMI_PUBLICATION,
FormStateKey.DMI_FALSIFICATION,
FormStateKey.DMI_OTHER
]
];
3 changes: 0 additions & 3 deletions src/pages/progress_reports/ProgressReportUtils.ts

This file was deleted.

Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy