From 6d343e9b7f5fc1b38f30835c705d3db94dc13829 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 6 Feb 2025 17:35:12 -0500 Subject: [PATCH] feature/IO-3096-GlobalNotifications - Watchers - Third version, final. --- .../job-watcher-toggle.component.jsx | 110 ++++++++++++------ client/src/translations/en_us/common.json | 5 +- client/src/translations/es/common.json | 5 +- client/src/translations/fr/common.json | 5 +- 4 files changed, 88 insertions(+), 37 deletions(-) diff --git a/client/src/pages/jobs-detail/job-watcher-toggle.component.jsx b/client/src/pages/jobs-detail/job-watcher-toggle.component.jsx index 3fc09c04b..9027f1663 100644 --- a/client/src/pages/jobs-detail/job-watcher-toggle.component.jsx +++ b/client/src/pages/jobs-detail/job-watcher-toggle.component.jsx @@ -1,14 +1,14 @@ -import { useCallback, useMemo, useState } from "react"; +import React, { useCallback, useMemo, useState } from "react"; import { useMutation, useQuery } from "@apollo/client"; import { EyeFilled, EyeOutlined, UserOutlined } from "@ant-design/icons"; import { ADD_JOB_WATCHER, GET_JOB_WATCHERS, REMOVE_JOB_WATCHER } from "../../graphql/jobs.queries.js"; -import { Avatar, Button, List, Popover, Tooltip, Typography } from "antd"; +import { Avatar, Button, Divider, List, Popover, Select, Tooltip, Typography } from "antd"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors.js"; import EmployeeSearchSelectComponent from "../../components/employee-search-select/employee-search-select.component.jsx"; -import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component.jsx"; // Ensure correct path +import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component.jsx"; const { Text } = Typography; @@ -24,6 +24,7 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => { const [open, setOpen] = useState(false); const [selectedWatcher, setSelectedWatcher] = useState(null); // New state for selected value + const [selectedTeam, setSelectedTeam] = useState(null); // New state to track selected team // Fetch current watchers const { data: watcherData, loading: watcherLoading } = useQuery(GET_JOB_WATCHERS, { variables: { jobid } }); @@ -75,6 +76,45 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => { setSelectedWatcher(null); }; + const handleTeamSelect = (team) => { + const selectedTeamMembers = JSON.parse(team); // Parse the array of emails + + const newWatchers = selectedTeamMembers.filter( + (email) => !jobWatchers.some((watcher) => watcher.user_email === email) + ); + + // Add each new watcher + newWatchers.forEach((email) => { + addWatcher({ variables: { jobid, userEmail: email } }).catch((err) => + console.error(`Error adding job watcher: ${err.message}`) + ); + }); + + // Clear selection + setSelectedTeam(null); + }; + + const handleRenderItem = (watcher) => { + const employee = bodyshop.employees.find((e) => e.user_email === watcher.user_email); + const displayName = employee ? `${employee.first_name} ${employee.last_name}` : watcher.user_email; + + return ( + handleRemoveWatcher(watcher.user_email)}> + {t("notifications.actions.remove")} + + ]} + > + } />} + title={{displayName}} + description={watcher.user_email} // Keep the email for reference + /> + + ); + }; + // Popover content const popoverContent = (
@@ -88,52 +128,54 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => { > {isWatching ? t("notifications.tooltips.unwatch") : t("notifications.tooltips.watch")} - {/* List of Watchers */} {t("notifications.labels.watching-issue")} - - {watcherLoading ? ( - - ) : ( - { - const employee = bodyshop.employees.find((e) => e.user_email === watcher.user_email); - const displayName = employee ? `${employee.first_name} ${employee.last_name}` : watcher.user_email; - - return ( - handleRemoveWatcher(watcher.user_email)}> - {t("notifications.actions.remove")} - - ]} - > - } />} - title={{displayName}} - description={watcher.user_email} // Keep the email for reference - /> - - ); - }} - /> - )} - + {watcherLoading ? : } {/* Employee Search Select (for adding watchers) */} + + {t("notifications.labels.add-watchers")} jobWatchers.every((w) => w.user_email !== e.user_email))} - placeholder={t("production.labels.employeesearch")} + placeholder={t("notifications.labels.employee-search")} value={selectedWatcher} // Controlled value onChange={(value) => { setSelectedWatcher(value); // Update selected state handleWatcherSelect(value); // Add watcher logic }} /> + {/* Divider for UI separation */} + {/* Only show team selection if there are available teams */} + {bodyshop?.employee_teams?.length > 0 && ( + <> + + {t("notifications.labels.add-watchers-team")} + +