feature/IO-3096-GlobalNotifications - Checkpoint - Additional String Cleanup, loading spinner
This commit is contained in:
@@ -180,3 +180,13 @@
|
|||||||
.muted-button:hover {
|
.muted-button:hover {
|
||||||
color: darkgrey;
|
color: darkgrey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notification-alert-unordered-list {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
.notification-alert-unordered-list-item {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Virtuoso } from "react-virtuoso";
|
import { Virtuoso } from "react-virtuoso";
|
||||||
import { Alert, Badge, Button, Tooltip, Typography } from "antd";
|
import { Alert, Badge, Button, Space, Spin, Tooltip, Typography } from "antd";
|
||||||
import { EyeFilled, EyeOutlined, CheckCircleFilled, CheckCircleOutlined } from "@ant-design/icons";
|
import { CheckCircleFilled, CheckCircleOutlined, EyeFilled, EyeOutlined } from "@ant-design/icons";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import "./notification-center.styles.scss";
|
import "./notification-center.styles.scss";
|
||||||
@@ -66,7 +66,10 @@ const NotificationCenterComponent = ({
|
|||||||
return (
|
return (
|
||||||
<div className={`notification-center ${visible ? "visible" : ""}`}>
|
<div className={`notification-center ${visible ? "visible" : ""}`}>
|
||||||
<div className="notification-header">
|
<div className="notification-header">
|
||||||
<h3>{t("notifications.labels.notification-center")}</h3>
|
<Space direction="horizontal">
|
||||||
|
<h3>{t("notifications.labels.notification-center")}</h3>
|
||||||
|
{loading && !error && <Spin spinning={loading} size="small"></Spin>}
|
||||||
|
</Space>
|
||||||
<div className="notification-controls">
|
<div className="notification-controls">
|
||||||
<Tooltip title={t("notifications.labels.show-unread-only")}>
|
<Tooltip title={t("notifications.labels.show-unread-only")}>
|
||||||
<Button
|
<Button
|
||||||
@@ -94,7 +97,6 @@ const NotificationCenterComponent = ({
|
|||||||
endReached={loadMore}
|
endReached={loadMore}
|
||||||
itemContent={renderNotification}
|
itemContent={renderNotification}
|
||||||
/>
|
/>
|
||||||
{loading && !error && <div>{t("notifications.labels.loading")}</div>}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,13 +12,14 @@ import {
|
|||||||
MARK_NOTIFICATION_READ
|
MARK_NOTIFICATION_READ
|
||||||
} from "../../graphql/notifications.queries.js";
|
} from "../../graphql/notifications.queries.js";
|
||||||
import { gql, useMutation } from "@apollo/client";
|
import { gql, useMutation } from "@apollo/client";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const SocketContext = createContext(null);
|
const SocketContext = createContext(null);
|
||||||
|
|
||||||
const INITIAL_NOTIFICATIONS = 10;
|
const INITIAL_NOTIFICATIONS = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket Provider - Scenario Notifications / Web Socket related items.
|
* Socket Provider - Scenario Notifications / Web Socket related items
|
||||||
* @param children
|
* @param children
|
||||||
* @param bodyshop
|
* @param bodyshop
|
||||||
* @param navigate
|
* @param navigate
|
||||||
@@ -33,6 +34,7 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser, scenarioNot
|
|||||||
const [isConnected, setIsConnected] = useState(false);
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
const notification = useNotification();
|
const notification = useNotification();
|
||||||
const userAssociationId = bodyshop?.associations?.[0]?.id;
|
const userAssociationId = bodyshop?.associations?.[0]?.id;
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [markNotificationRead] = useMutation(MARK_NOTIFICATION_READ, {
|
const [markNotificationRead] = useMutation(MARK_NOTIFICATION_READ, {
|
||||||
update: (cache, { data: { update_notifications } }) => {
|
update: (cache, { data: { update_notifications } }) => {
|
||||||
@@ -284,19 +286,18 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser, scenarioNot
|
|||||||
});
|
});
|
||||||
|
|
||||||
notification.info({
|
notification.info({
|
||||||
message: `Changes for ${jobRoNumber}:`,
|
message: t("notifications.labels.notification-popup-title", { ro_number: jobRoNumber }),
|
||||||
description: (
|
description: (
|
||||||
<ul
|
<ul
|
||||||
className="notification-alert-unorderd-list"
|
className="notification-alert-unordered-list"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
markNotificationRead({ variables: { id: notificationId } })
|
markNotificationRead({ variables: { id: notificationId } })
|
||||||
.then(() => navigate(`/manage/jobs/${jobId}`))
|
.then(() => navigate(`/manage/jobs/${jobId}`))
|
||||||
.catch((e) => console.error(`Error marking notification read: ${e?.message || ""}`));
|
.catch((e) => console.error(`Error marking notification read: ${e?.message || ""}`));
|
||||||
}}
|
}}
|
||||||
style={{ cursor: "pointer" }}
|
|
||||||
>
|
>
|
||||||
{notifications.map((notif, index) => (
|
{notifications.map((notif, index) => (
|
||||||
<li className="notification-alert-unorderd-list-item" key={index}>
|
<li className="notification-alert-unordered-list-item" key={index}>
|
||||||
{notif.body}
|
{notif.body}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => {
|
|||||||
const jobid = job.id;
|
const jobid = job.id;
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [selectedWatcher, setSelectedWatcher] = useState(null); // New state for selected value
|
const [selectedWatcher, setSelectedWatcher] = useState(null);
|
||||||
const [selectedTeam, setSelectedTeam] = useState(null); // New state to track selected team
|
const [selectedTeam, setSelectedTeam] = useState(null);
|
||||||
|
|
||||||
// Fetch current watchers
|
// Fetch current watchers
|
||||||
const { data: watcherData, loading: watcherLoading } = useQuery(GET_JOB_WATCHERS, { variables: { jobid } });
|
const { data: watcherData, loading: watcherLoading } = useQuery(GET_JOB_WATCHERS, { variables: { jobid } });
|
||||||
@@ -109,7 +109,7 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => {
|
|||||||
<List.Item.Meta
|
<List.Item.Meta
|
||||||
avatar={<Avatar icon={<UserOutlined />} />}
|
avatar={<Avatar icon={<UserOutlined />} />}
|
||||||
title={<Text>{displayName}</Text>}
|
title={<Text>{displayName}</Text>}
|
||||||
description={watcher.user_email} // Keep the email for reference
|
description={watcher.user_email}
|
||||||
/>
|
/>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
);
|
);
|
||||||
@@ -118,7 +118,6 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => {
|
|||||||
// Popover content
|
// Popover content
|
||||||
const popoverContent = (
|
const popoverContent = (
|
||||||
<div style={{ width: 600 }}>
|
<div style={{ width: 600 }}>
|
||||||
{/* Self-toggle Button */}
|
|
||||||
<Button
|
<Button
|
||||||
block
|
block
|
||||||
type="text"
|
type="text"
|
||||||
@@ -128,12 +127,10 @@ const JobWatcherToggle = ({ job, currentUser, bodyshop }) => {
|
|||||||
>
|
>
|
||||||
{isWatching ? t("notifications.tooltips.unwatch") : t("notifications.tooltips.watch")}
|
{isWatching ? t("notifications.tooltips.unwatch") : t("notifications.tooltips.watch")}
|
||||||
</Button>
|
</Button>
|
||||||
{/* List of Watchers */}
|
|
||||||
<Text type="secondary" style={{ marginBottom: 8, display: "block" }}>
|
<Text type="secondary" style={{ marginBottom: 8, display: "block" }}>
|
||||||
{t("notifications.labels.watching-issue")}
|
{t("notifications.labels.watching-issue")}
|
||||||
</Text>
|
</Text>
|
||||||
{watcherLoading ? <LoadingSpinner /> : <List dataSource={jobWatchers} renderItem={handleRenderItem} />}
|
{watcherLoading ? <LoadingSpinner /> : <List dataSource={jobWatchers} renderItem={handleRenderItem} />}
|
||||||
{/* Employee Search Select (for adding watchers) */}
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<Text type="secondary">{t("notifications.labels.add-watchers")}</Text>
|
<Text type="secondary">{t("notifications.labels.add-watchers")}</Text>
|
||||||
|
|||||||
@@ -3781,7 +3781,7 @@
|
|||||||
"new-notification-title": "New Notification:",
|
"new-notification-title": "New Notification:",
|
||||||
"show-unread-only": "Show Unread",
|
"show-unread-only": "Show Unread",
|
||||||
"mark-all-read": "Mark Read",
|
"mark-all-read": "Mark Read",
|
||||||
"loading": "Loading Notifications..."
|
"notification-popup-title": "Changes for Job #{{ro_number}}"
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"remove": "remove"
|
"remove": "remove"
|
||||||
|
|||||||
@@ -3769,6 +3769,7 @@
|
|||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"labels": {
|
"labels": {
|
||||||
|
"notification-center": "",
|
||||||
"scenario": "",
|
"scenario": "",
|
||||||
"notificationscenarios": "",
|
"notificationscenarios": "",
|
||||||
"save": "",
|
"save": "",
|
||||||
@@ -3776,7 +3777,11 @@
|
|||||||
"add-watchers": "",
|
"add-watchers": "",
|
||||||
"employee-search": "",
|
"employee-search": "",
|
||||||
"teams-search": "",
|
"teams-search": "",
|
||||||
"add-watchers-team": ""
|
"add-watchers-team": "",
|
||||||
|
"new-notification-title": "",
|
||||||
|
"show-unread-only": "",
|
||||||
|
"mark-all-read": "",
|
||||||
|
"notification-popup-title": ""
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"remove": ""
|
"remove": ""
|
||||||
|
|||||||
@@ -3769,6 +3769,7 @@
|
|||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"labels": {
|
"labels": {
|
||||||
|
"notification-center": "",
|
||||||
"scenario": "",
|
"scenario": "",
|
||||||
"notificationscenarios": "",
|
"notificationscenarios": "",
|
||||||
"save": "",
|
"save": "",
|
||||||
@@ -3776,7 +3777,11 @@
|
|||||||
"add-watchers": "",
|
"add-watchers": "",
|
||||||
"employee-search": "",
|
"employee-search": "",
|
||||||
"teams-search": "",
|
"teams-search": "",
|
||||||
"add-watchers-team": ""
|
"add-watchers-team": "",
|
||||||
|
"new-notification-title": "",
|
||||||
|
"show-unread-only": "",
|
||||||
|
"mark-all-read": "",
|
||||||
|
"notification-popup-title": ""
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"remove": ""
|
"remove": ""
|
||||||
|
|||||||
@@ -9,7 +9,13 @@ const { getJobAssignmentType } = require("./stringHelpers");
|
|||||||
const populateWatchers = (data, result) => {
|
const populateWatchers = (data, result) => {
|
||||||
data.scenarioWatchers.forEach((recipients) => {
|
data.scenarioWatchers.forEach((recipients) => {
|
||||||
const { user, app, fcm, email, firstName, lastName, employeeId, associationId } = 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 (fcm === true) result.fcm.recipients.push(user);
|
||||||
if (email === true) result.email.recipients.push({ user, firstName, lastName });
|
if (email === true) result.email.recipients.push({ user, firstName, lastName });
|
||||||
});
|
});
|
||||||
@@ -147,7 +153,7 @@ const intakeDeliveryChecklistCompletedBuilder = (data) => {
|
|||||||
* Builds notification data for job assignment events.
|
* Builds notification data for job assignment events.
|
||||||
*/
|
*/
|
||||||
const jobAssignedToMeBuilder = (data) => {
|
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 = {
|
const result = {
|
||||||
app: {
|
app: {
|
||||||
jobId: data.jobId,
|
jobId: data.jobId,
|
||||||
|
|||||||
Reference in New Issue
Block a user