Skip to content
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

No errors found upload transcript to VBMS modal #23349

Draft
wants to merge 5 commits into
base: feature/APPEALS-49620-and-APPEALS-49626
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 17 additions & 0 deletions app/controllers/tasks_controller.rb

Choose a reason for hiding this comment

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

You could reduce this method's indentations by using a return unless clause instead of if.

def upload_transcription_to_vbms
  return unless task.type == "ReviewTranscriptTask" && task.status == "in_progress"
  
  ...
end 

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Choose a reason for hiding this comment

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

I apologize for being unclear.

For code cleanliness, leave an empty line below the return command, and remove one level of indentation through the rest of the method.

Functionally there's no difference, but its the sort of thing RuboCop's Layout Cop looks for.

Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,23 @@ def request_hearing_disposition_change
}
end

def upload_transcription_to_vbms
return unless task.type == "ReviewTranscriptTask" && task.status == "in_progress"
new_instructions = task.instructions.push(params[:task][:instructions])

Transcription.where(task_id: task.id).update_all(
updated_by_id: current_user.id,
uploaded_to_vbms_date: Time.zone.now,
updated_at: Time.zone.now
)

Task.where(id: task.id).update_all(
instructions: new_instructions,
status: Constants.TASK_STATUSES.completed,
closed_at: Time.zone.now
)
end

private

def send_initial_notification_letter
Expand Down
1 change: 0 additions & 1 deletion app/models/tasks/assign_hearing_disposition_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ def schedule_later(instructions: nil, with_admin_action_klass: nil, admin_action
end

def create_transcription_and_maybe_evidence_submission_window_tasks
# binding.pry
transcription_task = TranscriptionTask.create!(
appeal: appeal,
parent: self,
Expand Down
7 changes: 6 additions & 1 deletion client/COPY.json
Original file line number Diff line number Diff line change
Expand Up @@ -1614,5 +1614,10 @@
"DATE_PICKER_DROPDOWN_LABEL": "Date filter parameters",
"DATE_PICKER_QUICK_BUTTON_30": "Last 30 days",
"WORK_ORDER_BANNER_MESSAGE": "Work Order Transcription Package will need to be manually removed from the box.com folder for %s, please inform %s as they may have picked up the Work Order",
"HEARING_BANNER_MESSAGE": "All Hearing files have been set back to the UnAssigned state for Dispatching"
"HEARING_BANNER_MESSAGE": "All Hearing files have been set back to the UnAssigned state for Dispatching",
"UPLOAD_TRANSCRIPTION_VBMS_TEXT": "By uploading to VBMS, you are confirming that you have reviewed the transcript in Caseflow and have found no errors.",
"UPLOAD_TRANSCRIPTION_VBMS_TEXT_AREA": "Please provide context and instructions for this action",
"UPLOAD_TRANSCRIPTION_VBMS_TITLE": "Upload transcript to VBMS",
"UPLOAD_TRANSCRIPTION_VBMS_BUTTON": "Upload to VBMS"

}
11 changes: 11 additions & 0 deletions client/app/queue/QueueApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import AddPrivateBarModal from './AddPrivateBarModal';
import LookupParticipantIdModal from './LookupParticipantIdModal';
import PostponeHearingTaskModal from './PostponeHearingTaskModal';
import ChangeTaskTypeModal from './ChangeTaskTypeModal';
import UploadTranscriptionVBMSNoErrorModal from './UploadTranscriptionVBMSNoErrorModal';
import SetOvertimeStatusModal from './SetOvertimeStatusModal';
import StartHoldModal from './components/StartHoldModal';
import EndHoldModal from './components/EndHoldModal';
Expand Down Expand Up @@ -547,6 +548,10 @@ class QueueApp extends React.PureComponent {
<ChangeTaskTypeModal {...props.match.params} />
);

routedUploadTranscriptionVBMSModal = (props) => (
<UploadTranscriptionVBMSNoErrorModal {...props.match.params} />
);

routedChangeHearingRequestTypeToVirtual = (props) => (
<HearingTypeConversionContainer type="Virtual" {...props.match.params} />
);
Expand Down Expand Up @@ -1405,6 +1410,12 @@ class QueueApp extends React.PureComponent {
})
}
/>
<PageRoute
exact
path="/queue/appeals/:appealId/tasks/:taskId/modal/upload_transcription_vbms"
title={`${PAGE_TITLES.UPLOAD_TRANSCRIPTION_VBMS} | Caseflow`}
render={this.routedUploadTranscriptionVBMSModal}
/>

<Route
path="/organizations/:organization/modal/bulk_assign_tasks"
Expand Down
121 changes: 121 additions & 0 deletions client/app/queue/UploadTranscriptionVBMSNoErrorModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { withRouter } from 'react-router-dom';

import TextareaField from '../components/TextareaField';

import { highlightInvalidFormItems, requestPatch } from './uiReducer/uiActions';
import { setAppealAttrs, onReceiveAmaTasks } from './QueueActions';

import {
appealWithDetailSelector,
taskById
} from './selectors';
import { marginTop } from './constants';
import COPY from '../../COPY';

import QueueFlowModal from './components/QueueFlowModal';

class UploadTranscriptionVBMSNoErrorModal extends React.PureComponent {

constructor(props) {
super(props);

this.state = {
instructions: '',
};
}

validateForm = () => Boolean(this.state.instructions);

prependUrlToInstructions = () => {
return this.state.instructions;
};

buildPayload = () => {
return {
data: {
task: {
instructions: this.prependUrlToInstructions()
}
}
};
}

submit = () => {
const { task } = this.props;
const payload = this.buildPayload();

return this.props.requestPatch(`/tasks/${task.taskId}/upload_transcription_to_vbms`, payload).
then((response) => {
this.props.onReceiveAmaTasks({ amaTasks: response.body.tasks.data });
}).
catch(() => {
// handle the error from the frontend
});
}

actionForm = () => {
const { instructions } = this.state;

return <React.Fragment>
<div>
<div>{COPY.UPLOAD_TRANSCRIPTION_VBMS_TEXT}</div>
<div {...marginTop(4)}>
<TextareaField
name={COPY.UPLOAD_TRANSCRIPTION_VBMS_TEXT_AREA}
onChange={(value) => this.setState({ instructions: value })}
placeholder= "This is the reason this is being put on hold."
value={instructions} />
</div>
</div>
</React.Fragment>;
};

render = () => {
return <QueueFlowModal
validateForm={this.validateForm}
submit={this.submit}
title={COPY.UPLOAD_TRANSCRIPTION_VBMS_TITLE}
button={COPY.UPLOAD_TRANSCRIPTION_VBMS_BUTTON}
pathAfterSubmit={`/queue/appeals/${this.props.appealId}`}
submitButtonClassNames={['usa-button']}
submitDisabled={!this.validateForm()}
>
{ this.actionForm() }
</QueueFlowModal>;
}
}

UploadTranscriptionVBMSNoErrorModal.propTypes = {
appealId: PropTypes.string,
error: PropTypes.shape({
title: PropTypes.string,
detail: PropTypes.string
}),
highlightInvalidFormItems: PropTypes.func,
onReceiveAmaTasks: PropTypes.func,
requestPatch: PropTypes.func,
setAppealAttrs: PropTypes.func,
task: PropTypes.shape({
taskId: PropTypes.string,
type: PropTypes.string,
})
};

const mapStateToProps = (state, ownProps) => ({
error: state.ui.messages.error,
appeal: appealWithDetailSelector(state, ownProps),
task: taskById(state, { taskId: ownProps.taskId })
});

const mapDispatchToProps = (dispatch) => bindActionCreators({
highlightInvalidFormItems,
requestPatch,
onReceiveAmaTasks,
setAppealAttrs
}, dispatch);

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(UploadTranscriptionVBMSNoErrorModal));
1 change: 1 addition & 0 deletions client/app/queue/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export const PAGE_TITLES = {
REMOVE_HEARING_TO_CORRECT_ERROR: 'Remove hearing to correct a scheduling error',
POSTPONE_HEARING: 'Postpone Hearing',
CHANGE_TASK_TYPE: 'Change Task Type',
UPLOAD_TRANSCRIPTION_VBMS: 'Upload transcription VBMS',
CONVERT_HEARING_TO_VIRTUAL: 'Change Hearing Request Type to Virtual',
CONVERT_HEARING_TO_VIDEO: 'Change Hearing Request Type to Video',
CONVERT_HEARING_TO_CENTRAL: 'Change Hearing Request Type to Central',
Expand Down
4 changes: 3 additions & 1 deletion client/constants/TASK_ACTIONS.json
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,9 @@
"func": "cancel_task_and_return_to_sct_action"
},
"TRANSCRIPT_NO_ERRORS_FOUND": {
"label": "No errors found: Upload transcript to VBMS"
"label": "No errors found: Upload transcript to VBMS",
"value": "modal/upload_transcription_vbms",
"func": "change_task_type_data"
},
"TRANSCRIPT_ERRORS_FOUND_AND_CORRECTED": {
"label": "Errors found and corrected: Upload transcript to VBMS"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';
import { MemoryRouter, Route } from 'react-router';
import { render, screen, act } from '@testing-library/react';
import { Provider } from 'react-redux';
import { applyMiddleware, createStore, compose } from 'redux';
import thunk from 'redux-thunk';
import UploadTranscriptionVBMSNoErrorModal from '../../../../app/queue/UploadTranscriptionVBMSNoErrorModal';
import {
createQueueReducer,
getAppealId,
getTaskId
} from './modalUtils';
import { UploadTranscriptionVBMSNoErrorData } from '../../../data/queue/taskActionModals/taskActionModalData';
import userEvent from '@testing-library/user-event';
import ApiUtil from '../../../../app/util/ApiUtil';
jest.mock('../../../../app/util/ApiUtil');

const renderUploadTranscriptionVBMSNoErrorModal = (storeValues, taskType) => {
const appealId = getAppealId(storeValues);
const taskId = getTaskId(storeValues, taskType);

const queueReducer = createQueueReducer(storeValues);
const store = createStore(
queueReducer,
compose(applyMiddleware(thunk))
);

const path = `/queue/appeals/${appealId}/tasks/${taskId}/modal/upload_transcription_vbms`;

return render(
<Provider store={store}>
<MemoryRouter initialEntries={[path]}>
<Route component={(props) => {
return <UploadTranscriptionVBMSNoErrorModal {...props.match.params} />;
}} path="/queue/appeals/:appealId/tasks/:taskId/modal/upload_transcription_vbms" />
</MemoryRouter>
</Provider>
);
};

describe('UploadTranscriptionVBMSNoErrorModal', () => {
const setUpModal = () => renderUploadTranscriptionVBMSNoErrorModal(UploadTranscriptionVBMSNoErrorData, 'RootTask');

describe('on modal open', () => {
test('modal title: "Upload transcript to VBMS"', () => {
setUpModal();

expect(screen.getByRole('heading', { level: 1 })).toBeTruthy();
});

test('submit button is initially disabled', () => {
setUpModal();

expect(screen.getByText('Upload to VBMS', { selector: 'button' })).toBeDisabled();
});
});

describe('Button Disabled until text field is populated', () => {
const instructionsLabel = 'Please provide context and instructions for this action';

test('instructions field is present', async () => {
jest.useFakeTimers('modern');
setUpModal();

const response = { status: 200, body: { document_presence: true } };

ApiUtil.get.mockResolvedValue(response);
await act(async() => jest.runAllTimers());
userEvent.type(screen.getByLabelText(instructionsLabel), 'This is a test.');
jest.runAllTimers();
expect(screen.getByText('Upload to VBMS', { selector: 'button' })).toBeEnabled();
});
});
});
Loading
Loading