From f7b4f77ba32ce7f25182d5a0e3c933a5fe18aabc Mon Sep 17 00:00:00 2001 From: Abijith Sebastian <98075058+AbijithS-aot@users.noreply.github.com> Date: Thu, 1 Feb 2024 21:50:09 -0800 Subject: [PATCH] Task rework (#1859) * follow update uncheck fixed * task variable insert button disabled if no task variables entered * optimized task header * task header updations * task page optimizations and rework * test case fixes * removed taskHeader --------- Co-authored-by: AbijithS-aot <abijith.s@aot-technololgies.com> --- ...der.test.js => TaskHeaderListView.test.js} | 28 +- .../ServiceFlow/details/ServiceTaskDetails.js | 35 +- .../ServiceFlow/details/TaskHeader.js | 308 ---------------- .../ServiceFlow/details/TaskHeaderListView.js | 103 ++---- .../src/components/ServiceFlow/index.js | 235 ++++++------ .../ServiceFlow/list/ServiceTaskList.js | 14 +- .../ServiceFlow/list/ServiceTaskListView.js | 23 +- .../ServiceFlow/list/TaskVariable.js | 34 +- .../list/search/TaskFilterComponent.js | 134 ------- .../list/search/TaskFilterDropdown.js | 20 -- .../list/search/TaskFilterDropdownListView.js | 0 .../list/search/TaskFilterSearch.js | 338 ------------------ .../list/search/TaskFilterSearchType.js | 51 --- ...omponent.js => TaskFilterViewComponent.js} | 5 +- .../list/search/TaskIgnoreCaseComponent.js | 70 ---- ...rchBarListView.js => TaskSearchBarView.js} | 4 +- .../list/sort/TaskAttributeComponent.js | 1 - 17 files changed, 237 insertions(+), 1166 deletions(-) rename forms-flow-web/src/_tests_/test-components/test-serviceflow/details/{Taskheader.test.js => TaskHeaderListView.test.js} (68%) delete mode 100644 forms-flow-web/src/components/ServiceFlow/details/TaskHeader.js delete mode 100644 forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterComponent.js delete mode 100644 forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterDropdown.js delete mode 100644 forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterDropdownListView.js delete mode 100644 forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterSearch.js delete mode 100644 forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterSearchType.js rename forms-flow-web/src/components/ServiceFlow/list/search/{TaskFilterListViewComponent.js => TaskFilterViewComponent.js} (99%) delete mode 100644 forms-flow-web/src/components/ServiceFlow/list/search/TaskIgnoreCaseComponent.js rename forms-flow-web/src/components/ServiceFlow/list/search/{TaskSearchBarListView.js => TaskSearchBarView.js} (97%) diff --git a/forms-flow-web/src/_tests_/test-components/test-serviceflow/details/Taskheader.test.js b/forms-flow-web/src/_tests_/test-components/test-serviceflow/details/TaskHeaderListView.test.js similarity index 68% rename from forms-flow-web/src/_tests_/test-components/test-serviceflow/details/Taskheader.test.js rename to forms-flow-web/src/_tests_/test-components/test-serviceflow/details/TaskHeaderListView.test.js index e52f176b95..e09d79d33f 100644 --- a/forms-flow-web/src/_tests_/test-components/test-serviceflow/details/Taskheader.test.js +++ b/forms-flow-web/src/_tests_/test-components/test-serviceflow/details/TaskHeaderListView.test.js @@ -1,4 +1,4 @@ -import TaskHeader from "../../../../components/ServiceFlow/details/TaskHeader"; +import TaskHeaderListView from "../../../../components/ServiceFlow/details/TaskHeaderListView"; import configureStore from "redux-mock-store"; import { Provider } from "react-redux"; import { fireEvent, render, screen } from "@testing-library/react"; @@ -7,7 +7,7 @@ import "@testing-library/jest-dom/extend-expect"; let store; let mockStore = configureStore([]); -it("Should render the Taskheader component without breaking", () => { +it("Should render the Taskheader component without breaking", async() => { store = mockStore({ bpmTasks: { taskDetail: { @@ -41,7 +41,20 @@ it("Should render the Taskheader component without breaking", () => { selectedFilter: "", listReqParams: "", firstResult: "", + vissibleAttributes:{ + taskVisibleAttributes:{ + applicationId:true, + assignee:true, + createdDate:true, + dueDate:true, + followUp:true, + groups:true, + priority:true, + taskTitle:true, + } + }, }, + user: { userDetail: { preferred_username: "", @@ -51,14 +64,13 @@ it("Should render the Taskheader component without breaking", () => { store.dispatch = jest.fn(); render( <Provider store={store}> - <TaskHeader /> + <TaskHeaderListView /> </Provider> ); - expect(screen.getByText("Review Submission")).toBeInTheDocument(); - expect(screen.getByText("Submission ID# 35")).toBeInTheDocument(); - expect(screen.getByText("Set follow-up Date")).toBeInTheDocument(); - expect(screen.getByText("Add groups")).toBeInTheDocument(); - expect(screen.getByText("Claim")).toBeInTheDocument(); + + expect(screen.getByText("Follow up Date")).toBeInTheDocument(); + expect(screen.getByText("Due Date")).toBeInTheDocument(); + expect(screen.getByText("Assign to Me")).toBeInTheDocument(); const claimbtn = screen.getByTestId("clam-btn"); fireEvent.click(claimbtn); expect(store.dispatch.mock.calls).toHaveLength(2); diff --git a/forms-flow-web/src/components/ServiceFlow/details/ServiceTaskDetails.js b/forms-flow-web/src/components/ServiceFlow/details/ServiceTaskDetails.js index c27edf4388..9811491e4b 100644 --- a/forms-flow-web/src/components/ServiceFlow/details/ServiceTaskDetails.js +++ b/forms-flow-web/src/components/ServiceFlow/details/ServiceTaskDetails.js @@ -1,6 +1,5 @@ import React, { useCallback, useEffect, useState } from "react"; -import { Tab, Tabs } from "react-bootstrap"; -import TaskHeader from "./TaskHeader"; +import { Card, Col, Row, Tab, Tabs } from "react-bootstrap"; import { reloadTaskFormSubmission, setBPMTaskDetailLoader, @@ -45,6 +44,7 @@ import NoTaskSelectedMessage from "../../../components/ServiceFlow/NoTaskSelec import { bpmActionError } from "../../../actions/bpmTaskActions"; import { setCustomSubmission } from "../../../actions/checkListActions"; +import TaskHeaderListView from "./TaskHeaderListView"; const ServiceFlowTaskDetails = React.memo(() => { const { t } = useTranslation(); const { taskId } = useParams(); @@ -265,8 +265,37 @@ const ServiceFlowTaskDetails = React.memo(() => { return ( <div className="service-task-details"> <LoadingOverlay active={isTaskUpdating} spinner text={t("Loading...")}> - <TaskHeader /> + <Card className="me-2 bg-light"> + <Card.Body> + <div className="d-flex justify-content-between"> + <Col > + <Row className="ms-0 task-header">{task?.name}</Row> + <Row className="ms-0 task-name"> + <span className="application-id" data-title={t("Process Name")}> + {" "} + { + getProcessDataObjectFromList(processList, + task?.processDefinitionId) + ?.name + } + </span> + </Row> + <Row className="ms-0"> + <span data-title={t("Application ID")} className="application-id"> + {t("Application ID")}# {task?.applicationId} + </span> + </Row> + <Row className="ms-0 mt-3"> + <TaskHeaderListView + task={task} taskId={task?.id} groupView={true} + /> + </Row> + </Col> + </div> + </Card.Body> + </Card> <Tabs defaultActiveKey="form" id="service-task-details" mountOnEnter> + <Tab eventKey="form" title={t("Form")}> <LoadingOverlay active={task?.assignee !== currentUser} diff --git a/forms-flow-web/src/components/ServiceFlow/details/TaskHeader.js b/forms-flow-web/src/components/ServiceFlow/details/TaskHeader.js deleted file mode 100644 index 362f8e32b6..0000000000 --- a/forms-flow-web/src/components/ServiceFlow/details/TaskHeader.js +++ /dev/null @@ -1,308 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { Row, Col } from "react-bootstrap"; -import { - getISODateTime, - getFormattedDateAndTime, - getProcessDataObjectFromList, -} from "../../../apiManager/services/formatterService"; -import { useDispatch, useSelector } from "react-redux"; -import DatePicker from "react-datepicker"; -import moment from "moment"; -import "react-datepicker/dist/react-datepicker.css"; -import "./../ServiceFlow.scss"; -import AddGroupModal from "./AddGroupModal"; -import { - claimBPMTask, - fetchServiceTaskList, - getBPMTaskDetail, - unClaimBPMTask, - updateAssigneeBPMTask, - updateBPMTask, -} from "../../../apiManager/services/bpmTaskServices"; -import { setBPMTaskDetailUpdating } from "../../../actions/bpmTaskActions"; -import UserSelectionDebounce from "./UserSelectionDebounce"; -import SocketIOService from "../../../services/SocketIOService"; -import { useTranslation } from "react-i18next"; - -const TaskHeader = React.memo(() => { - const task = useSelector((state) => state.bpmTasks.taskDetail); - const taskId = useSelector((state) => state.bpmTasks.taskId); - const processList = useSelector((state) => state.bpmTasks.processList); - const username = useSelector( - (state) => state.user?.userDetail?.preferred_username || "" - ); - const taskGroups = useSelector((state) => state.bpmTasks.taskGroups); - const selectedFilter = useSelector((state) => state.bpmTasks.selectedFilter); - const reqData = useSelector((state) => state.bpmTasks.listReqParams); - const firstResult = useSelector((state) => state.bpmTasks.firstResult); - const [followUpDate, setFollowUpDate] = useState(null); - const [dueDate, setDueDate] = useState(null); - const [showModal, setModal] = useState(false); - const [isEditAssignee, setIsEditAssignee] = useState(false); - const dispatch = useDispatch(); - const { t } = useTranslation(); - useEffect(() => { - const followUp = task?.followUp ? new Date(task?.followUp) : null; - setFollowUpDate(followUp); - }, [task?.followUp]); - - useEffect(() => { - const due = task?.due ? new Date(task?.due) : null; - setDueDate(due); - }, [task?.due]); - - const updateBpmTasksAndDetails = (err) =>{ - if (!err) { - if (!SocketIOService.isConnected()) { - if (selectedFilter) { - dispatch(getBPMTaskDetail(taskId)); - dispatch( - fetchServiceTaskList(reqData,null,firstResult) - ); - } else { - dispatch(setBPMTaskDetailUpdating(false)); - } - } - - } else { - dispatch(setBPMTaskDetailUpdating(false)); - } - }; - - const onClaim = () => { - dispatch(setBPMTaskDetailUpdating(true)); - dispatch( - // eslint-disable-next-line no-unused-vars - claimBPMTask(taskId, username,updateBpmTasksAndDetails) - ); - }; - - const onChangeClaim = (userId) => { - setIsEditAssignee(false); - if (userId && userId !== task.assignee) { - dispatch(setBPMTaskDetailUpdating(true)); - dispatch( - // eslint-disable-next-line no-unused-vars - updateAssigneeBPMTask(taskId, userId, updateBpmTasksAndDetails) - ); - } - }; - - const onUnClaimTask = () => { - dispatch(setBPMTaskDetailUpdating(true)); - dispatch( - // eslint-disable-next-line no-unused-vars - unClaimBPMTask(taskId, updateBpmTasksAndDetails) - ); - }; - - const onFollowUpDateUpdate = (followUpDate) => { - setFollowUpDate(followUpDate); - dispatch(setBPMTaskDetailUpdating(true)); - const updatedTask = { - ...task, - ...{ followUp: followUpDate ? getISODateTime(followUpDate) : null }, - }; - dispatch( - // eslint-disable-next-line no-unused-vars - updateBPMTask(taskId, updatedTask, updateBpmTasksAndDetails) - ); - }; - - const onDueDateUpdate = (dueDate) => { - setDueDate(dueDate); - dispatch(setBPMTaskDetailUpdating(true)); - const updatedTask = { - ...task, - ...{ due: dueDate ? getISODateTime(dueDate) : null }, - }; - dispatch( - // eslint-disable-next-line no-unused-vars - updateBPMTask(taskId, updatedTask, updateBpmTasksAndDetails) - ); - }; - - // eslint-disable-next-line no-unused-vars - const FollowUpDateInput = React.forwardRef(({ value, onClick }, ref) => { - return ( - <div onClick={onClick} ref={ref}> - <i className="fa fa-calendar me-1" />{" "} - {followUpDate ? ( - <span className="me-4">{moment(followUpDate).fromNow()}</span> - ) : ( - t("Set follow-up Date") - )} - </div> - ); - }); - - // eslint-disable-next-line no-unused-vars - const DueDateInput = React.forwardRef(({ value, onClick }, ref) => { - return ( - <div onClick={onClick} ref={ref}> - <i className="fa fa-bell me-1" />{" "} - {dueDate ? ( - <span className="me-4">{moment(dueDate).fromNow()}</span> - ) : ( - t("Set Due date") - )} - </div> - ); - }); - - const getGroups = (groups) => { - return groups?.map((group) => group.groupId).join(", "); - }; - - return ( - <> - <AddGroupModal - modalOpen={showModal} - onClose={() => setModal(false)} - groups={taskGroups} - /> - <Row className="mx-0 task-header">{task?.name}</Row> - <Row className="mx-0 task-name"> - <span className="application-id" - title={t("Process Name")} - data-bs-toggle="tooltip" - > - {" "} - { - getProcessDataObjectFromList(processList, task?.processDefinitionId) - ?.name - } - </span> - </Row> - <Row className="mx-0"> - <span - title={t("Submission ID")} - data-bs-toggle="tooltip" - className="application-id"> - {t("Submission ID")}# {task?.applicationId} - </span> - </Row> - <Row className="actionable mb-4 mx-0"> - <Col - sm={followUpDate ? 2 : "auto"} - data-bs-toggle="tooltip" - title={ - followUpDate - ? getFormattedDateAndTime(followUpDate) - : t("Set FollowUp Date") - } - className="date-container" - > - <DatePicker - selected={followUpDate} - onChange={onFollowUpDateUpdate} - showTimeSelect - isClearable - popperPlacement="bottom-start" - popperModifiers={{ - offset: { - enabled: true, - offset: "5px, 10px", - }, - preventOverflow: { - enabled: true, - escapeWithReference: false, - boundariesElement: "viewport", - }, - }} - customInput={<FollowUpDateInput />} - /> - </Col> - <Col - sm={dueDate ? 2 : "auto"} - data-bs-toggle="tooltip" - title={ - dueDate ? getFormattedDateAndTime(dueDate) : t("Set Due date") - } - className="date-container" - > - <DatePicker - selected={dueDate} - onChange={onDueDateUpdate} - showTimeSelect - isClearable - shouldCloseOnSelect - popperPlacement="bottom-start" - popperModifiers={{ - offset: { - enabled: true, - offset: "5px, 10px", - }, - preventOverflow: { - enabled: true, - escapeWithReference: false, - boundariesElement: "viewport", - }, - }} - customInput={<DueDateInput />} - /> - </Col> - <Col - className="center-position" - sm={4} - onClick={() => setModal(true)} - title={t("Groups")} - data-bs-toggle="tooltip" - > - <i className="fa fa-group me-1" /> - {taskGroups.length === 0 ? ( - <span>{t("Add groups")}</span> - ) : ( - <span className="group-align">{getGroups(taskGroups)}</span> - )} - </Col> - <Col className="right-side"> - {isEditAssignee ? ( - task?.assignee ? ( - <span> - <UserSelectionDebounce - onClose={() => setIsEditAssignee(false)} - currentUser={task.assignee} - onChangeClaim={onChangeClaim} - /> - </span> - ) : ( - <span data-testid="clam-btn" onClick={onClaim}> - {" "} - {t("Claim")} - </span> - ) - ) : ( - <> - <i className="fa fa-user me-1" /> - {task?.assignee ? ( - <span> - <span - className="change-tooltip" - onClick={() => setIsEditAssignee(true)} - title={t("Click to Change Assignee")} - data-bs-toggle="tooltip" - > - {task.assignee} - </span> - <i - className="fa fa-times ms-1" - onClick={onUnClaimTask} - title={t("Reset Assignee")} - data-bs-toggle="tooltip" - /> - </span> - ) : ( - <span data-testid="clam-btn" onClick={onClaim}> - {t("Claim")} - </span> - )} - </> - )} - </Col> - </Row> - </> - ); -}); - -export default TaskHeader; diff --git a/forms-flow-web/src/components/ServiceFlow/details/TaskHeaderListView.js b/forms-flow-web/src/components/ServiceFlow/details/TaskHeaderListView.js index 70c5ca765f..401b97aaf9 100644 --- a/forms-flow-web/src/components/ServiceFlow/details/TaskHeaderListView.js +++ b/forms-flow-web/src/components/ServiceFlow/details/TaskHeaderListView.js @@ -48,32 +48,29 @@ const TaskHeaderListView = React.memo(({task,taskId,groupView = true}) => { setDueDate(due); }, [task?.due]); + const updateBpmTasksAndDetails = (err) =>{ + if (!err) { + if (!SocketIOService.isConnected()) { + if (selectedFilter) { + dispatch(getBPMTaskDetail(taskId)); + dispatch( + fetchServiceTaskList(reqData,null,firstResult) + ); + } else { + dispatch(setBPMTaskDetailUpdating(false)); + } + } + + } else { + dispatch(setBPMTaskDetailUpdating(false)); + } + }; + const onClaim = () => { dispatch(setBPMTaskDetailUpdating(true)); dispatch( // eslint-disable-next-line no-unused-vars - claimBPMTask(taskId, username, (err, response) => { - if (!err) { - if (!SocketIOService.isConnected()) { - if (selectedFilter) { - dispatch(getBPMTaskDetail(taskId)); - dispatch( - fetchServiceTaskList(reqData,null,firstResult) - ); - } else { - dispatch(setBPMTaskDetailUpdating(false)); - } - } - if(selectedFilter){ - dispatch( - fetchServiceTaskList(reqData,null,firstResult) - ); - } - - } else { - dispatch(setBPMTaskDetailUpdating(false)); - } - }) + claimBPMTask(taskId, username,updateBpmTasksAndDetails) ); }; const onChangeClaim = (userId) => { @@ -82,23 +79,7 @@ const TaskHeaderListView = React.memo(({task,taskId,groupView = true}) => { dispatch(setBPMTaskDetailUpdating(true)); dispatch( // eslint-disable-next-line no-unused-vars - updateAssigneeBPMTask(taskId, userId, (err, response) => { - if (!err) { - if (!SocketIOService.isConnected()) { - if (selectedFilter) { - dispatch(getBPMTaskDetail(taskId)); - } - } - if(selectedFilter){ - dispatch( - fetchServiceTaskList(reqData,null,firstResult) - ); - } - - } else { - dispatch(setBPMTaskDetailUpdating(false)); - } - }) + updateAssigneeBPMTask(taskId, userId, updateBpmTasksAndDetails) ); } }; @@ -107,23 +88,7 @@ const TaskHeaderListView = React.memo(({task,taskId,groupView = true}) => { dispatch(setBPMTaskDetailUpdating(true)); dispatch( // eslint-disable-next-line no-unused-vars - unClaimBPMTask(taskId, (err, response) => { - if (!err) { - if (!SocketIOService.isConnected()) { - if (selectedFilter) { - dispatch(getBPMTaskDetail(taskId)); - } - } - if(selectedFilter){ - dispatch( - fetchServiceTaskList(reqData,null,firstResult) - ); - } - - } else { - dispatch(setBPMTaskDetailUpdating(false)); - } - }) + unClaimBPMTask(taskId, updateBpmTasksAndDetails) ); }; @@ -136,18 +101,7 @@ const TaskHeaderListView = React.memo(({task,taskId,groupView = true}) => { }; dispatch( // eslint-disable-next-line no-unused-vars - updateBPMTask(taskId, updatedTask, (err, response) => { - if (!err) { - if (!SocketIOService.isConnected()) { - dispatch(getBPMTaskDetail(taskId)); - dispatch( - fetchServiceTaskList(reqData,null,firstResult) - ); - } - } else { - dispatch(setBPMTaskDetailUpdating(false)); - } - }) + updateBPMTask(taskId, updatedTask, updateBpmTasksAndDetails) ); }; @@ -160,18 +114,7 @@ const TaskHeaderListView = React.memo(({task,taskId,groupView = true}) => { }; dispatch( // eslint-disable-next-line no-unused-vars - updateBPMTask(taskId, updatedTask, (err, response) => { - if (!err) { - if (!SocketIOService.isConnected()) { - dispatch(getBPMTaskDetail(taskId)); - dispatch( - fetchServiceTaskList(reqData,null,firstResult) - ); - } - } else { - dispatch(setBPMTaskDetailUpdating(false)); - } - }) + updateBPMTask(taskId, updatedTask, updateBpmTasksAndDetails) ); }; diff --git a/forms-flow-web/src/components/ServiceFlow/index.js b/forms-flow-web/src/components/ServiceFlow/index.js index cb8bbd7f3b..354696d0bd 100644 --- a/forms-flow-web/src/components/ServiceFlow/index.js +++ b/forms-flow-web/src/components/ServiceFlow/index.js @@ -1,11 +1,10 @@ -import React, { useCallback, useEffect, useRef } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; import ServiceFlowTaskList from "./list/ServiceTaskList"; import ServiceTaskListView from "./list/ServiceTaskListView"; -import ServiceTaskListViewDetails from './list/ServiceTaskListViewDetails'; - +import ServiceTaskListViewDetails from "./list/ServiceTaskListViewDetails"; import ServiceFlowTaskDetails from "./details/ServiceTaskDetails"; - import "./ServiceFlow.scss"; +import "./ServiceFlow.scss"; import { fetchBPMTaskCount, fetchFilterList, @@ -22,17 +21,19 @@ import { setBPMFiltersAndCount, setBPMTaskDetailLoader, setFilterListParams, + setIsAllTaskVariableExpand, setSelectedBPMFilter, setSelectedTaskID, } from "../../actions/bpmTaskActions"; -import TaskSortSelectedList from "./list/sort/TaskSortSelectedList"; +// import TaskSortSelectedList from "./list/sort/TaskSortSelectedList"; import SocketIOService from "../../services/SocketIOService"; import isEqual from "lodash/isEqual"; import cloneDeep from "lodash/cloneDeep"; import { Route, Redirect, Switch } from "react-router-dom"; import { push, replace } from "connected-react-router"; -import { BASE_ROUTE,MULTITENANCY_ENABLED } from "../../constants/constants"; +import { BASE_ROUTE, MULTITENANCY_ENABLED } from "../../constants/constants"; import TaskHead from "../../containers/TaskHead"; +import TaskSearchBarView from "./list/search/TaskSearchBarView"; export default React.memo(() => { const dispatch = useDispatch(); @@ -40,9 +41,7 @@ export default React.memo(() => { const selectedFilterId = useSelector( (state) => state.bpmTasks.selectedFilter?.id || null ); - const bpmFiltersList = useSelector( - (state) => state.bpmTasks.filterList - ); + const bpmFiltersList = useSelector((state) => state.bpmTasks.filterList); const bpmTaskId = useSelector((state) => state.bpmTasks.taskId); const reqData = useSelector((state) => state.bpmTasks.listReqParams); const selectedFilter = useSelector((state) => state.bpmTasks.selectedFilter); @@ -58,15 +57,17 @@ export default React.memo(() => { ); const firstResult = useSelector((state) => state.bpmTasks.firstResult); const taskList = useSelector((state) => state.bpmTasks.tasksList); + const allTaskVariablesExpanded = useSelector( + (state) => state.bpmTasks.allTaskVariablesExpand + ); const selectedFilterIdRef = useRef(selectedFilterId); const bpmTaskIdRef = useRef(bpmTaskId); const reqDataRef = useRef(reqData); const firstResultsRef = useRef(firstResult); const taskListRef = useRef(taskList); const tenantKey = useSelector((state) => state.tenants?.tenantId); - const cardView = useSelector( - (state) => state.bpmTasks.viewType - ); + const cardView = useSelector((state) => state.bpmTasks.viewType); + const [expandedTasks, setExpandedTasks] = useState({}); const redirectUrl = useRef( MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/" ); @@ -82,6 +83,7 @@ export default React.memo(() => { redirectUrl.current = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/"; }); +// This useEffect will render if any changes happens in the depenendencies mentioned in the array and will update filter list params useEffect(() => { const reqParamData = { ...{ sorting: [...sortParams.sorting] }, @@ -90,62 +92,49 @@ export default React.memo(() => { selectedBPMFilterParams = bpmFiltersList.find( (item) => item.id === selectedFilterId ); - if(selectedBPMFilterParams){ + if (selectedBPMFilterParams) { selectedBPMFilterParams = { ...selectedBPMFilterParams, criteria: { ...selectedBPMFilterParams?.criteria, - ...reqParamData - } + ...reqParamData, + }, }; } - if (!isEqual(selectedBPMFilterParams, listReqParams) && selectedBPMFilterParams) { + if ( + !isEqual(selectedBPMFilterParams, listReqParams) && + selectedBPMFilterParams + ) { dispatch(setFilterListParams(cloneDeep(selectedBPMFilterParams))); } - }, [selectedFilterId]); - - useEffect(() => { - const reqParamData = { - ...{ sorting: [...sortParams.sorting] }, - ...searchParams, - }; - selectedBPMFilterParams = bpmFiltersList.find( - (item) => item.id === selectedFilterId - ); - if(selectedBPMFilterParams){ - selectedBPMFilterParams = { - ...selectedBPMFilterParams, - criteria: { - ...selectedBPMFilterParams?.criteria, - ...reqParamData - } - }; - } - if (!isEqual(selectedBPMFilterParams, listReqParams) && selectedBPMFilterParams) { - dispatch(setFilterListParams(cloneDeep(selectedBPMFilterParams))); - } - }, [searchParams, sortParams, dispatch, listReqParams]); - + }, [selectedFilterId, searchParams, sortParams, dispatch, listReqParams]); useEffect(() => { dispatch(setBPMFilterLoader(true)); - dispatch(fetchFilterList((err,data)=>{ - if(data){ - fetchBPMTaskCount(data).then((res)=>{ - dispatch(setBPMFiltersAndCount(res.data)); - }).catch((err)=> console.error(err)).finally(()=>{ - dispatch(setBPMFilterLoader(false)); - }); - } - })); + dispatch( + fetchFilterList((err, data) => { + if (data) { + fetchBPMTaskCount(data) + .then((res) => { + dispatch(setBPMFiltersAndCount(res.data)); + }) + .catch((err) => console.error(err)) + .finally(() => { + dispatch(setBPMFilterLoader(false)); + }); + } + }) + ); dispatch(fetchProcessDefinitionList()); }, [dispatch]); - useEffect(()=>{ - if(filterList?.length){ + useEffect(() => { + if (filterList?.length) { let filterSelected; if (filterList.length > 1) { - filterSelected = filterList?.find((filter) => filter.name === ALL_TASKS); + filterSelected = filterList?.find( + (filter) => filter.name === ALL_TASKS + ); if (!filterSelected) { filterSelected = filterList[0]; } @@ -154,28 +143,40 @@ export default React.memo(() => { } dispatch(setSelectedBPMFilter(filterSelected)); } - },[filterList?.length]); + }, [filterList?.length]); const checkIfTaskIDExistsInList = (list, id) => { return list.some((task) => task.id === id); }; + + const toggleAllTaskVariables = () => { + const newExpandedState = !allTaskVariablesExpanded; + const updatedExpandedTasks = {}; + + taskList.forEach((task) => { + if (task?._embedded?.variable?.length > 1) { + updatedExpandedTasks[task.id] = newExpandedState; + } + }); + setExpandedTasks(updatedExpandedTasks); + dispatch(setIsAllTaskVariableExpand(newExpandedState)); + }; + const SocketIOCallback = useCallback( (refreshedTaskId, forceReload, isUpdateEvent) => { - const reqParamData = { ...{ sorting: [...sortParams.sorting] }, ...searchParams, }; - - const selectedBPMFilterParams = { - ...selectedFilter, - criteria: { - ...selectedFilter?.criteria, - ...reqParamData - } - }; - + const selectedBPMFilterParams = { + ...selectedFilter, + criteria: { + ...selectedFilter?.criteria, + ...reqParamData, + }, + }; + if (forceReload) { dispatch( fetchServiceTaskList( @@ -212,7 +213,7 @@ export default React.memo(() => { fetchServiceTaskList( selectedBPMFilterParams, null, - firstResultsRef.current, + firstResultsRef.current ) ); //Refreshes the Task } @@ -231,7 +232,7 @@ export default React.memo(() => { } } }, - [dispatch, currentUser, selectedFilter,searchParams, sortParams] + [dispatch, currentUser, selectedFilter, searchParams, sortParams] ); useEffect(() => { @@ -257,60 +258,64 @@ export default React.memo(() => { return ( <div> <TaskHead /> + <TaskSearchBarView + toggleAllTaskVariables={toggleAllTaskVariables} + /> {cardView ? ( <> - - <div className="row mx-0"> - <div className="col-12 px-0 col-md-4 col-xl-3"> - <section> - <header className="d-flex flex-wrap align-items-center p-2 bg-light shadow mb-2"> + <div className="row mx-0"> + + <div className="col-12 px-0 col-md-4 col-xl-3"> + <section> + {/* <header className="d-flex flex-wrap align-items-center p-2 bg-light shadow mb-2"> <TaskSortSelectedList /> - </header> - <ServiceFlowTaskList /> - </section> - </div> - <div className="col-12 pe-0 ps-md-5 col-md-8 col-xl-9 px-2 pe-md-0 py-5 py-md-0 border "> - <Switch> - <Route - path={`${BASE_ROUTE}task/:taskId?`} - component={ServiceFlowTaskDetails} - ></Route> - <Route path={`${BASE_ROUTE}task/:taskId/:notAvailable`}> - {" "} - <Redirect exact to="/404" /> - </Route> - </Switch> - </div> - </div> + </header> */} + <ServiceFlowTaskList + expandedTasks={expandedTasks} + setExpandedTasks={setExpandedTasks}/> + </section> + </div> + <div className="col-12 pe-0 ps-md-5 col-md-8 col-xl-9 px-2 pe-md-0 py-5 py-md-0 border "> + <Switch> + <Route + path={`${BASE_ROUTE}task/:taskId?`} + component={ServiceFlowTaskDetails} + ></Route> + <Route path={`${BASE_ROUTE}task/:taskId/:notAvailable`}> + {" "} + <Redirect exact to="/404" /> + </Route> + </Switch> + </div> + </div> </> - ) : - ( - <Switch> - <Route - exact - path={`${BASE_ROUTE}task`} - render={() => ( - <> - <ServiceTaskListView /> - </> - )} - > - </Route> - <Route - path={`${BASE_ROUTE}task/:taskId`} - render={() => ( - <> - - <ServiceTaskListViewDetails /> - </> - )} - - ></Route> - <Route path={`${BASE_ROUTE}task/:taskId/:notAvailable`}> - <Redirect exact to="/404" /> - </Route> - </Switch> - ) } + ) : ( + <Switch> + <Route + exact + path={`${BASE_ROUTE}task`} + render={() => ( + <> + <ServiceTaskListView + expandedTasks={expandedTasks} + setExpandedTasks={setExpandedTasks} + /> + </> + )} + ></Route> + <Route + path={`${BASE_ROUTE}task/:taskId`} + render={() => ( + <> + <ServiceTaskListViewDetails /> + </> + )} + ></Route> + <Route path={`${BASE_ROUTE}task/:taskId/:notAvailable`}> + <Redirect exact to="/404" /> + </Route> + </Switch> + )} </div> ); }); diff --git a/forms-flow-web/src/components/ServiceFlow/list/ServiceTaskList.js b/forms-flow-web/src/components/ServiceFlow/list/ServiceTaskList.js index fa1d284f1c..29890dbad5 100644 --- a/forms-flow-web/src/components/ServiceFlow/list/ServiceTaskList.js +++ b/forms-flow-web/src/components/ServiceFlow/list/ServiceTaskList.js @@ -13,14 +13,14 @@ import { getProcessDataObjectFromList, getFormattedDateAndTime, } from "../../../apiManager/services/formatterService"; -import TaskFilterComponent from "./search/TaskFilterComponent"; import Pagination from "react-js-pagination"; import { push } from "connected-react-router"; import { MAX_RESULTS } from "../constants/taskConstants"; import { getFirstResultIndex } from "../../../apiManager/services/taskSearchParamsFormatterService"; import TaskVariable from "./TaskVariable"; import { MULTITENANCY_ENABLED } from "../../../constants/constants"; -const ServiceFlowTaskList = React.memo(() => { +const ServiceFlowTaskList = React.memo((props) => { + const {expandedTasks,setExpandedTasks} = props; const { t } = useTranslation(); const taskList = useSelector((state) => state.bpmTasks.tasksList); const tasksCount = useSelector((state) => state.bpmTasks.tasksCount); @@ -52,7 +52,6 @@ const ServiceFlowTaskList = React.memo(() => { }; dispatch(setBPMTaskLoader(true)); dispatch(setBPMTaskListActivePage(1)); - dispatch(fetchServiceTaskList(selectedBPMFilterParams,null,firstResult)); } }, [reqData]); @@ -72,6 +71,8 @@ const ServiceFlowTaskList = React.memo(() => { ); }; + + const renderTaskList = () => { if ((tasksCount || taskList.length) && selectedFilter) { return ( @@ -153,7 +154,11 @@ const ServiceFlowTaskList = React.memo(() => { </div> {task._embedded?.variable && ( - <TaskVariable variables={task._embedded?.variable || []} /> + <TaskVariable + expandedTasks={expandedTasks} + setExpandedTasks={setExpandedTasks} + taskId={task?.id} + variables={task._embedded?.variable || []} /> )} </div> ))} @@ -192,7 +197,6 @@ const ServiceFlowTaskList = React.memo(() => { return ( <> <ListGroup className="service-task-list d-block"> - <TaskFilterComponent totalTasks={isTaskListLoading ? 0 : tasksCount} /> {isTaskListLoading ? <Loading /> : renderTaskList()} </ListGroup> </> diff --git a/forms-flow-web/src/components/ServiceFlow/list/ServiceTaskListView.js b/forms-flow-web/src/components/ServiceFlow/list/ServiceTaskListView.js index bffe524591..5fa8aed05d 100644 --- a/forms-flow-web/src/components/ServiceFlow/list/ServiceTaskListView.js +++ b/forms-flow-web/src/components/ServiceFlow/list/ServiceTaskListView.js @@ -6,23 +6,20 @@ import { fetchServiceTaskList } from "../../../apiManager/services/bpmTaskServic import { setBPMTaskListActivePage, setBPMTaskLoader, - setIsAllTaskVariableExpand } from "../../../actions/bpmTaskActions"; import Loading from "../../../containers/Loading"; import { useTranslation } from "react-i18next"; import "./../ServiceFlow.scss"; -import TaskSearchBarListView from "./search/TaskSearchBarListView"; import { getFormattedDateAndTime, } from "../../../apiManager/services/formatterService"; import Pagination from "react-js-pagination"; import { push } from "connected-react-router"; -// import { MAX_RESULTS } from "../constants/taskConstants"; -// import { getFirstResultIndex } from "../../../apiManager/services/taskSearchParamsFormatterService"; import { MULTITENANCY_ENABLED } from "../../../constants/constants"; import TaskHeaderListView from "../details/TaskHeaderListView"; -const ServiceTaskListView = React.memo(() => { +const ServiceTaskListView = React.memo((props) => { + const {expandedTasks,setExpandedTasks} = props; const { t } = useTranslation(); const taskList = useSelector((state) => state.bpmTasks.tasksList); const tasksCount = useSelector((state) => state.bpmTasks.tasksCount); @@ -35,7 +32,6 @@ const ServiceTaskListView = React.memo(() => { const selectedFilter = useSelector((state) => state.bpmTasks.selectedFilter); const firstResult = useSelector((state) => state.bpmTasks.firstResult); const activePage = useSelector((state) => state.bpmTasks.activePage); - const [expandedTasks, setExpandedTasks] = useState({}); const allTaskVariablesExpanded = useSelector((state) => state.bpmTasks.allTaskVariablesExpand); const [selectedLimitValue, setSelectedLimitValue] = useState(15); const tenantKey = useSelector((state) => state.tenants?.tenantId); @@ -111,19 +107,6 @@ const ServiceTaskListView = React.memo(() => { [taskId]: !prevExpandedTasks[taskId], })); }; - // Toggle expand or collapse the TaskVariables of all task - const toggleAllTaskVariables = () => { - const newExpandedState = !allTaskVariablesExpanded; - const updatedExpandedTasks = {}; - - taskList.forEach(task => { - if (task?._embedded?.variable?.length > 1) { - updatedExpandedTasks[task.id] = newExpandedState; - } - }); - setExpandedTasks(updatedExpandedTasks); - dispatch(setIsAllTaskVariableExpand(newExpandedState)); - }; const renderTaskList = () => { if ((tasksCount || taskList.length) && selectedFilter) { @@ -318,8 +301,6 @@ const ServiceTaskListView = React.memo(() => { return ( <> - <TaskSearchBarListView - toggleAllTaskVariables={toggleAllTaskVariables} /> {isTaskListLoading ? <Loading /> : renderTaskList()} </> ); diff --git a/forms-flow-web/src/components/ServiceFlow/list/TaskVariable.js b/forms-flow-web/src/components/ServiceFlow/list/TaskVariable.js index 0f865f2b55..8534f57a7b 100644 --- a/forms-flow-web/src/components/ServiceFlow/list/TaskVariable.js +++ b/forms-flow-web/src/components/ServiceFlow/list/TaskVariable.js @@ -1,14 +1,34 @@ -import React, { useState } from "react"; +import React, { useEffect } from "react"; import { useSelector } from "react-redux"; import { Row, Col } from "react-bootstrap"; -const TaskVariable = ({ variables }) => { - const [showMore, setShowMore] = useState(false); +const TaskVariable = ({ expandedTasks, setExpandedTasks,taskId, variables }) => { let variableCount = 0; const taskvariable = useSelector( (state) => state.bpmTasks.selectedFilter?.variables || [] ); + const allTaskVariablesExpanded = useSelector((state) => state.bpmTasks.allTaskVariablesExpand); + const taskList = useSelector((state) => state.bpmTasks.tasksList); - const rowReturn = (taskItem, data, index) => { + useEffect(() => { + // Initialize expandedTasks based on the initial value of allTaskVariablesExpanded + const updatedExpandedTasks = {}; + if (allTaskVariablesExpanded) { + taskList.forEach((task) => { + updatedExpandedTasks[task.id] = allTaskVariablesExpanded; + }); + } + setExpandedTasks(updatedExpandedTasks); + }, [allTaskVariablesExpanded, taskList]); + + //Toggle the expanded state of TaskVariables in single task + const handleToggleTaskVariable = (taskId) => { + setExpandedTasks((prevExpandedTasks) => ({ + ...prevExpandedTasks, + [taskId]: !prevExpandedTasks[taskId], + })); + }; + + const rowReturn = (taskItem, data, index) => { return ( <Col xs={12} lg={6} key={index} className="mb-2"> <div @@ -46,7 +66,7 @@ const TaskVariable = ({ variables }) => { if (variableCount < 2) { variableCount++; return rowReturn(taskItem, data, index); - } else if (showMore) { + } else if (expandedTasks[taskId]) { return rowReturn(taskItem, data, index); } else { return false; @@ -61,13 +81,13 @@ const TaskVariable = ({ variables }) => { className="justify-content-center text-center" onClick={(e) => { e.stopPropagation(); - setShowMore(!showMore); + handleToggleTaskVariable(taskId); }} > <i className="fa fa-angle-down" style={{ - transform: `${showMore ? "rotate(180deg)" : "rotate(0deg)"}`, + transform: `${expandedTasks[taskId] ? "rotate(180deg)" : "rotate(0deg)"}`, }} aria-hidden="true" /> diff --git a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterComponent.js b/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterComponent.js deleted file mode 100644 index f3dac2d3e1..0000000000 --- a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterComponent.js +++ /dev/null @@ -1,134 +0,0 @@ -import React, { useEffect, useRef, useState } from "react"; -import TaskFilterDropdown from "./TaskFilterDropdown"; -import TaskFilterSearch from "./TaskFilterSearch"; -import { QUERY_TYPES } from "../../constants/taskConstants"; -import { - setFilterListSearchParams, - setSearchQueryType, -} from "../../../../actions/bpmTaskActions"; -import { useDispatch, useSelector } from "react-redux"; -import TaskIgnoreCaseComponent from "./TaskIgnoreCaseComponent"; -import { useTranslation } from "react-i18next"; -const TaskFilterComponent = React.memo(({ totalTasks }) => { - const createSearchNode = useRef(); - const filterSearchSelections = useSelector( - (state) => state.bpmTasks.filterSearchSelections - ); - const queryType = useSelector((state) => state.bpmTasks.searchQueryType); - const [filterSelections, setFilterSelections] = useState( - filterSearchSelections - ); - const [showFilterItems, setShowFilterItems] = useState(false); - const dispatch = useDispatch(); - const { t } = useTranslation(); - - const handleClick = (e) => { - if (createSearchNode?.current?.contains(e.target)) { - return; - } - // outside click - setShowFilterItems(null); - }; - - useEffect(() => { - // add when mounted - document.addEventListener("mousedown", handleClick); - // return function to be called when unmounted - return () => { - document.removeEventListener("mousedown", handleClick); - }; - }, []); - - useEffect(() => { - dispatch(setFilterListSearchParams(filterSelections)); - }, [filterSelections, dispatch]); - - const setFilter = (filter) => { - const updatedSelectionsArray = [...filterSelections, { ...filter }]; - setFilterSelections(updatedSelectionsArray); - setShowFilterItems(false); - }; - - const deleteSearchFilter = (filter, index) => { - let updatedSelectionsArray = [...filterSelections]; - updatedSelectionsArray.splice(index, 1); - setFilterSelections(updatedSelectionsArray); - }; - - const updateSearchFilterData = (index, key, value) => { - let updatedSelectionsArray = [...filterSelections]; - let newValue; - if (value === "false") { - newValue = false; - } else if (value === "true") { - newValue = true; - } else if (isNaN(value)) { - newValue = value; - } else { - newValue = Number(value); - } - - updatedSelectionsArray[index][key] = newValue; - setFilterSelections(updatedSelectionsArray); - }; - - const updateFilter = (filter, index) => { - let updatedSelectionsArray = [...filterSelections]; - updatedSelectionsArray[index].label = filter.label; - updatedSelectionsArray[index].type = filter.type; - updatedSelectionsArray[index].operator = filter.operator; - updatedSelectionsArray[index].key = filter.key; - setFilterSelections(updatedSelectionsArray); - }; - - const setQueryType = (type) => { - dispatch(setSearchQueryType(type)); - }; - - const changeQueryType = () => { - queryType === QUERY_TYPES.ALL - ? setQueryType(QUERY_TYPES.ANY) - : setQueryType(QUERY_TYPES.ALL); - }; - - return ( - <> - <div className="filter-container"> - <div> - {filterSelections.length ? ( - <div> - <span className="button click-element" onClick={changeQueryType}> - {queryType} - </span> - <span> {t("of the criteria are met.")}</span> - </div> - ) : null} - - <TaskFilterSearch - updateSearchFilterData={updateSearchFilterData} - filterSelections={filterSelections} - deleteSearchFilter={deleteSearchFilter} - updateFilter={updateFilter} - /> - <div ref={createSearchNode}> - <input - type="text" - className="filter" - placeholder={t("Filter Tasks")} - onClick={() => {}} - onFocus={() => setShowFilterItems(true)} - title={t("Filter Tasks")} - /> - {showFilterItems ? ( - <TaskFilterDropdown onFilterSelect={setFilter} /> - ) : null} - <span data-title={t("Total number of results")}>{totalTasks}</span> - </div> - </div> - <TaskIgnoreCaseComponent /> - </div> - </> - ); -}); - -export default TaskFilterComponent; diff --git a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterDropdown.js b/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterDropdown.js deleted file mode 100644 index b7ac4d244b..0000000000 --- a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterDropdown.js +++ /dev/null @@ -1,20 +0,0 @@ -import { taskFilters } from "../../constants/taskConstants"; -import React from "react"; - -const TaskFilterDropdown = React.memo(({ onFilterSelect }) => { - return ( - <div className="filter-items"> - {taskFilters.map((filter, index) => ( - <div - key={index} - className="clickable p-0 mb-2" - onClick={() => onFilterSelect(filter)} - > - {filter.label} - </div> - ))} - </div> - ); -}); - -export default TaskFilterDropdown; diff --git a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterDropdownListView.js b/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterDropdownListView.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterSearch.js b/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterSearch.js deleted file mode 100644 index 83a58600bf..0000000000 --- a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterSearch.js +++ /dev/null @@ -1,338 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { useSelector } from "react-redux"; -import { - FILTER_COMPARE_OPTIONS, - Filter_Search_Types, -} from "../../constants/taskConstants"; -import OperatorFilterDropDown from "../../filter/OperatorFilterDropdown"; -import TaskFilterSearchType from "./TaskFilterSearchType"; -import { - getFormattedDateAndTime, - getISODateTime, -} from "../../../../apiManager/services/formatterService"; -import DatePicker from "react-datepicker"; -import { useTranslation } from "react-i18next"; -const TaskFilterSearch = React.memo( - ({ - filterSelections = [], - deleteSearchFilter, - updateSearchFilterData, - updateFilter, - }) => { - const [valueBoxIndex, setShowValueBoxIndex] = useState(null); - const [nameBoxIndex, setShowNameBoxIndex] = useState(null); - const [selectedFilterInputValue, setSelectedFilterInputValue] = - useState(""); - const [selectedFilterInputName, setSelectedFilterInputName] = useState(""); - const [inputDate, setUpInputDate] = useState(null); - const [filterTaskVariableArray, setFilterTaskVariableArray] = useState([]); - const { t } = useTranslation(); - const [taskVariable, setTaskVariable] = useState([]); - const selectedFilter = useSelector( - (state) => state.bpmTasks.selectedFilter - ); - const [showCalander, setCalander] = useState(false); - useEffect(() => { - if (selectedFilter) { - const taskVariable = selectedFilter?.variables || []; - setTaskVariable(taskVariable); - setFilterTaskVariableArray(taskVariable); - } - }, [selectedFilter]); - - const filterTaskVariable = (e) => { - setFilterTaskVariableArray( - // eslint-disable-next-line no-unused-vars - taskVariable.filter((task, index) => - task?.name.includes(e.target.value) - ) - ); - }; - - const handleFilterValueChange = (e, index) => { - if (e.key === "Enter") { - e.preventDefault(); - updateFilterValue(index); - } - }; - - const updateFilterValue = (index) => { - setCalander(false); - updateSearchFilterData(index, "value", selectedFilterInputValue); - setShowValueBoxIndex(null); - setSelectedFilterInputValue(""); - }; - - const updateOperator = (index, value) => { - updateSearchFilterData(index, "operator", value); - }; - - const updateFilterName = (index, value) => { - updateSearchFilterData(index, "name", value || selectedFilterInputName); - setShowNameBoxIndex(null); - setSelectedFilterInputName(""); - }; - - const handleFilterNameChange = (e, index) => { - if (e.key === "Enter") { - e.preventDefault(); - updateFilterName(index); - } - }; - - const handleValueInput = (index, value = "", type) => { - setShowValueBoxIndex(index); - type !== Filter_Search_Types.DATE - ? setSelectedFilterInputValue(value.toString()) - : setUpInputDate(value ? new Date(value) : null); - }; - - const handleNameInput = (index, value = "") => { - setShowNameBoxIndex(index); - setSelectedFilterInputName(value); - }; - - const handleFilterUpdate = (filter, index) => { - updateFilter(filter, index); - }; - - const onUpDateInputdate = (updatedDate, index) => { - setUpInputDate(updatedDate); - updateSearchFilterData( - index, - "value", - updatedDate ? getISODateTime(updatedDate) : null - ); - setShowValueBoxIndex(null); - setSelectedFilterInputValue(""); - /*followUpDate?getISODateTime(followUpDate):null*/ - }; - - // eslint-disable-next-line no-unused-vars - const UpDateInputComponent = React.forwardRef(({ value, onClick }, ref) => { - return ( - <div onClick={onClick} ref={ref}> - <i className="fa fa-calendar" />{" "} - {inputDate ? ( - <span className="me-4">{getFormattedDateAndTime(inputDate)}</span> - ) : ( - "??" - )} - </div> - ); - }); - - return ( - <> - {filterSelections.map((filter, index) => ( - <div key={index}> - <div className="filter-details" key={index}> - <div - className="close-container click-element" - onClick={() => deleteSearchFilter(filter, index)} - > - <span className="close-btn" title={t("Remove search")}> - <i className="fa fa-times" aria-hidden="true" /> - </span> - </div> - - <div className="box-container"> - <TaskFilterSearchType - filter={filter} - index={index} - handleFilterUpdate={handleFilterUpdate} - /> - <span> - <span className="btn-container"> - {filter.type === Filter_Search_Types.VARIABLES && - nameBoxIndex === index ? ( - <> - <button - className="btn btn-small" - onClick={() => updateFilterName(index)} - > - <i className="fa fa-check" aria-hidden="true" /> - </button> - <button - className="btn btn-small" - onClick={() => setShowNameBoxIndex(null)} - > - <i className="fa fa-times" aria-hidden="true" /> - </button> - </> - ) : null} - </span> - {filter.type === Filter_Search_Types.VARIABLES ? ( - nameBoxIndex === index ? ( - <div> - <input - type="text" - className="filters position-box" - placeholder="" - value={selectedFilterInputName} - onChange={(e) => { - filterTaskVariable(e); - setSelectedFilterInputName(e.target.value); - }} - onKeyDown={(e) => handleFilterNameChange(e, index)} - /> - <div className="filter-items variable-filter-item"> - {filterTaskVariableArray.map((variable) => ( - <div - key={variable.label} - className="clickable p-0 mb-2 text-truncate" - onClick={() => { - setSelectedFilterInputName(variable.name); - updateFilterName(index, variable.name); - }} - data-bs-toggle="tooltip" - data-bs-placement="top" - title={`${variable.name} (${variable.label})`} - > - <span> - {variable.name}{" "} - <span className="text-muted"> - {" "} - ({variable.label}) - </span> - </span> - </div> - ))} - </div> - </div> - ) : ( - <div className="text-truncate"> - <span - data-bs-toggle="tooltip" - data-bs-placement="top" - title={`${filter.name ? filter.name : "property"}`} - className="click-element" - onClick={() => handleNameInput(index, filter.name)} - > - {filter.name ? filter.name : "??"} - </span> - </div> - ) - ) : null} - - <span className="condition-container"> - {valueBoxIndex === index && - filter.type !== Filter_Search_Types.DATE ? ( - <span className="btn-container second-box"> - <span className="second-inner-box"> - {filter.type === Filter_Search_Types.VARIABLES ? ( - <button className="btn btn-small"> - <i - className="fa fa-calendar" - aria-hidden="true" - onClick={() => setCalander(true)} - /> - </button> - ) : null} - <button - className="btn btn-small" - onClick={() => updateFilterValue(index)} - > - <i className="fa fa-check" aria-hidden="true" /> - </button> - - <button - className="btn btn-small" - onClick={() => { - setShowValueBoxIndex(null); - setCalander(false); - }} - > - <i className="fa fa-times" aria-hidden="true" /> - </button> - </span> - </span> - ) : null} - <div className="operator-box-container"> - <span - title={t("Operator")} - className="operator-container" - > - <OperatorFilterDropDown - compareOptions={FILTER_COMPARE_OPTIONS[filter.type]} - operator={filter.operator} - changeOperator={(value) => - updateOperator(index, value) - } - /> - </span> - - <span - id="task-search-input" - className={ - filter.type === Filter_Search_Types.DATE && inputDate - ? "date-with-value" - : "" - } - > - {valueBoxIndex === index ? ( - filter.type === Filter_Search_Types.DATE ? ( - <DatePicker - selected={inputDate} - onChange={(date) => - onUpDateInputdate(date, index) - } - showTimeSelect - isClearable - popperPlacement="bottom-start" - popperModifiers={{ - offset: { - enabled: true, - offset: "5px, 10px", - }, - preventOverflow: { - enabled: true, - escapeWithReference: false, - boundariesElement: "viewport", - }, - }} - customInput={<UpDateInputComponent />} - /> - ) : ( - <input - type={showCalander ? "datetime-local" : "text"} - className="filters" - placeholder="" - value={selectedFilterInputValue} - onChange={(e) => - setSelectedFilterInputValue(e.target.value) - } - onKeyDown={(e) => - handleFilterValueChange(e, index) - } - /> - ) - ) : ( - <span - title={t("value")} - className="click-element" - onClick={() => - handleValueInput(index, filter.value, filter.type) - } - > - {filter.value !== (undefined || null || "") - ? filter.type !== Filter_Search_Types.DATE - ? filter.value.toString() - : getFormattedDateAndTime(filter.value) - : "??"} - </span> - )} - </span> - </div> - </span> - </span> - </div> - </div> - </div> - ))} - </> - ); - } -); - -export default TaskFilterSearch; diff --git a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterSearchType.js b/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterSearchType.js deleted file mode 100644 index ae00a4f935..0000000000 --- a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterSearchType.js +++ /dev/null @@ -1,51 +0,0 @@ -import React, { useEffect, useRef, useState } from "react"; -import { Filter_Search_Types } from "../../constants/taskConstants"; -import TaskFilterDropdown from "./TaskFilterDropdown"; -import { useTranslation } from "react-i18next"; - -const TaskFilterSearchType = React.memo( - ({ filter, index, handleFilterUpdate }) => { - const createSearchNode = useRef(); - const [showFilterItems, setShowFilterItems] = useState(false); - const { t } = useTranslation(); - const handleClick = (e) => { - if (createSearchNode?.current?.contains(e.target)) { - return; - } - // outside click - setShowFilterItems(false); - }; - - useEffect(() => { - // add when mounted - document.addEventListener("mousedown", handleClick); - // return function to be called when unmounted - return () => { - document.removeEventListener("mousedown", handleClick); - }; - }, []); - - const handleFilterSelect = (filterToUpdate) => { - handleFilterUpdate(filterToUpdate, index); - setShowFilterItems(false); - }; - - return ( - <span - className="click-element me-1 list-span" - title={t("Type")} - ref={createSearchNode} - > - <span onClick={() => setShowFilterItems(true)}> - {filter.label}{" "} - {filter.type === Filter_Search_Types.VARIABLES ? " :" : null} - </span> - {showFilterItems ? ( - <TaskFilterDropdown onFilterSelect={handleFilterSelect} /> - ) : null} - </span> - ); - } -); - -export default TaskFilterSearchType; diff --git a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterListViewComponent.js b/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterViewComponent.js similarity index 99% rename from forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterListViewComponent.js rename to forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterViewComponent.js index c21ad860db..88a9c099ff 100644 --- a/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterListViewComponent.js +++ b/forms-flow-web/src/components/ServiceFlow/list/search/TaskFilterViewComponent.js @@ -12,7 +12,7 @@ import { getISODateTime } from "../../../../apiManager/services/formatterService import { MAX_VARIABLES_PER_ROW } from "../../constants/taskConstants"; import { useTranslation } from "react-i18next"; -const TaskFilterListViewComponent = React.memo( +const TaskFilterViewComponent = React.memo( ({ setDisplayFilter, setFilterParams, filterParams }) => { const vissibleAttributes = useSelector( (state) => state.bpmTasks.vissibleAttributes @@ -139,7 +139,6 @@ const TaskFilterListViewComponent = React.memo( updatedfilterParams["createdBefore"] = getISODateTime(createdEndDate); } - dispatch(setBPMFilterSearchParams(updatedfilterParams)); setFilterParams(updatedfilterParams); setDisplayFilter(false); @@ -450,4 +449,4 @@ const TaskFilterListViewComponent = React.memo( } ); -export default TaskFilterListViewComponent; +export default TaskFilterViewComponent; diff --git a/forms-flow-web/src/components/ServiceFlow/list/search/TaskIgnoreCaseComponent.js b/forms-flow-web/src/components/ServiceFlow/list/search/TaskIgnoreCaseComponent.js deleted file mode 100644 index 6292d0b097..0000000000 --- a/forms-flow-web/src/components/ServiceFlow/list/search/TaskIgnoreCaseComponent.js +++ /dev/null @@ -1,70 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { Form } from 'react-bootstrap'; -import { - setIsVariableNameIgnoreCase, - setIsVariableValueIgnoreCase, -} from "../../../../actions/bpmTaskActions"; -import { isVariableTypeAvailable } from "../../../../apiManager/services/taskSearchParamsFormatterService"; -import { useTranslation } from "react-i18next"; -const TaskIgnoreCaseComponent = React.memo(() => { - const variableNameIgnoreCase = useSelector( - (state) => state.bpmTasks.variableNameIgnoreCase - ); - const variableValueIgnoreCase = useSelector( - (state) => state.bpmTasks.variableValueIgnoreCase - ); - const filterSelections = useSelector( - (state) => state.bpmTasks.filterSearchSelections - ); - const [isVariableTypeInFilter, setIsVariableTypeInFilter] = useState(false); - const dispatch = useDispatch(); - const { t } = useTranslation(); - const setVariableNameIgnoreCase = (isIgnoreCase) => { - dispatch(setIsVariableNameIgnoreCase(isIgnoreCase)); - }; - - const setVariableValueIgnoreCase = (isIgnoreCase) => { - dispatch(setIsVariableValueIgnoreCase(isIgnoreCase)); - }; - - useEffect(() => { - setIsVariableTypeInFilter(isVariableTypeAvailable(filterSelections)); - }, [filterSelections]); - - return ( - <> - {filterSelections.length && isVariableTypeInFilter ? ( - <div> - <span className="name-value-container d-flex align-items-center"> - {t("For Variable, ignore case of")} - <Form className="ms-2"> - <Form.Check - type="checkbox" - id="name" - label={t("Name")} - checked={variableNameIgnoreCase} - onChange={() => - setVariableNameIgnoreCase(!variableNameIgnoreCase) - } - /> - </Form> - <Form className="ms-2"> - <Form.Check - type="checkbox" - id="value" - label={t("value")} - checked={variableValueIgnoreCase} - onChange={() => - setVariableValueIgnoreCase(!variableValueIgnoreCase) - } - /> - </Form> - </span> - </div> - ) : null} - </> - ); -}); - -export default TaskIgnoreCaseComponent; diff --git a/forms-flow-web/src/components/ServiceFlow/list/search/TaskSearchBarListView.js b/forms-flow-web/src/components/ServiceFlow/list/search/TaskSearchBarView.js similarity index 97% rename from forms-flow-web/src/components/ServiceFlow/list/search/TaskSearchBarListView.js rename to forms-flow-web/src/components/ServiceFlow/list/search/TaskSearchBarView.js index c8d31b6acd..8811a867d4 100644 --- a/forms-flow-web/src/components/ServiceFlow/list/search/TaskSearchBarListView.js +++ b/forms-flow-web/src/components/ServiceFlow/list/search/TaskSearchBarView.js @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import { useSelector, useDispatch } from "react-redux"; import TaskSortSelectedList from "../sort/TaskSortSelectedList"; -import TaskFilterListViewComponent from "./TaskFilterListViewComponent"; +import TaskFilterViewComponent from "./TaskFilterViewComponent"; import "./TaskSearchBarListView.scss"; import { setSelectedTaskVariables } from "../../../../actions/bpmTaskActions"; import { useTranslation } from "react-i18next"; @@ -107,7 +107,7 @@ const TaskSearchBarListView = React.memo(({ toggleAllTaskVariables }) => { {displayFilter && ( <div className="clickable shadow border filter-list-view m-0 p-0"> - <TaskFilterListViewComponent + <TaskFilterViewComponent totalTasks={isTaskListLoading ? 0 : tasksCount} setDisplayFilter={setDisplayFilter} filterParams={filterParams} diff --git a/forms-flow-web/src/components/ServiceFlow/list/sort/TaskAttributeComponent.js b/forms-flow-web/src/components/ServiceFlow/list/sort/TaskAttributeComponent.js index bd69ae1e82..18fc37a7d1 100644 --- a/forms-flow-web/src/components/ServiceFlow/list/sort/TaskAttributeComponent.js +++ b/forms-flow-web/src/components/ServiceFlow/list/sort/TaskAttributeComponent.js @@ -43,7 +43,6 @@ function TaskAttributeComponent({ const UndefinedVaribaleCheckboxChange = (e) => { setShowUndefinedVariable(e.target.checked); }; - console.log("input values",inputValues); return ( <Modal show={show}