From 86aa5bf5e7335bf59e1a5d3f85b10df052413eb6 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 3 Mar 2025 12:07:19 -0500 Subject: [PATCH] feature/IO-3096-GlobalNotifications - Checkpoint - Additional String Cleanup, loading spinner --- client/src/App/App.styles.scss | 10 ++++++++++ .../notification-center.component.jsx | 10 ++++++---- client/src/contexts/SocketIO/socketContext.jsx | 11 ++++++----- .../jobs-detail/job-watcher-toggle.component.jsx | 9 +++------ client/src/translations/en_us/common.json | 2 +- client/src/translations/es/common.json | 7 ++++++- client/src/translations/fr/common.json | 7 ++++++- server/notifications/scenarioBuilders.js | 10 ++++++++-- 8 files changed, 46 insertions(+), 20 deletions(-) diff --git a/client/src/App/App.styles.scss b/client/src/App/App.styles.scss index a2cd5bea6..9ea0a8d24 100644 --- a/client/src/App/App.styles.scss +++ b/client/src/App/App.styles.scss @@ -180,3 +180,13 @@ .muted-button:hover { color: darkgrey; } + +.notification-alert-unordered-list { + cursor: pointer; + padding: 0; + margin: 0; + + .notification-alert-unordered-list-item { + margin-right: 0; + } +} diff --git a/client/src/components/notification-center/notification-center.component.jsx b/client/src/components/notification-center/notification-center.component.jsx index 5311fc78a..246721dc7 100644 --- a/client/src/components/notification-center/notification-center.component.jsx +++ b/client/src/components/notification-center/notification-center.component.jsx @@ -1,6 +1,6 @@ import { Virtuoso } from "react-virtuoso"; -import { Alert, Badge, Button, Tooltip, Typography } from "antd"; -import { EyeFilled, EyeOutlined, CheckCircleFilled, CheckCircleOutlined } from "@ant-design/icons"; +import { Alert, Badge, Button, Space, Spin, Tooltip, Typography } from "antd"; +import { CheckCircleFilled, CheckCircleOutlined, EyeFilled, EyeOutlined } from "@ant-design/icons"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import "./notification-center.styles.scss"; @@ -66,7 +66,10 @@ const NotificationCenterComponent = ({ return (
-

{t("notifications.labels.notification-center")}

+ +

{t("notifications.labels.notification-center")}

+ {loading && !error && } +
); }; diff --git a/client/src/contexts/SocketIO/socketContext.jsx b/client/src/contexts/SocketIO/socketContext.jsx index 3a4e8b6e1..2529dba7e 100644 --- a/client/src/contexts/SocketIO/socketContext.jsx +++ b/client/src/contexts/SocketIO/socketContext.jsx @@ -12,13 +12,14 @@ import { MARK_NOTIFICATION_READ } from "../../graphql/notifications.queries.js"; import { gql, useMutation } from "@apollo/client"; +import { useTranslation } from "react-i18next"; const SocketContext = createContext(null); const INITIAL_NOTIFICATIONS = 10; /** - * Socket Provider - Scenario Notifications / Web Socket related items. + * Socket Provider - Scenario Notifications / Web Socket related items * @param children * @param bodyshop * @param navigate @@ -33,6 +34,7 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser, scenarioNot const [isConnected, setIsConnected] = useState(false); const notification = useNotification(); const userAssociationId = bodyshop?.associations?.[0]?.id; + const { t } = useTranslation(); const [markNotificationRead] = useMutation(MARK_NOTIFICATION_READ, { update: (cache, { data: { update_notifications } }) => { @@ -284,19 +286,18 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser, scenarioNot }); notification.info({ - message: `Changes for ${jobRoNumber}:`, + message: t("notifications.labels.notification-popup-title", { ro_number: jobRoNumber }), description: (
    { markNotificationRead({ variables: { id: notificationId } }) .then(() => navigate(`/manage/jobs/${jobId}`)) .catch((e) => console.error(`Error marking notification read: ${e?.message || ""}`)); }} - style={{ cursor: "pointer" }} > {notifications.map((notif, index) => ( -
  • +
  • {notif.body}
  • ))} 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 9027f1663..d74d6b7cf 100644 --- a/client/src/pages/jobs-detail/job-watcher-toggle.component.jsx +++ b/client/src/pages/jobs-detail/job-watcher-toggle.component.jsx @@ -23,8 +23,8 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => { const jobid = job.id; 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 + const [selectedWatcher, setSelectedWatcher] = useState(null); + const [selectedTeam, setSelectedTeam] = useState(null); // Fetch current watchers const { data: watcherData, loading: watcherLoading } = useQuery(GET_JOB_WATCHERS, { variables: { jobid } }); @@ -109,7 +109,7 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => { } />} title={{displayName}} - description={watcher.user_email} // Keep the email for reference + description={watcher.user_email} /> ); @@ -118,7 +118,6 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => { // Popover content const popoverContent = (
    - {/* Self-toggle Button */} - {/* List of Watchers */} {t("notifications.labels.watching-issue")} {watcherLoading ? : } - {/* Employee Search Select (for adding watchers) */} {t("notifications.labels.add-watchers")} diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index cf7756abf..53c07fc12 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -3781,7 +3781,7 @@ "new-notification-title": "New Notification:", "show-unread-only": "Show Unread", "mark-all-read": "Mark Read", - "loading": "Loading Notifications..." + "notification-popup-title": "Changes for Job #{{ro_number}}" }, "actions": { "remove": "remove" diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 4495a83c9..777737a01 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -3769,6 +3769,7 @@ }, "notifications": { "labels": { + "notification-center": "", "scenario": "", "notificationscenarios": "", "save": "", @@ -3776,7 +3777,11 @@ "add-watchers": "", "employee-search": "", "teams-search": "", - "add-watchers-team": "" + "add-watchers-team": "", + "new-notification-title": "", + "show-unread-only": "", + "mark-all-read": "", + "notification-popup-title": "" }, "actions": { "remove": "" diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 4f6ac7563..f4920775b 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -3769,6 +3769,7 @@ }, "notifications": { "labels": { + "notification-center": "", "scenario": "", "notificationscenarios": "", "save": "", @@ -3776,7 +3777,11 @@ "add-watchers": "", "employee-search": "", "teams-search": "", - "add-watchers-team": "" + "add-watchers-team": "", + "new-notification-title": "", + "show-unread-only": "", + "mark-all-read": "", + "notification-popup-title": "" }, "actions": { "remove": "" diff --git a/server/notifications/scenarioBuilders.js b/server/notifications/scenarioBuilders.js index 447585918..316b353ea 100644 --- a/server/notifications/scenarioBuilders.js +++ b/server/notifications/scenarioBuilders.js @@ -9,7 +9,13 @@ const { getJobAssignmentType } = require("./stringHelpers"); const populateWatchers = (data, result) => { data.scenarioWatchers.forEach((recipients) => { const { user, app, fcm, email, firstName, lastName, employeeId, associationId } = recipients; - if (app === true) result.app.recipients.push({ user, bodyShopId: data.bodyShopId, employeeId, associationId }); + if (app === true) + result.app.recipients.push({ + user, + bodyShopId: data.bodyShopId, + employeeId, + associationId + }); if (fcm === true) result.fcm.recipients.push(user); if (email === true) result.email.recipients.push({ user, firstName, lastName }); }); @@ -147,7 +153,7 @@ const intakeDeliveryChecklistCompletedBuilder = (data) => { * Builds notification data for job assignment events. */ const jobAssignedToMeBuilder = (data) => { - const body = `You have been assigned to [${getJobAssignmentType(data.scenarioFields?.[0])}]`; + const body = `You have been assigned to ${getJobAssignmentType(data.scenarioFields?.[0])}`; const result = { app: { jobId: data.jobId,