Merge branch 'bluewave-labs:develop' into Fix-for-status-boxes
This commit is contained in:
21 files changed
+370
-219
No files matched your search
@@ -21,7 +21,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
minWidth: 400,
|
||||
bgcolor: theme.palette.primary.main,
|
||||
border: 1,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
|
||||
@@ -35,6 +35,7 @@ const Fallback = ({ title, checks, link = "/", isAdmin, vowelStart = false }) =>
|
||||
overflow="hidden"
|
||||
sx={{
|
||||
borderStyle: "dashed",
|
||||
minHeight: "calc(100vh - var(--env-var-spacing-2) * 2)",
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
.home-layout {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: var(--env-var-spacing-2);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* TODO go for this approach for responsiveness. The aside needs to be taken care of */
|
||||
@@ -15,10 +14,9 @@
|
||||
|
||||
.home-layout aside {
|
||||
position: sticky;
|
||||
top: var(--env-var-spacing-2);
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
height: calc(100vh - var(--env-var-spacing-2) * 2);
|
||||
height: 100vh;
|
||||
max-width: var(--env-var-side-bar-width);
|
||||
}
|
||||
|
||||
@@ -26,3 +24,10 @@
|
||||
min-height: calc(100vh - var(--env-var-spacing-2) * 2);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.home-content-wrapper {
|
||||
padding: var(--env-var-spacing-2);
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
flex: 1;
|
||||
}
|
||||
@@ -12,7 +12,9 @@ const HomeLayout = () => {
|
||||
gap={14}
|
||||
>
|
||||
<Sidebar />
|
||||
<Outlet />
|
||||
<Stack className="home-content-wrapper">
|
||||
<Outlet />
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
+66
-36
@@ -1,5 +1,6 @@
|
||||
import { useState, useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
@@ -49,11 +50,11 @@ const NotificationIntegrationModal = ({
|
||||
// Helper to get the field state key with error handling
|
||||
const getFieldKey = (typeId, fieldId) => {
|
||||
if (typeof typeId !== 'string' || typeId === '') {
|
||||
throw new Error('Invalid typeId provided to getFieldKey');
|
||||
throw new Error(t('errorInvalidTypeId'));
|
||||
}
|
||||
|
||||
if (typeof fieldId !== 'string' || fieldId === '') {
|
||||
throw new Error('Invalid fieldId provided to getFieldKey');
|
||||
throw new Error(t('errorInvalidFieldId'));
|
||||
}
|
||||
|
||||
return `${typeId}${fieldId.charAt(0).toUpperCase() + fieldId.slice(1)}`;
|
||||
@@ -182,43 +183,64 @@ const NotificationIntegrationModal = ({
|
||||
await sendTestNotification(type, config);
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
//notifications array for selected integrations
|
||||
const notifications = [...(monitor?.notifications || [])];
|
||||
|
||||
// Get all notification types IDs
|
||||
const existingTypes = activeNotificationTypes.map(type => type.id);
|
||||
|
||||
// Filter out notifications that are configurable in this modal
|
||||
const filteredNotifications = notifications.filter(
|
||||
notification => !existingTypes.includes(notification.type)
|
||||
);
|
||||
// In NotificationIntegrationModal.jsx, update the handleSave function:
|
||||
|
||||
// Add each enabled notification with its configured fields
|
||||
activeNotificationTypes.forEach(type => {
|
||||
if (integrations[type.id]) {
|
||||
const notificationObject = {
|
||||
type: type.id
|
||||
};
|
||||
|
||||
// Add each field value to the notification object
|
||||
type.fields.forEach(field => {
|
||||
const fieldKey = getFieldKey(type.id, field.id);
|
||||
notificationObject[field.id] = integrations[fieldKey];
|
||||
});
|
||||
|
||||
filteredNotifications.push(notificationObject);
|
||||
const handleSave = () => {
|
||||
// Get existing notifications
|
||||
const notifications = [...(monitor?.notifications || [])];
|
||||
|
||||
// Get all notification types IDs
|
||||
const existingTypes = activeNotificationTypes.map(type => type.id);
|
||||
|
||||
// Filter out notifications that are configurable in this modal
|
||||
const filteredNotifications = notifications.filter(
|
||||
notification => {
|
||||
|
||||
if (notification.platform) {
|
||||
return !existingTypes.includes(notification.platform);
|
||||
}
|
||||
});
|
||||
|
||||
return !existingTypes.includes(notification.type);
|
||||
}
|
||||
);
|
||||
|
||||
// Update monitor with new notifications
|
||||
setMonitor(prev => ({
|
||||
...prev,
|
||||
notifications: filteredNotifications
|
||||
}));
|
||||
|
||||
onClose();
|
||||
};
|
||||
// Add each enabled notification with its configured fields
|
||||
activeNotificationTypes.forEach(type => {
|
||||
if (integrations[type.id]) {
|
||||
|
||||
let notificationObject = {
|
||||
type: "webhook",
|
||||
platform: type.id, // Set platform to identify the specific service
|
||||
config: {}
|
||||
};
|
||||
|
||||
// Configure based on notification type
|
||||
switch(type.id) {
|
||||
case "slack":
|
||||
case "discord":
|
||||
notificationObject.config.webhookUrl = integrations[getFieldKey(type.id, 'webhook')];
|
||||
break;
|
||||
case "telegram":
|
||||
notificationObject.config.botToken = integrations[getFieldKey(type.id, 'token')];
|
||||
notificationObject.config.chatId = integrations[getFieldKey(type.id, 'chatId')];
|
||||
break;
|
||||
case "webhook":
|
||||
notificationObject.config.webhookUrl = integrations[getFieldKey(type.id, 'url')];
|
||||
break;
|
||||
}
|
||||
|
||||
filteredNotifications.push(notificationObject);
|
||||
}
|
||||
});
|
||||
|
||||
// Update monitor with new notifications
|
||||
setMonitor(prev => ({
|
||||
...prev,
|
||||
notifications: filteredNotifications
|
||||
}));
|
||||
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
@@ -320,4 +342,12 @@ const NotificationIntegrationModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
NotificationIntegrationModal.propTypes = {
|
||||
open: PropTypes.bool.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
monitor: PropTypes.object.isRequired,
|
||||
setMonitor: PropTypes.func.isRequired,
|
||||
notificationTypes: PropTypes.array
|
||||
};
|
||||
|
||||
export default NotificationIntegrationModal;
|
||||
@@ -205,9 +205,10 @@ function Sidebar() {
|
||||
*/
|
||||
sx={{
|
||||
position: "relative",
|
||||
border: 1,
|
||||
borderRight: `1px solid ${theme.palette.primary.lowContrast}`,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
borderRadius: 0,
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
"& :is(p, span, .MuiListSubheader-root)": {
|
||||
/*
|
||||
Text color for unselected menu items and menu headings
|
||||
@@ -399,6 +400,7 @@ function Sidebar() {
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
px: theme.spacing(4),
|
||||
pl: theme.spacing(5),
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
|
||||
@@ -653,6 +655,7 @@ function Sidebar() {
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
px: theme.spacing(4),
|
||||
pl: theme.spacing(5),
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon} </ListItemIcon>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useSelector } from "react-redux";
|
||||
import Select from "../../Inputs/Select";
|
||||
import { GenericDialog } from "../../Dialog/genericDialog";
|
||||
import DataTable from "../../Table/";
|
||||
import { useGetInviteToken } from "../../../Hooks/inviteHooks";
|
||||
/**
|
||||
* TeamPanel component manages the organization and team members,
|
||||
* providing functionalities like renaming the organization, managing team members,
|
||||
@@ -20,7 +21,6 @@ import DataTable from "../../Table/";
|
||||
|
||||
const TeamPanel = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const SPACING_GAP = theme.spacing(12);
|
||||
|
||||
const [toInvite, setToInvite] = useState({
|
||||
@@ -34,6 +34,8 @@ const TeamPanel = () => {
|
||||
const [errors, setErrors] = useState({});
|
||||
const [isSendingInvite, setIsSendingInvite] = useState(false);
|
||||
|
||||
const [getInviteToken, clearToken, isLoading, error, token] = useGetInviteToken();
|
||||
|
||||
const headers = [
|
||||
{
|
||||
id: "name",
|
||||
@@ -124,6 +126,10 @@ const TeamPanel = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const handleGetToken = async () => {
|
||||
await getInviteToken({ email: toInvite.email, role: toInvite.role });
|
||||
};
|
||||
|
||||
const handleInviteMember = async () => {
|
||||
if (!toInvite.email) {
|
||||
setErrors((prev) => ({ ...prev, email: "Email is required." }));
|
||||
@@ -146,7 +152,7 @@ const TeamPanel = () => {
|
||||
}
|
||||
|
||||
try {
|
||||
await networkService.requestInvitationToken({
|
||||
await networkService.sendInvitationToken({
|
||||
email: toInvite.email,
|
||||
role: toInvite.role,
|
||||
});
|
||||
@@ -165,6 +171,7 @@ const TeamPanel = () => {
|
||||
|
||||
const closeInviteModal = () => {
|
||||
setIsOpen(false);
|
||||
clearToken();
|
||||
setToInvite({ email: "", role: ["0"] });
|
||||
setErrors({});
|
||||
};
|
||||
@@ -275,6 +282,13 @@ const TeamPanel = () => {
|
||||
{ _id: "user", name: "User" },
|
||||
]}
|
||||
/>
|
||||
{token && <Typography>Invite link</Typography>}
|
||||
{token && (
|
||||
<TextInput
|
||||
id="invite-token"
|
||||
value={token}
|
||||
/>
|
||||
)}
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(4)}
|
||||
@@ -289,6 +303,15 @@ const TeamPanel = () => {
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
onClick={handleGetToken}
|
||||
loading={isSendingInvite}
|
||||
disabled={isDisabled}
|
||||
>
|
||||
Get token
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
@@ -296,7 +319,7 @@ const TeamPanel = () => {
|
||||
loading={isSendingInvite}
|
||||
disabled={isDisabled}
|
||||
>
|
||||
Send invite
|
||||
E-mail token
|
||||
</Button>
|
||||
</Stack>
|
||||
</GenericDialog>
|
||||
|
||||
Reference in new issue
Block a user