diff --git a/app/models/serializers/work_queue/correspondence_appeals_serializer.rb b/app/models/serializers/work_queue/correspondence_appeals_serializer.rb index 4e0b289ef1b..6b600874432 100644 --- a/app/models/serializers/work_queue/correspondence_appeals_serializer.rb +++ b/app/models/serializers/work_queue/correspondence_appeals_serializer.rb @@ -31,21 +31,16 @@ class WorkQueue::CorrespondenceAppealsSerializer object.appeal.issues.length end + attribute :appeal do |object| + WorkQueue::AppealSerializer.new(object.appeal, params: { user: RequestStore[:current_user] }) + end + attribute :task_added_data do |object| - tasks = [] - object.correspondences_appeals_tasks.each do |cor_app_task| - assigned_to = cor_app_task.task.assigned_to - assigned_to_text = assigned_to.is_a?(Organization) ? assigned_to.name : assigned_to.css_id - task_data = { - assigned_at: cor_app_task.task.assigned_at, - assigned_to: assigned_to_text, - assigned_to_type: cor_app_task.task.assigned_to_type, - instructions: cor_app_task.task.instructions, - type: cor_app_task.task.label - } - tasks << task_data - end - tasks + AmaAndLegacyTaskSerializer.create_and_preload_legacy_appeals( + params: { user: RequestStore[:current_user], role: "generic" }, + tasks: object.tasks, + ama_serializer: WorkQueue::TaskSerializer + ).call end attribute :status do |object| diff --git a/client/app/queue/QueueApp.jsx b/client/app/queue/QueueApp.jsx index bfad9c284e7..83ab345b0cc 100644 --- a/client/app/queue/QueueApp.jsx +++ b/client/app/queue/QueueApp.jsx @@ -1017,12 +1017,6 @@ class QueueApp extends React.PureComponent { title={`${PAGE_TITLES.USER_MANAGEMENT} | Caseflow`} render={this.routedUserManagement} /> - - { // If the url is a specified path, use it over the organization route - const orgHref = org.url.includes('/') ? org.url : `/organizations/${org.url}`; + const orgHref = org.url?.includes('/') ? org.url : `/organizations/${org.url}`; const label = correspondenceTable(org) ? org.name : sprintf(COPY.CASE_LIST_TABLE_QUEUE_DROPDOWN_TEAM_CASES_LABEL, org.name); diff --git a/client/app/queue/components/TaskRows.jsx b/client/app/queue/components/TaskRows.jsx index 491b3ac960c..44ea558f8c8 100644 --- a/client/app/queue/components/TaskRows.jsx +++ b/client/app/queue/components/TaskRows.jsx @@ -676,6 +676,7 @@ class TaskRows extends React.PureComponent { eventsFromAppeal ); + return ( {sortedTimelineEvents.map((timelineEvent, index) => { diff --git a/client/app/queue/correspondence/CorrespondenceTasksAdded.jsx b/client/app/queue/correspondence/CorrespondenceAppealTasks.jsx similarity index 73% rename from client/app/queue/correspondence/CorrespondenceTasksAdded.jsx rename to client/app/queue/correspondence/CorrespondenceAppealTasks.jsx index b0a3429cdc6..4ff975ab396 100644 --- a/client/app/queue/correspondence/CorrespondenceTasksAdded.jsx +++ b/client/app/queue/correspondence/CorrespondenceAppealTasks.jsx @@ -2,10 +2,20 @@ import React from 'react'; import PropTypes from 'prop-types'; import CaseDetailsLink from '../CaseDetailsLink'; import DocketTypeBadge from '../../components/DocketTypeBadge'; -import CorrespondenceCaseTimeline from './CorrespondenceCaseTimeline'; +import { appealWithDetailSelector, taskSnapshotTasksForAppeal } from '../selectors'; +import { useSelector } from 'react-redux'; +import TaskRows from '../components/TaskRows'; -const CorrespondenceTasksAdded = (props) => { +const CorrespondenceAppealTasks = (props) => { const veteranFullName = props.correspondence.veteranFullName; + const appealId = props.appeal.external_id; + const appeal = useSelector((state) => + appealWithDetailSelector(state, { appealId }) + ); + + const tasks = useSelector((state) => + taskSnapshotTasksForAppeal(state, { appealId }) + ); return ( <> @@ -46,15 +56,15 @@ const CorrespondenceTasksAdded = (props) => {

{props.task_added.assignedTo ? props.task_added.assignedTo.name : ''}

- +
Tasks added to appeal -
- +
@@ -63,11 +73,12 @@ const CorrespondenceTasksAdded = (props) => { ); }; -CorrespondenceTasksAdded.propTypes = { +CorrespondenceAppealTasks.propTypes = { correspondence: PropTypes.object, task_added: PropTypes.object, organizations: PropTypes.array, userCssId: PropTypes.string, + appeal: PropTypes.object }; -export default CorrespondenceTasksAdded; +export default CorrespondenceAppealTasks; diff --git a/client/app/queue/correspondence/CorrespondenceTaskRows.jsx b/client/app/queue/correspondence/CorrespondenceTaskRows.jsx index 65ae7bed39a..bbd34cedf09 100644 --- a/client/app/queue/correspondence/CorrespondenceTaskRows.jsx +++ b/client/app/queue/correspondence/CorrespondenceTaskRows.jsx @@ -43,7 +43,7 @@ class CorrespondenceTaskRows extends React.PureComponent { this.state = { taskInstructionsIsVisible: [], showEditNodDateModal: false, - activeTasks: [props.taskList], + activeTasks: props.taskList, }; } @@ -95,12 +95,12 @@ class CorrespondenceTaskRows extends React.PureComponent { }; taskInstructionsWithLineBreaks = (task) => { - if (!task.instructions || !task.instructions.length) { + if (!task.instructions || !task.instructions?.length) { return
; } return ( - + {task.instructions.map((text) => (
{ + if (!task.instructions || !task.instructions?.length > 0) { + return null; + } + const taskInstructionsVisible = this.state.taskInstructionsIsVisible.includes(task.label); return ( @@ -146,7 +150,7 @@ class CorrespondenceTaskRows extends React.PureComponent { }; showActionsListItem = (task, correspondence) => { - if (task.availableActions.length <= 0) { + if (task.availableActions?.length === 0) { return null; } @@ -187,7 +191,7 @@ class CorrespondenceTaskRows extends React.PureComponent { const timelineTitle = isCancelled(task) ? `${task.type} cancelled` : task.timelineTitle; return ( - + {isCancelled(task) ? : closedAtIcon(task, timeline)} - {((index < sortedTimelineEvents.length && timeline) || - (index < this.state.activeTasks.length - 1 && !timeline)) && ( + {((index < sortedTimelineEvents?.length && timeline) || + (index < this.state.activeTasks?.length - 1 && !timeline)) && (
)} diff --git a/client/app/queue/correspondence/details/CorrespondenceDetails.jsx b/client/app/queue/correspondence/details/CorrespondenceDetails.jsx index 00b2fa7ba18..ce1ef3c4d07 100644 --- a/client/app/queue/correspondence/details/CorrespondenceDetails.jsx +++ b/client/app/queue/correspondence/details/CorrespondenceDetails.jsx @@ -14,7 +14,8 @@ import { import CorrespondenceResponseLetters from './CorrespondenceResponseLetters'; import COPY from '../../../../COPY'; import CaseListTable from 'app/queue/CaseListTable'; -import CorrespondenceTasksAdded from '../CorrespondenceTasksAdded'; +import { prepareAppealForSearchStore, prepareAppealForStore, prepareTasksForStore } from 'app/queue/utils'; +import { onReceiveTasks, onReceiveAppealDetails } from '../../QueueActions'; import moment from 'moment'; import Pagination from 'app/components/Pagination/Pagination'; import Table from 'app/components/Table'; @@ -22,9 +23,11 @@ import { ExternalLinkIcon } from 'app/components/icons/ExternalLinkIcon'; import { COLORS } from 'app/constants/AppConstants'; import Checkbox from 'app/components/Checkbox'; import CorrespondencePaginationWrapper from 'app/queue/correspondence/CorrespondencePaginationWrapper'; + import Button from '../../../components/Button'; import Alert from '../../../components/Alert'; import ApiUtil from '../../../util/ApiUtil'; +import CorrespondenceAppealTasks from '../CorrespondenceAppealTasks'; const CorrespondenceDetails = (props) => { const dispatch = useDispatch(); @@ -364,6 +367,28 @@ const CorrespondenceDetails = (props) => { useEffect(() => { dispatch(loadCorrespondence(correspondence)); dispatch(correspondenceInfo(correspondence)); + // load appeals related to the correspondence into the store + const corAppealTasks = []; + + props.correspondence.correspondenceAppeals.map((corAppeal) => { + dispatch(onReceiveAppealDetails(prepareAppealForStore([corAppeal.appeal.data]))); + + corAppeal.taskAddedData.data.map((taskData) => { + const formattedTask = {}; + + formattedTask[taskData.id] = taskData; + + corAppealTasks.push(taskData); + }); + + }); + // // load appeal tasks into the store + const preparedTasks = prepareTasksForStore(corAppealTasks); + + dispatch(onReceiveTasks({ + amaTasks: preparedTasks + })); + }, []); const isTasksUnrelatedToAppealEmpty = () => { @@ -438,11 +463,12 @@ const CorrespondenceDetails = (props) => { )} {(props.correspondence.correspondenceAppeals.map((taskAdded) => - taskAdded.correspondencesAppealsTasks?.length > 0 && ) )} diff --git a/client/test/app/queue/correspondences/details/CorrespondenceDetails.test.js b/client/test/app/queue/correspondences/details/CorrespondenceDetails.test.js index c4bebc3cb5a..12f597a3554 100644 --- a/client/test/app/queue/correspondences/details/CorrespondenceDetails.test.js +++ b/client/test/app/queue/correspondences/details/CorrespondenceDetails.test.js @@ -350,7 +350,6 @@ describe('CorrespondenceDetails', () => { expect(document.getElementsByClassName('plus-symbol').length).toBe(1); // Existing Appeals Table and Columns - fireEvent.click(existingAppealButton); expect(screen.getByText('Existing Appeals')).toBeInTheDocument(); expect(screen.getByText('Appellant Name')).toBeInTheDocument(); expect(screen.getByText('Appeal Status')).toBeInTheDocument(); diff --git a/spec/feature/queue/correspondence/correspondence_details_task_actions_spec.rb b/spec/feature/queue/correspondence/correspondence_details_task_actions_spec.rb index 2dd422521f7..9604a7ddb48 100644 --- a/spec/feature/queue/correspondence/correspondence_details_task_actions_spec.rb +++ b/spec/feature/queue/correspondence/correspondence_details_task_actions_spec.rb @@ -75,12 +75,19 @@ it "Verify #{task_action[:name]} task with Assign to team action dropdown" do visit "/queue/correspondence/#{@correspondence.uuid}" + # find + dropdowns and click last one for tasks unrelated to appeal + dropdowns = page.all(".cf-btn-link") + dropdowns.last.click + click_dropdown(prompt: "Select an action", text: "Assign to team") expect(page).to have_content("Assign Task") expect(page).to have_content("Select a team") click_dropdown(prompt: "Select or search", text: "Education") find(".cf-form-textarea", match: :first).fill_in with: "Assign task instructions" click_button "Assign-Task-button-id-1" + # find + dropdowns and click last one for tasks unrelated to appeal + dropdowns = page.all(".cf-btn-link") + dropdowns.last.click expect(page).to have_content("#{task_action[:name]} task has been assigned to Education.") expect(all(".cf-row-wrapper")[1].text).to include("Education") expect(all(".cf-row-wrapper")[2].text).to include(task_action[:name].to_s) @@ -90,12 +97,18 @@ it "Verify #{task_action[:name]} task with Change task type action dropdown" do visit "/queue/correspondence/#{@correspondence.uuid}" + # find + dropdowns and click last one for tasks unrelated to appeal + dropdowns = page.all(".cf-btn-link") + dropdowns.last.click click_dropdown(prompt: "Select an action", text: "Change task type") expect(page).to have_content("Change task type") expect(page).to have_content("Select another task type from the list of available options:") click_dropdown(prompt: "Select an action type", text: "CAVC Correspondence") find(".cf-form-textarea", match: :first).fill_in with: "Change task type instructions" click_button "Change-task-type-button-id-1" + # find + dropdowns and click last one for tasks unrelated to appeal + dropdowns = page.all(".cf-btn-link") + dropdowns.last.click expect(page).to have_content("You have changed the task type from #{task_action[:name]} " \ "to CAVC Correspondence. These changes are now reflected in the tasks section below.") expect(all(".cf-row-wrapper")[2].find("dd").text).to eq("CAVC Correspondence") diff --git a/spec/support/correspondece_task_actions_helpers.rb b/spec/support/correspondece_task_actions_helpers.rb index f953763e6c9..f956edd16c4 100644 --- a/spec/support/correspondece_task_actions_helpers.rb +++ b/spec/support/correspondece_task_actions_helpers.rb @@ -91,9 +91,20 @@ def check_task_action(options = {}) expected_message = options[:expected_message] visit "/queue/correspondence/#{correspondence.uuid}" + expect(page).to have_current_path("/queue/correspondence/#{correspondence.uuid}") + + # find + dropdowns and click last one for tasks unrelated to appeal + dropdowns = page.all(".cf-btn-link") + dropdowns.last.click + click_dropdown(prompt: "Select an action", text: action) find(".cf-form-textarea", match: :first).fill_in with: form_text click_button button_id + expect(page).to have_current_path("/queue/correspondence/#{correspondence.uuid}") + # find + dropdowns and click last one for tasks unrelated to appeal + dropdowns = page.all(".cf-btn-link") + dropdowns.last.click + expect(page).to have_content("#{task_name} #{expected_message}") end end