diff --git a/app/backend/lib/excel_import/cbc_project.ts b/app/backend/lib/excel_import/cbc_project.ts index 7f4348a5c0..63e4d07ee9 100644 --- a/app/backend/lib/excel_import/cbc_project.ts +++ b/app/backend/lib/excel_import/cbc_project.ts @@ -125,12 +125,16 @@ const readSummary = async (wb, sheet) => { phase: project['C'], intake: project['D'], projectStatus: project['E'], - changeRequestPending: project['F'], + changeRequestPending: project?.['F'] + ? project?.['F'].toLowerCase() === 'yes' + : null, projectTitle: project['G'], projectDescription: project['H'], applicantContractualName: project['I'], currentOperatingName: project['J'], - eightThirtyMillionFunding: project['K'], + eightThirtyMillionFunding: project?.['K'] + ? project?.['K'].toLowerCase() === 'yes' + : null, federalFundingSource: project['L'], federalProjectNumber: project['M'], projectType: project['N'], @@ -138,7 +142,9 @@ const readSummary = async (wb, sheet) => { highwayProjectType: project['P'], lastMileProjectType: project['Q'], lastMileMinimumSpeed: project['R'], - connectedCoastNetworkDependant: project['S'], + connectedCoastNetworkDependant: project?.['S'] + ? project?.['S'].toLowerCase() === 'yes' + : null, projectLocations: project['T'], communitiesAndLocalesCount: validateNumber( project['U'], @@ -201,9 +207,15 @@ const readSummary = async (wb, sheet) => { errorLog, projectNumber ), - nditConditionalApprovalLetterSent: project['AF'], - bindingAgreementSignedNditRecipient: project['AG'], - announcedByProvince: project['AH'], + nditConditionalApprovalLetterSent: project?.['AF'] + ? project?.['AF'].toLowerCase() === 'yes' + : null, + bindingAgreementSignedNditRecipient: project?.['AG'] + ? project?.['AG'].toLowerCase() === 'yes' + : null, + announcedByProvince: project?.['AH'] + ? project?.['AH'].toLowerCase() === 'yes' + : null, dateApplicationReceived: validateDate( project['AI'], 'dateApplicationReceived', @@ -262,7 +274,7 @@ const readSummary = async (wb, sheet) => { primaryNewsRelease: project['AS'], secondaryNewsRelease: project['AT'], notes: project['AU'], - locked: project['AV'], + locked: project?.['AV'] ? project?.['AV'].toLowerCase() === 'x' : null, lastReviewed: validateDate( project['AW'], 'lastReviewed', diff --git a/app/components/Analyst/CBC/AssignField.tsx b/app/components/Analyst/CBC/AssignField.tsx index bba99c9e32..f4514a9599 100644 --- a/app/components/Analyst/CBC/AssignField.tsx +++ b/app/components/Analyst/CBC/AssignField.tsx @@ -14,11 +14,17 @@ const StyledDropdown = styled.select` border-radius: 4px; `; -const AssignField = ({ fieldName, fieldOptions, fieldType, cbc }) => { +const AssignField = ({ + fieldName, + fieldOptions, + fieldType, + cbc, + isFormEditMode, +}) => { const queryFragment = useFragment( graphql` fragment AssignField_query on Cbc { - cbcDataByCbcId { + cbcDataByCbcId(first: 500) @connection(key: "CbcData__cbcDataByCbcId") { edges { node { jsonData @@ -43,7 +49,8 @@ const AssignField = ({ fieldName, fieldOptions, fieldType, cbc }) => { : jsonData[fieldName] || null ); - const allowEdit = useFeature('show_cbc_edit').value ?? false; + const allowEdit = + (useFeature('show_cbc_edit').value ?? false) && !isFormEditMode; const handleChange = (e) => { const { rowId } = queryFragment.cbcDataByCbcId.edges[0].node; diff --git a/app/components/Analyst/CBC/CbcAnalystLayout.tsx b/app/components/Analyst/CBC/CbcAnalystLayout.tsx index 9737b9e8ee..56b48fcce4 100644 --- a/app/components/Analyst/CBC/CbcAnalystLayout.tsx +++ b/app/components/Analyst/CBC/CbcAnalystLayout.tsx @@ -22,9 +22,14 @@ const StyledFormDiv = styled(FormDiv)` interface Props { children: JSX.Element[] | JSX.Element; query: any; + isFormEditMode?: boolean; } -const CbcAnalystLayout: React.FC = ({ children, query }) => { +const CbcAnalystLayout: React.FC = ({ + children, + query, + isFormEditMode = false, +}) => { const queryFragment = useFragment( graphql` fragment CbcAnalystLayout_query on Query { @@ -35,7 +40,7 @@ const CbcAnalystLayout: React.FC = ({ children, query }) => { ); return ( - + {children} diff --git a/app/components/Analyst/CBC/CbcChangeStatus.tsx b/app/components/Analyst/CBC/CbcChangeStatus.tsx index df9eac9259..c027f3894d 100644 --- a/app/components/Analyst/CBC/CbcChangeStatus.tsx +++ b/app/components/Analyst/CBC/CbcChangeStatus.tsx @@ -70,15 +70,23 @@ interface Props { cbc: any; status: string; statusList: any; + isFormEditMode: boolean; } -const CbcChangeStatus: React.FC = ({ cbc, status, statusList }) => { +const CbcChangeStatus: React.FC = ({ + cbc, + status, + statusList, + isFormEditMode, +}) => { const queryFragment = useFragment( graphql` fragment CbcChangeStatus_query on Cbc { - cbcDataByCbcId { + cbcDataByCbcId(first: 500) @connection(key: "CbcData__cbcDataByCbcId") { + __id edges { node { + id jsonData sharepointTimestamp rowId @@ -94,7 +102,8 @@ const CbcChangeStatus: React.FC = ({ cbc, status, statusList }) => { ); const [updateStatus] = useUpdateCbcDataByRowIdMutation(); const [currentStatus, setCurrentStatus] = useState(getStatus(status)); - const allowEdit = useFeature('show_cbc_edit').value ?? false; + const allowEdit = + (useFeature('show_cbc_edit').value ?? false) && !isFormEditMode; const handleChange = (e) => { const newStatus = e.target.value; @@ -124,7 +133,7 @@ const CbcChangeStatus: React.FC = ({ cbc, status, statusList }) => { onChange={(e) => { // eslint-disable-next-line no-void void (() => handleChange(e))(); - }} // Use draft status for colour so it changes as user selects it + }} statusStyles={statusStyles[getStatus(status)]} value={currentStatus} id="change-status" diff --git a/app/components/Analyst/CBC/CbcForm.tsx b/app/components/Analyst/CBC/CbcForm.tsx index d26a9b4524..42f35c3328 100644 --- a/app/components/Analyst/CBC/CbcForm.tsx +++ b/app/components/Analyst/CBC/CbcForm.tsx @@ -5,6 +5,7 @@ import CircularProgress from '@mui/material/CircularProgress'; import { RJSFSchema } from '@rjsf/utils'; import Button from '@button-inc/bcgov-theme/Button'; import ProjectTheme from '../Project/ProjectTheme'; +import { ProjectFormProps } from '../Project/ProjectFormProps'; const LoadingContainer = styled.div` display: block; @@ -21,46 +22,29 @@ const LoadingItem = styled.div` justify-content: center; `; -const StyledBtn = styled(Button)` - margin: 0 8px; - padding: 8px 16px; +const StyledContainer = styled.div` + display: flex; + flex-direction: row; + margin: 20px auto; `; -interface Props { - additionalContext?: any; - before?: React.ReactNode; - children?: React.ReactNode; - formAnimationHeight?: number; - formAnimationHeightOffset?: number; - formData: any; - formHeader?: string | React.ReactNode | JSX.Element; - handleChange: any; - showEditBtn?: boolean; - /** The hidden submit button's ref, used to enforce validation on the form - * (the red-outline we see on widgets) */ - hiddenSubmitRef?: any; - isExpanded?: boolean; - isFormEditMode: boolean; - isFormAnimated?: boolean; - liveValidate?: boolean; - onSubmit: any; - resetFormData: any; - saveBtnText?: string; - saveBtnDisabled?: boolean; - cancelBtnDisabled?: boolean; - schema: RJSFSchema; - setFormData?: any; - setIsFormEditMode: any; - submitting?: boolean; - submittingText?: string; - theme?: any; - title: string; - uiSchema?: any; - saveDataTestId?: string; - validate?: any; -} +const StyledBtn = styled(Button)` + @media (min-width: 1024px) { + position: fixed; + bottom: 5vh; + left: 80vw; + + &:nth-child(2) { + left: 85vw; + } + } + @media (max-width: 1900px) { + margin: 0 8px; + padding: 8px 16px; + } +`; -const CbcForm: React.FC = ({ +const CbcForm: React.FC = ({ additionalContext, before, children, @@ -136,7 +120,7 @@ const CbcForm: React.FC = ({ )} {isFormEditMode && ( - <> + = ({ variant="secondary" disabled={cancelBtnDisabled} onClick={() => { - setFormData(); + resetFormData(); setIsFormEditMode(false); }} > Cancel - + )} )} diff --git a/app/components/Analyst/CBC/CbcHeader.tsx b/app/components/Analyst/CBC/CbcHeader.tsx index fcba69773e..fbc1c9b276 100644 --- a/app/components/Analyst/CBC/CbcHeader.tsx +++ b/app/components/Analyst/CBC/CbcHeader.tsx @@ -56,9 +56,10 @@ const StyledPendingChangeRequests = styled(StyledItem)` interface Props { query: any; + isFormEditMode: boolean; } -const CbcHeader: React.FC = ({ query }) => { +const CbcHeader: React.FC = ({ query, isFormEditMode }) => { const queryFragment = useFragment( graphql` fragment CbcHeader_query on Query { @@ -66,7 +67,8 @@ const CbcHeader: React.FC = ({ query }) => { projectNumber rowId sharepointTimestamp - cbcDataByCbcId { + cbcDataByCbcId(first: 500) + @connection(key: "CbcData__cbcDataByCbcId") { edges { node { jsonData @@ -117,6 +119,7 @@ const CbcHeader: React.FC = ({ query }) => { { description: 'Reporting Complete', name: 'complete', id: 2 }, { description: 'Agreement Signed', name: 'approved', id: 3 }, ]} + isFormEditMode={isFormEditMode} /> @@ -127,6 +130,7 @@ const CbcHeader: React.FC = ({ query }) => { fieldOptions={['1', '2', '3', '4', '4b']} fieldType="string" cbc={cbcByRowId} + isFormEditMode={isFormEditMode} /> @@ -137,6 +141,7 @@ const CbcHeader: React.FC = ({ query }) => { fieldOptions={[null, 1, 2, 3, 4]} fieldType="number" cbc={cbcByRowId} + isFormEditMode={isFormEditMode} /> diff --git a/app/components/Analyst/CBC/CbcTheme.ts b/app/components/Analyst/CBC/CbcTheme.ts new file mode 100644 index 0000000000..292b899c8e --- /dev/null +++ b/app/components/Analyst/CBC/CbcTheme.ts @@ -0,0 +1,59 @@ +import { ThemeProps, getDefaultRegistry } from '@rjsf/core'; +import { + CheckboxWidget, + CheckboxesWidget, + MoneyWidget, + NumberWidget, + NumericStringWidget, + RadioWidget, + SelectWidget, + TextAreaWidget, + TextWidget, + DatePickerWidget, +} from 'lib/theme/widgets'; +import ArrayBooleanField from '../../Review/fields/ArrayBooleanField'; +import ReviewCheckboxField from '../../Review/fields/ReviewCheckboxField'; +import ReviewInlineArrayField from '../../Review/fields/ReviewInlineArrayField'; +import ReviewObjectFieldTemplate from '../../Review/ReviewObjectFieldTemplate'; +import ReviewSectionField from '../../Review/ReviewSectionField'; +import ReviewArrayFieldTemplate from '../../Review/fields/ReviewArrayFieldTemplate'; +import ReviewFieldTemplate from '../../Review/fields/ReviewFieldTemplate'; +import DefaultWidget from '../../Review/widgets/DefaultWidget'; +import BooleanWidget from '../../Review/widgets/BooleanWidget'; +import FileWidget from '../../Review/widgets/FileWidget'; + +const { templates } = getDefaultRegistry(); + +const CbcTheme: ThemeProps = { + fields: { + SectionField: ReviewSectionField, + InlineArrayField: ReviewInlineArrayField, + ArrayBooleanField, + ReviewCheckboxField, + }, + widgets: { + TextAreaWidget, + DatePickerWidget, + CheckboxesWidget, + CheckboxWidget, + FileWidget, + RadioWidget, + SelectWidget, + TextWidget, + MoneyWidget, + BooleanWidget, + DefaultWidget, + ReadOnlyMoneyWidget: DefaultWidget, + NumberWidget, + NumericStringWidget, + ReadOnlyWidget: DefaultWidget, + }, + templates: { + ...templates, + ObjectFieldTemplate: ReviewObjectFieldTemplate, + FieldTemplate: ReviewFieldTemplate, + ArrayFieldTemplate: ReviewArrayFieldTemplate, + }, +}; + +export default CbcTheme; diff --git a/app/components/Analyst/Project/ProjectForm.tsx b/app/components/Analyst/Project/ProjectForm.tsx index 4e21c94fb0..31657f644d 100644 --- a/app/components/Analyst/Project/ProjectForm.tsx +++ b/app/components/Analyst/Project/ProjectForm.tsx @@ -6,8 +6,8 @@ import Accordion from 'components/Accordion'; import { FormBase } from 'components/Form'; import CircularProgress from '@mui/material/CircularProgress'; import { Collapse } from '@mui/material'; -import { RJSFSchema } from '@rjsf/utils'; import ProjectTheme from './ProjectTheme'; +import { ProjectFormProps } from './ProjectFormProps'; const ToggleRight = styled.div` display: flex; @@ -58,41 +58,7 @@ const StyledBtn = styled(Button)` padding: 8px 16px; `; -interface Props { - additionalContext?: any; - before?: React.ReactNode; - children?: React.ReactNode; - formAnimationHeight?: number; - formAnimationHeightOffset?: number; - formData: any; - formHeader?: string | React.ReactNode | JSX.Element; - handleChange: any; - showEditBtn?: boolean; - /** The hidden submit button's ref, used to enforce validation on the form - * (the red-outline we see on widgets) */ - hiddenSubmitRef?: any; - isExpanded?: boolean; - isFormEditMode: boolean; - isFormAnimated?: boolean; - liveValidate?: boolean; - onSubmit: any; - resetFormData: any; - saveBtnText?: string; - saveBtnDisabled?: boolean; - cancelBtnDisabled?: boolean; - schema: RJSFSchema; - setFormData?: any; - setIsFormEditMode: any; - submitting?: boolean; - submittingText?: string; - theme?: any; - title: string; - uiSchema?: any; - saveDataTestId?: string; - validate?: any; -} - -const ProjectForm: React.FC = ({ +const ProjectForm: React.FC = ({ additionalContext, before, children, diff --git a/app/components/Analyst/Project/ProjectFormProps.ts b/app/components/Analyst/Project/ProjectFormProps.ts new file mode 100644 index 0000000000..6ba169d905 --- /dev/null +++ b/app/components/Analyst/Project/ProjectFormProps.ts @@ -0,0 +1,35 @@ +import { RJSFSchema } from '@rjsf/utils'; + +export interface ProjectFormProps { + additionalContext?: any; + before?: React.ReactNode; + children?: React.ReactNode; + formAnimationHeight?: number; + formAnimationHeightOffset?: number; + formData: any; + formHeader?: string | React.ReactNode | JSX.Element; + handleChange: any; + showEditBtn?: boolean; + /** The hidden submit button's ref, used to enforce validation on the form + * (the red-outline we see on widgets) */ + hiddenSubmitRef?: any; + isExpanded?: boolean; + isFormEditMode: boolean; + isFormAnimated?: boolean; + liveValidate?: boolean; + onSubmit: any; + resetFormData: any; + saveBtnText?: string; + saveBtnDisabled?: boolean; + cancelBtnDisabled?: boolean; + schema: RJSFSchema; + setFormData?: any; + setIsFormEditMode: any; + submitting?: boolean; + submittingText?: string; + theme?: any; + title: string; + uiSchema?: any; + saveDataTestId?: string; + validate?: any; +} diff --git a/app/components/Review/ReviewTheme.tsx b/app/components/Review/ReviewTheme.tsx index d4fdc7b6d9..8cc5befb9e 100644 --- a/app/components/Review/ReviewTheme.tsx +++ b/app/components/Review/ReviewTheme.tsx @@ -10,6 +10,7 @@ import DefaultWidget from './widgets/DefaultWidget'; import MoneyWidget from './widgets/MoneyWidget'; import BooleanWidget from './widgets/BooleanWidget'; import FileWidget from './widgets/FileWidget'; +import DateWidget from './widgets/DateWidget'; const { templates } = getDefaultRegistry(); @@ -36,6 +37,7 @@ const ReviewTheme: ThemeProps = { ReadOnlyWidget: DefaultWidget, ReadOnlyProjectAreaWidget: DefaultWidget, ReadOnlyProjectAreaWidgetIntakeFour: DefaultWidget, + DateWidget, }, templates: { ...templates, diff --git a/app/components/Review/widgets/DateWidget.tsx b/app/components/Review/widgets/DateWidget.tsx new file mode 100644 index 0000000000..3022897120 --- /dev/null +++ b/app/components/Review/widgets/DateWidget.tsx @@ -0,0 +1,8 @@ +import { WidgetProps } from '@rjsf/utils'; + +const DateWidget: React.FC = ({ value }) => { + const date = value?.toString().split('T')[0]; + return <>{date}; +}; + +export default DateWidget; diff --git a/app/cypress/e2e/analyst/cbc/[cbcId].cy.js b/app/cypress/e2e/analyst/cbc/[cbcId].cy.js index 08ead52efc..66b5a66877 100644 --- a/app/cypress/e2e/analyst/cbc/[cbcId].cy.js +++ b/app/cypress/e2e/analyst/cbc/[cbcId].cy.js @@ -23,4 +23,12 @@ describe('The cbc project view', () => { cy.contains('h2', 'Project data reviews'); cy.get('body').happoScreenshot({ component: 'CBC project view' }); }); + + it('triggers quick edit', () => { + cy.visit('/analyst/cbc/1'); + cy.get('button').contains('Quick edit').click(); + cy.get('body').happoScreenshot({ + component: 'CBC project view - quick edit', + }); + }); }); diff --git a/app/formSchema/analyst/cbc/eventsAndDates.ts b/app/formSchema/analyst/cbc/eventsAndDates.ts index 77964a3188..aa06e69a29 100644 --- a/app/formSchema/analyst/cbc/eventsAndDates.ts +++ b/app/formSchema/analyst/cbc/eventsAndDates.ts @@ -6,19 +6,28 @@ const eventsAndDates: RJSFSchema = { type: 'object', properties: { nditConditionalApprovalLetterSent: { - type: 'string', + type: 'boolean', title: 'NDIT Conditional Approval Letter Sent', - enum: [null, 'Yes', 'No'], + oneOf: [ + { const: true, title: 'Yes' }, + { const: false, title: 'No' }, + ], }, bindingAgreementSignedNditRecipient: { - type: 'string', + type: 'boolean', title: 'Binding Agreement Signed - NDIT Recipient', - enum: [null, 'Yes', 'No'], + oneOf: [ + { const: true, title: 'Yes' }, + { const: false, title: 'No' }, + ], }, announcedByProvince: { - type: 'string', + type: 'boolean', title: 'Announced by Province', - enum: [null, 'Yes', 'No'], + oneOf: [ + { const: true, title: 'Yes' }, + { const: false, title: 'No' }, + ], }, dateApplicationReceived: { type: 'string', diff --git a/app/formSchema/analyst/cbc/projectDataReviews.ts b/app/formSchema/analyst/cbc/projectDataReviews.ts index f6745d6669..cb9bed8c4d 100644 --- a/app/formSchema/analyst/cbc/projectDataReviews.ts +++ b/app/formSchema/analyst/cbc/projectDataReviews.ts @@ -8,6 +8,10 @@ const projectDataReviews: RJSFSchema = { locked: { type: 'boolean', title: 'Locked', + oneOf: [ + { const: true, title: 'Yes' }, + { const: false, title: 'No' }, + ], }, lastReviewed: { type: 'string', diff --git a/app/formSchema/analyst/cbc/projectType.ts b/app/formSchema/analyst/cbc/projectType.ts index 173963cd0c..6f61ee14ce 100644 --- a/app/formSchema/analyst/cbc/projectType.ts +++ b/app/formSchema/analyst/cbc/projectType.ts @@ -8,7 +8,15 @@ const projectType: RJSFSchema = { projectType: { type: 'string', title: 'Project Type', - enum: [null, 'Transport', 'Highway', 'Last Mile'], + enum: [ + null, + 'Highway', + 'Last-Mile', + 'Last-Mile & Cellular', + 'Last-Mile & Transport', + 'Plan', + 'Transport', + ], }, transportProjectType: { type: 'string', @@ -32,7 +40,10 @@ const projectType: RJSFSchema = { connectedCoastNetworkDependant: { type: 'string', title: 'Connected Coast Network Dependant', - enum: [null, 'Yes', 'No'], + oneOf: [ + { const: true, title: 'Yes' }, + { const: false, title: 'No' }, + ], }, }, }; diff --git a/app/formSchema/analyst/cbc/tombstone.ts b/app/formSchema/analyst/cbc/tombstone.ts index d919baf26c..6f249c7b0f 100644 --- a/app/formSchema/analyst/cbc/tombstone.ts +++ b/app/formSchema/analyst/cbc/tombstone.ts @@ -46,7 +46,10 @@ const cbcTombstone: RJSFSchema = { eightThirtyMillionFunding: { type: 'string', title: '$8.30 Million Funding', - enum: [null, 'Yes', 'No'], + oneOf: [ + { const: true, title: 'Yes' }, + { const: false, title: 'No' }, + ], }, federalFundingSource: { type: 'string', diff --git a/app/formSchema/uiSchema/cbc/eventsAndDatesUiSchema.ts b/app/formSchema/uiSchema/cbc/eventsAndDatesUiSchema.ts index 12f36302a9..8495c1624e 100644 --- a/app/formSchema/uiSchema/cbc/eventsAndDatesUiSchema.ts +++ b/app/formSchema/uiSchema/cbc/eventsAndDatesUiSchema.ts @@ -5,22 +5,22 @@ const eventsAndDatesUiSchema = { }, 'ui:title': 'Events and Dates', nditConditionalApprovalLetterSent: { - 'ui:widget': 'TextAreaWidget', + 'ui:widget': 'RadioWidget', 'ui:label': 'NDIT Conditional Approval Letter Sent', }, bindingAgreementSignedNditRecipient: { - 'ui:widget': 'TextAreaWidget', + 'ui:widget': 'RadioWidget', 'ui:label': 'Binding Agreement Signed NDIT Recipient', }, announcedByProvince: { - 'ui:widget': 'TextAreaWidget', + 'ui:widget': 'RadioWidget', 'ui:label': 'Announced By Province', }, dateApplicationReceived: { 'ui:widget': 'DatePickerWidget', 'ui:label': 'Date Application Received', }, - dateConditionallyApprovedApproved: { + dateConditionallyApproved: { 'ui:widget': 'DatePickerWidget', 'ui:label': 'Date Conditionally Approved Approved', }, diff --git a/app/formSchema/uiSchema/cbc/locationsAndCountsUiSchema.ts b/app/formSchema/uiSchema/cbc/locationsAndCountsUiSchema.ts index 5995349975..c52be7567d 100644 --- a/app/formSchema/uiSchema/cbc/locationsAndCountsUiSchema.ts +++ b/app/formSchema/uiSchema/cbc/locationsAndCountsUiSchema.ts @@ -7,6 +7,9 @@ const locationsAndCountsUiSchema = { projectLocations: { 'ui:widget': 'TextAreaWidget', 'ui:label': 'Project Locations', + 'ui:options': { + maxLength: 1000, + }, }, communitiesAndLocalesCount: { 'ui:widget': 'NumberWidget', @@ -23,10 +26,18 @@ const locationsAndCountsUiSchema = { transportKm: { 'ui:widget': 'NumberWidget', 'ui:label': 'Transport Km', + 'ui:options': { + maxLength: 7, + decimals: 2, + }, }, highwayKm: { 'ui:widget': 'NumberWidget', 'ui:label': 'Highway Km', + 'ui:options': { + maxLength: 7, + decimals: 2, + }, }, restAreas: { 'ui:widget': 'NumberWidget', diff --git a/app/formSchema/uiSchema/cbc/miscellaneousUiSchema.ts b/app/formSchema/uiSchema/cbc/miscellaneousUiSchema.ts index d8763e9dd0..4a650561ef 100644 --- a/app/formSchema/uiSchema/cbc/miscellaneousUiSchema.ts +++ b/app/formSchema/uiSchema/cbc/miscellaneousUiSchema.ts @@ -15,18 +15,24 @@ const miscellaneousUiSchema = { milestoneComments: { 'ui:widget': 'TextAreaWidget', 'ui:label': 'Milestone Comments', + 'ui:options': { + maxLength: 1000, + }, }, primaryNewsRelease: { - 'ui:widget': 'TextAreaWidget', + 'ui:widget': 'TextWidget', 'ui:label': 'Primary News Release', }, secondaryNewsRelease: { - 'ui:widget': 'TextAreaWidget', + 'ui:widget': 'TextWidget', 'ui:label': 'Secondary News Release', }, notes: { 'ui:widget': 'TextAreaWidget', 'ui:label': 'Notes', + 'ui:options': { + maxLength: 1000, + }, }, }; diff --git a/app/formSchema/uiSchema/cbc/projectDataReviewsUiSchema.ts b/app/formSchema/uiSchema/cbc/projectDataReviewsUiSchema.ts index 9220fc91e2..c2f4e92f45 100644 --- a/app/formSchema/uiSchema/cbc/projectDataReviewsUiSchema.ts +++ b/app/formSchema/uiSchema/cbc/projectDataReviewsUiSchema.ts @@ -5,7 +5,7 @@ const projectDataReviewsUiSchema = { }, 'ui:title': 'Project Data Reviews', locked: { - 'ui:widget': 'TextAreaWidget', + 'ui:widget': 'RadioWidget', 'ui:label': 'Locked', }, lastReviewed: { @@ -15,6 +15,9 @@ const projectDataReviewsUiSchema = { reviewNotes: { 'ui:widget': 'TextAreaWidget', 'ui:label': 'Review Notes', + 'ui:options': { + maxLength: 1000, + }, }, }; export default projectDataReviewsUiSchema; diff --git a/app/formSchema/uiSchema/cbc/projectTypeUiSchema.ts b/app/formSchema/uiSchema/cbc/projectTypeUiSchema.ts index 8bea7b0e44..6f61749781 100644 --- a/app/formSchema/uiSchema/cbc/projectTypeUiSchema.ts +++ b/app/formSchema/uiSchema/cbc/projectTypeUiSchema.ts @@ -6,32 +6,30 @@ const projectTypeUiSchema = { 'ui:title': 'Project Type', projectType: { 'ui:widget': 'SelectWidget', - 'ui:placeholder': 'Select a project type', + 'ui:placeholder': 'Project type', 'ui:label': 'Project Type', }, transportProjectType: { 'ui:widget': 'SelectWidget', - 'ui:placeholder': 'Select a transport project type', + 'ui:placeholder': 'Transport type', 'ui:label': 'Transport Project Type', }, highwayProjectType: { - 'ui:widget': 'SelectWidget', - 'ui:placeholder': 'Select a highway project type', - 'ui:label': 'Highway Project Type', + 'ui:widget': 'TextWidget', + 'ui:placeholder': 'Highway project type', }, lastMileProjectType: { 'ui:widget': 'SelectWidget', - 'ui:placeholder': 'Select a last mile project type', + 'ui:placeholder': 'Last mile type', 'ui:label': 'Last Mile Project Type', }, lastMileMinimumSpeed: { 'ui:widget': 'SelectWidget', - 'ui:placeholder': 'Select a last mile minimum speed', + 'ui:placeholder': 'Last mile minimum speed', 'ui:label': 'Last Mile Minimum Speed', }, connectedCoastNetworkDependant: { - 'ui:widget': 'SelectWidget', - 'ui:placeholder': 'Select a connected coast network dependant', + 'ui:widget': 'RadioWidget', 'ui:label': 'Connected Coast Network Dependant', }, }; diff --git a/app/formSchema/uiSchema/cbc/reviewUiSchema.ts b/app/formSchema/uiSchema/cbc/reviewUiSchema.ts index 4d72fc15f8..fee4956d07 100644 --- a/app/formSchema/uiSchema/cbc/reviewUiSchema.ts +++ b/app/formSchema/uiSchema/cbc/reviewUiSchema.ts @@ -37,12 +37,44 @@ const reviewUiSchema = { }, eventsAndDates: { ...eventsAndDatesUiSchema, + dateApplicationReceived: { + ...eventsAndDatesUiSchema.dateApplicationReceived, + 'ui:widget': 'DateWidget', + }, + dateConditionallyApproved: { + ...eventsAndDatesUiSchema.dateConditionallyApproved, + 'ui:widget': 'DateWidget', + }, + dateAgreementSigned: { + ...eventsAndDatesUiSchema.dateAgreementSigned, + 'ui:widget': 'DateWidget', + }, + proposedStartDate: { + ...eventsAndDatesUiSchema.proposedStartDate, + 'ui:widget': 'DateWidget', + }, + proposedCompletionDate: { + ...eventsAndDatesUiSchema.proposedCompletionDate, + 'ui:widget': 'DateWidget', + }, + reportingCompletionDate: { + ...eventsAndDatesUiSchema.reportingCompletionDate, + 'ui:widget': 'DateWidget', + }, + dateAnnounced: { + ...eventsAndDatesUiSchema.dateAnnounced, + 'ui:widget': 'DateWidget', + }, }, miscellaneous: { ...miscellaneousUiSchema, }, projectDataReviews: { ...projectDataReviewsUiSchema, + lastReviewed: { + ...projectDataReviewsUiSchema.lastReviewed, + 'ui:widget': 'DateWidget', + }, }, }; diff --git a/app/formSchema/uiSchema/cbc/tombstoneUiSchema.ts b/app/formSchema/uiSchema/cbc/tombstoneUiSchema.ts index d49559f973..eefa261f17 100644 --- a/app/formSchema/uiSchema/cbc/tombstoneUiSchema.ts +++ b/app/formSchema/uiSchema/cbc/tombstoneUiSchema.ts @@ -6,39 +6,42 @@ const tombstoneUiSchema = { }, 'ui:title': 'Tombstone', projectTitle: { - 'ui:widget': 'HiddenWidget', + 'ui:widget': 'ReadOnlyWidget', 'ui:label': 'Project Title', }, originalProjectNumber: { - 'ui:widget': 'NumberWidget', + 'ui:widget': 'ReadOnlyWidget', 'ui:label': 'Original Project Number', }, projectNumber: { - 'ui:widget': 'HiddenWidget', + 'ui:widget': 'ReadOnlyWidget', 'ui:label': 'Project Number', }, phase: { - 'ui:widget': 'HiddenWidget', + 'ui:widget': 'ReadOnlyWidget', 'ui:placeholder': 'Select a phase', 'ui:label': 'Phase', }, intake: { - 'ui:widget': 'HiddenWidget', + 'ui:widget': 'ReadOnlyWidget', 'ui:placeholder': 'Select an intake', 'ui:label': 'Intake', }, projectStatus: { - 'ui:widget': 'HiddenWidget', + 'ui:widget': 'ReadOnlyWidget', 'ui:placeholder': 'Select a status', 'ui:label': 'Status', }, changeRequestPending: { - 'ui:widget': 'CheckboxWidget', + 'ui:widget': 'ReadOnlyWidget', 'ui:label': 'Change Request Pending', }, projectDescription: { 'ui:widget': 'TextAreaWidget', 'ui:label': 'Project Description', + 'ui:options': { + maxLength: 1000, + }, }, applicantContractualName: { 'ui:widget': 'TextWidget', @@ -49,7 +52,7 @@ const tombstoneUiSchema = { 'ui:label': 'Current Operating Name', }, eightThirtyMillionFunding: { - 'ui:widget': 'TextWidget', + 'ui:widget': 'RadioWidget', 'ui:label': '8.30M Funding', }, federalFundingSource: { diff --git a/app/lib/theme/widgets/CheckboxWidget.tsx b/app/lib/theme/widgets/CheckboxWidget.tsx index 99ccf7c7c5..896c67f4d9 100644 --- a/app/lib/theme/widgets/CheckboxWidget.tsx +++ b/app/lib/theme/widgets/CheckboxWidget.tsx @@ -42,9 +42,9 @@ const CheckboxWidget: React.FC = ({ required={required} aria-label={label} disabled={disabled} - onChange={(event: { target: { checked: any } }) => - onChange(event.target.checked) - } + onChange={(event: { target: { checked: any } }) => { + onChange(event.target.checked); + }} /> {label} diff --git a/app/pages/analyst/cbc/[cbcId].tsx b/app/pages/analyst/cbc/[cbcId].tsx index 5eb088cc74..3b1013058e 100644 --- a/app/pages/analyst/cbc/[cbcId].tsx +++ b/app/pages/analyst/cbc/[cbcId].tsx @@ -8,13 +8,14 @@ import CbcAnalystLayout from 'components/Analyst/CBC/CbcAnalystLayout'; import CbcForm from 'components/Analyst/CBC/CbcForm'; import styled from 'styled-components'; import ReviewTheme from 'components/Review/ReviewTheme'; -import { useRef, useState } from 'react'; -import { ProjectTheme } from 'components/Analyst/Project'; +import { useEffect, useRef, useState } from 'react'; +// import { ProjectTheme } from 'components/Analyst/Project'; import { useUpdateCbcDataByRowIdMutation } from 'schema/mutations/cbc/updateCbcData'; import review from 'formSchema/analyst/cbc/review'; import reviewUiSchema from 'formSchema/uiSchema/cbc/reviewUiSchema'; import editUiSchema from 'formSchema/uiSchema/cbc/editUiSchema'; import { useFeature } from '@growthbook/growthbook-react'; +import CbcTheme from 'components/Analyst/CBC/CbcTheme'; const getCbcQuery = graphql` query CbcIdQuery($rowId: Int!) { @@ -22,7 +23,7 @@ const getCbcQuery = graphql` projectNumber rowId sharepointTimestamp - cbcDataByCbcId { + cbcDataByCbcId(first: 500) @connection(key: "CbcData__cbcDataByCbcId") { edges { node { jsonData @@ -55,105 +56,119 @@ const RightAlignText = styled('div')` text-align: right; padding-bottom: 4px; `; - const Cbc = ({ preloadedQuery, }: RelayProps, CbcIdQuery>) => { const query = usePreloadedQuery(getCbcQuery, preloadedQuery); - const allowEdit = useFeature('show_cbc_edit').value ?? false; - const [toggleOverride, setToggleExpandOrCollapseAll] = useState< + const [toggleOverrideReadOnly, setToggleExpandOrCollapseAllReadOnly] = + useState(true); + const [toggleOverrideEdit, setToggleExpandOrCollapseAllEdit] = useState< boolean | undefined - >(undefined); - + >(true); const [editMode, setEditMode] = useState(false); const hiddenSubmitRef = useRef(null); - const { cbcByRowId, session } = query; - const { cbcDataByCbcId } = cbcByRowId; - const { edges } = cbcDataByCbcId; - const cbcData = edges[0].node; - const { jsonData } = cbcData; + const { session } = query; - const tombstone = { - projectNumber: jsonData.projectNumber, - originalProjectNumber: jsonData.originalProjectNumber, - phase: jsonData.phase, - intake: jsonData.intake, - projectStatus: jsonData.projectStatus, - projectTitle: jsonData.projectTitle, - projectDescription: jsonData.projectDescription, - applicantContractualName: jsonData.applicantContractualName, - currentOperatingName: jsonData.currentOperatingName, - eightThirtyMillionFunding: jsonData.eightThirtyMillionFunding, - federalFundingSource: jsonData.federalFundingSource, - federalProjectNumber: jsonData.federalProjectNumber, - }; + const [formData, setFormData] = useState({} as any); + const [baseFormData, setBaseFormData] = useState({} as any); + useEffect(() => { + const { cbcByRowId } = query; + const { cbcDataByCbcId } = cbcByRowId; + const { edges } = cbcDataByCbcId; + const cbcData = edges[0].node; + const { jsonData } = cbcData; + const tombstone = { + projectNumber: jsonData.projectNumber, + originalProjectNumber: jsonData.originalProjectNumber, + phase: jsonData.phase, + intake: jsonData.intake, + projectStatus: jsonData.projectStatus, + projectTitle: jsonData.projectTitle, + projectDescription: jsonData.projectDescription, + applicantContractualName: jsonData.applicantContractualName, + currentOperatingName: jsonData.currentOperatingName, + eightThirtyMillionFunding: jsonData.eightThirtyMillionFunding, + federalFundingSource: jsonData.federalFundingSource, + federalProjectNumber: jsonData.federalProjectNumber, + }; - const projectType = { - projectType: jsonData.projectType, - transportProjectType: jsonData.transportProjectType, - highwayProjectType: jsonData.highwayProjectType, - lastMileProjectType: jsonData.lastMileProjectType, - lastMileMinimumSpeed: jsonData.lastMileMinimumSpeed, - connectedCoastNetworkDependant: jsonData.connectedCoastNetworkDependant, - }; - const locationsAndCounts = { - projectLocations: jsonData.projectLocations, - communitiesAndLocalesCount: jsonData.communitiesAndLocalesCount, - indigenousCommunities: jsonData.indigenousCommunities, - householdCount: jsonData.householdCount, - transportKm: jsonData.transportKm, - highwayKm: jsonData.highwayKm, - restAreas: jsonData.restAreas, - }; + const projectType = { + projectType: jsonData.projectType, + transportProjectType: jsonData.transportProjectType, + highwayProjectType: jsonData.highwayProjectType, + lastMileProjectType: jsonData.lastMileProjectType, + lastMileMinimumSpeed: jsonData.lastMileMinimumSpeed, + connectedCoastNetworkDependant: jsonData.connectedCoastNetworkDependant, + }; + const locationsAndCounts = { + projectLocations: jsonData.projectLocations, + communitiesAndLocalesCount: jsonData.communitiesAndLocalesCount, + indigenousCommunities: jsonData.indigenousCommunities, + householdCount: jsonData.householdCount, + transportKm: jsonData.transportKm, + highwayKm: jsonData.highwayKm, + restAreas: jsonData.restAreas, + }; - const funding = { - bcFundingRequest: jsonData.bcFundingRequest, - federalFunding: jsonData.federalFunding, - applicantAmount: jsonData.applicantAmount, - otherFunding: jsonData.otherFunding, - totalProjectBudget: jsonData.totalProjectBudget, - }; + const funding = { + bcFundingRequest: jsonData.bcFundingRequest, + federalFunding: jsonData.federalFunding, + applicantAmount: jsonData.applicantAmount, + otherFunding: jsonData.otherFunding, + totalProjectBudget: jsonData.totalProjectBudget, + }; - const eventsAndDates = { - nditConditionalApprovalLetterSent: - jsonData.nditConditionalApprovalLetterSent, - bindingAgreementSignedNditRecipient: - jsonData.bindingAgreementSignedNditRecipient, - announcedByProvince: jsonData.announcedByProvince, - dateApplicationReceived: jsonData.dateApplicationReceived, - dateConditionallyApproved: jsonData.dateConditionallyApproved, - dateAgreementSigned: jsonData.dateAgreementSigned, - proposedStartDate: jsonData.proposedStartDate, - proposedCompletionDate: jsonData.proposedCompletionDate, - reportingCompletionDate: jsonData.reportingCompletionDate, - dateAnnounced: jsonData.dateAnnounced, - }; + const eventsAndDates = { + nditConditionalApprovalLetterSent: + jsonData.nditConditionalApprovalLetterSent, + bindingAgreementSignedNditRecipient: + jsonData.bindingAgreementSignedNditRecipient, + announcedByProvince: jsonData.announcedByProvince, + dateApplicationReceived: jsonData.dateApplicationReceived, + dateConditionallyApproved: jsonData.dateConditionallyApproved, + dateAgreementSigned: jsonData.dateAgreementSigned, + proposedStartDate: jsonData.proposedStartDate, + proposedCompletionDate: jsonData.proposedCompletionDate, + reportingCompletionDate: jsonData.reportingCompletionDate, + dateAnnounced: jsonData.dateAnnounced, + }; - const miscellaneous = { - projectMilestoneCompleted: jsonData.projectMilestoneCompleted, - constructionCompletedOn: jsonData.constructionCompletedOn, - milestoneComments: jsonData.milestoneComments, - primaryNewsRelease: jsonData.primaryNewsRelease, - secondaryNewsRelease: jsonData.secondaryNewsRelease, - notes: jsonData.notes, - }; + const miscellaneous = { + projectMilestoneCompleted: jsonData.projectMilestoneCompleted, + constructionCompletedOn: jsonData.constructionCompletedOn, + milestoneComments: jsonData.milestoneComments, + primaryNewsRelease: jsonData.primaryNewsRelease, + secondaryNewsRelease: jsonData.secondaryNewsRelease, + notes: jsonData.notes, + }; - const projectDataReviews = { - locked: jsonData.locked, - lastReviewed: jsonData.lastReviewed, - reviewNotes: jsonData.reviewNotes, - }; + const projectDataReviews = { + locked: jsonData.locked, + lastReviewed: jsonData.lastReviewed, + reviewNotes: jsonData.reviewNotes, + }; + + setFormData({ + tombstone, + projectType, + locationsAndCounts, + funding, + eventsAndDates, + miscellaneous, + projectDataReviews, + }); + setBaseFormData({ + tombstone, + projectType, + locationsAndCounts, + funding, + eventsAndDates, + miscellaneous, + projectDataReviews, + }); + }, [query]); - const [formData, setFormData] = useState({ - tombstone, - projectType, - locationsAndCounts, - funding, - eventsAndDates, - miscellaneous, - projectDataReviews, - }); const [updateFormData] = useUpdateCbcDataByRowIdMutation(); const handleSubmit = (e) => { @@ -162,7 +177,7 @@ const Cbc = ({ updateFormData({ variables: { input: { - rowId: cbcData.rowId, + rowId: query?.cbcByRowId?.cbcDataByCbcId?.edges[0].node.rowId || null, cbcDataPatch: { jsonData: { ...formData.tombstone, @@ -184,40 +199,47 @@ const Cbc = ({ }; const handleResetFormData = () => { + setFormData(baseFormData); setEditMode(false); - setFormData({} as any); }; return ( - + - {!editMode && ( - <> - { - setToggleExpandOrCollapseAll(true); - }} - type="button" - > - Expand all - - {' | '} - { - setToggleExpandOrCollapseAll(false); - }} - type="button" - > - Collapse all - - {' | '} - - )} + <> + { + if (editMode) { + setToggleExpandOrCollapseAllEdit(true); + return; + } + setToggleExpandOrCollapseAllReadOnly(true); + }} + type="button" + > + Expand all + + {' | '} + { + if (editMode) { + setToggleExpandOrCollapseAllEdit(false); + return; + } + setToggleExpandOrCollapseAllReadOnly(false); + }} + type="button" + > + Collapse all + + {' | '} + {allowEdit && ( { setEditMode(!editMode); + setFormData(baseFormData); }} type="button" > @@ -226,7 +248,11 @@ const Cbc = ({ )} { setFormData({ ...e.formData }); @@ -237,12 +263,12 @@ const Cbc = ({ isFormEditMode={editMode} title="CBC Form" schema={review} - theme={editMode ? ProjectTheme : ReviewTheme} + theme={editMode ? CbcTheme : ReviewTheme} uiSchema={editMode ? editUiSchema : reviewUiSchema} resetFormData={handleResetFormData} onSubmit={handleSubmit} setIsFormEditMode={setEditMode} - saveBtnText="Save & Close" + saveBtnText="Save" /> diff --git a/app/pages/analyst/cbc/[cbcId]/cbcHistory.tsx b/app/pages/analyst/cbc/[cbcId]/cbcHistory.tsx index eb7f621b7d..c02cd7e658 100644 --- a/app/pages/analyst/cbc/[cbcId]/cbcHistory.tsx +++ b/app/pages/analyst/cbc/[cbcId]/cbcHistory.tsx @@ -12,7 +12,7 @@ const getCbcHistoryQuery = graphql` projectNumber rowId sharepointTimestamp - cbcDataByCbcId { + cbcDataByCbcId(first: 500) @connection(key: "CbcData__cbcDataByCbcId") { edges { node { jsonData diff --git a/app/tests/backend/lib/excel_import/cbc_project.test.ts b/app/tests/backend/lib/excel_import/cbc_project.test.ts index 259194ab4c..ff16cbb1a3 100644 --- a/app/tests/backend/lib/excel_import/cbc_project.test.ts +++ b/app/tests/backend/lib/excel_import/cbc_project.test.ts @@ -14,11 +14,12 @@ const mockErrorData = { phase: '4b', intake: undefined, projectStatus: 'Not Applicable', + changeRequestPending: true, projectTitle: 'Program Fee (1%) - Community', projectDescription: undefined, currentOperatingName: 'Northern Development', applicantContractualName: 'Northern Development', - eightThirtyMillionFunding: 'No', + eightThirtyMillionFunding: false, federalFundingSource: undefined, federalProjectNumber: undefined, projectType: 'Program Fee', @@ -41,7 +42,7 @@ const mockErrorData = { totalProjectBudget: null, nditConditionalApprovalLetterSent: undefined, bindingAgreementSignedNditRecipient: undefined, - announcedByProvince: undefined, + announcedByProvince: true, dateApplicationReceived: null, dateConditionallyApproved: null, dateAgreementSigned: null, @@ -55,7 +56,7 @@ const mockErrorData = { primaryNewsRelease: undefined, secondaryNewsRelease: undefined, notes: undefined, - locked: undefined, + locked: true, lastReviewed: null, reviewNotes: undefined, errorLog: [ @@ -476,4 +477,105 @@ describe('cbc_project', () => { result.data.createCbcProject.cbcProject.jsonData[0].currentOperatingName ).toEqual('Northern Development'); }); + + it('should turn yes-no and x to boolean', async () => { + jest.spyOn(XLSX.utils, 'sheet_to_json').mockReturnValue([ + { ...columnList }, + { + A: 9999, + C: '4b', + E: 'Not Applicable', + F: 'Yes', + G: 'Program Fee (1%) - Community', + H: 'NULL', + I: 'Northern Development', + J: 'Northern Development', + K: 'No', + L: 'NULL', + M: 'NULL', + N: 'Program Fee', + O: 'NULL', + P: 'NULL', + Q: 'NULL', + R: 'NULL', + S: 'NULL', + T: 'NULL', + U: 'should be a number', + V: 'should be a number', + W: 'should be a number', + Y: 'should be a number', + Z: 'NULL', + AA: 'should be a number', + AB: 'should be a number', + AC: 'should be a number', + AD: 'NULL', + AE: 'NULL', + AF: 'NULL', + AG: 'NULL', + AH: 'YES', + AI: 'should be a date', + AJ: 'should be a date', + AK: 'should be a date', + AL: 'should be a date', + AM: 'should be a date', + AN: 'should be a date', + AO: 'NULL', + AP: 'should be a date', + AQ: 'should be a date', + AR: 'NULL', + AS: 'NULL', + AT: 'NULL', + AU: 'NULL', + AV: 'x', + AW: 'should be a date', + }, + ]); + + const wb = XLSX.read(null); + + mocked(performQuery).mockImplementation(async () => { + return { + data: { + createCbcProject: { + cbcProject: { + id: '1', + rowId: 1, + jsonData: [mockErrorData], + }, + clientMutationId: '1', + }, + cbcByProjectNumber: { + cbcDataByProjectNumber: { + nodes: [], + }, + }, + createCbc: { + cbc: { + rowId: 1, + }, + }, + }, + }; + }); + + const result = (await LoadCbcProjectData( + wb, + 'CBC Project', + null, + request + )) as any; + expect(result.data.createCbcProject.cbcProject.jsonData[0].locked).toEqual( + true + ); + expect( + result.data.createCbcProject.cbcProject.jsonData[0].changeRequestPending + ).toEqual(true); + expect( + result.data.createCbcProject.cbcProject.jsonData[0] + .eightThirtyMillionFunding + ).toEqual(false); + expect( + result.data.createCbcProject.cbcProject.jsonData[0].announcedByProvince + ).toEqual(true); + }); }); diff --git a/app/tests/components/Analyst/CBC/CbcChangeStatus.test.tsx b/app/tests/components/Analyst/CBC/CbcChangeStatus.test.tsx index 16d7ad91ae..d5c9f188ed 100644 --- a/app/tests/components/Analyst/CBC/CbcChangeStatus.test.tsx +++ b/app/tests/components/Analyst/CBC/CbcChangeStatus.test.tsx @@ -12,7 +12,7 @@ const testQuery = graphql` projectNumber rowId sharepointTimestamp - cbcDataByCbcId { + cbcDataByCbcId(first: 500) @connection(key: "CbcData__cbcDataByCbcId") { edges { node { jsonData diff --git a/app/tests/pages/analyst/cbc/[cbcId].test.tsx b/app/tests/pages/analyst/cbc/[cbcId].test.tsx index 920c79fd9f..fda5dc37fe 100644 --- a/app/tests/pages/analyst/cbc/[cbcId].test.tsx +++ b/app/tests/pages/analyst/cbc/[cbcId].test.tsx @@ -176,4 +176,75 @@ describe('Cbc', () => { // expect not to find one expect(isAllHidden).toBeUndefined(); }); + + it('should send the mutation on save', async () => { + jest.spyOn(moduleApi, 'useFeature').mockReturnValue(mockShowCbcEdit); + pageTestingHelper.loadQuery(); + pageTestingHelper.renderPage(); + + const editButton = screen.getByRole('button', { + name: 'Quick edit', + }); + act(() => { + fireEvent.click(editButton); + }); + + const saveButton = screen.getByRole('button', { + name: 'Save', + }); + act(() => { + fireEvent.click(saveButton); + }); + + pageTestingHelper.expectMutationToBeCalled('updateCbcDataByRowIdMutation', { + input: { + rowId: 1, + cbcDataPatch: { + jsonData: { + projectNumber: 5555, + phase: 2, + intake: 1, + projectStatus: 'Reporting Complete', + projectTitle: 'Project 1', + projectDescription: 'Description 1', + applicantContractualName: 'Internet company 1', + currentOperatingName: 'Internet company 1', + eightThirtyMillionFunding: 'No', + federalFundingSource: 'ISED-CTI', + projectType: 'Transport', + transportProjectType: 'Fibre', + connectedCoastNetworkDependant: 'NO', + projectLocations: 'Location 1', + communitiesAndLocalesCount: 5, + indigenousCommunities: 5, + householdCount: null, + transportKm: 124, + highwayKm: null, + bcFundingRequest: 5555555, + federalFunding: 555555, + applicantAmount: 555555, + otherFunding: 265000, + totalProjectBudget: 5555555, + nditConditionalApprovalLetterSent: 'YES', + bindingAgreementSignedNditRecipient: 'YES', + announcedByProvince: 'YES', + dateApplicationReceived: null, + dateConditionallyApproved: '2019-06-26T00:00:00.000Z', + dateAgreementSigned: '2021-02-24T00:00:00.000Z', + proposedStartDate: '2020-07-01T00:00:00.000Z', + proposedCompletionDate: '2023-03-31T00:00:00.000Z', + reportingCompletionDate: null, + dateAnnounced: '2019-07-02T00:00:00.000Z', + projectMilestoneCompleted: 0.5, + constructionCompletedOn: null, + milestoneComments: 'Requested extension to March 31, 2024', + primaryNewsRelease: + 'https://www.canada.ca/en/innovation-science-economic-development/news/2019/07/rural-communities-in-british-columbia-will-benefit-from-faster-internet.html', + lastReviewed: '2023-07-11T00:00:00.000Z', + reviewNotes: 'Qtrly Report: Progress 0.39 -> 0.38', + }, + }, + }, + }); + }); });