diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 72bbe93b..d7a6f4f9 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -5896,6 +5896,7 @@ func initHandlers() { r.HandleFunc("/api/v1/files/{fileId}", shuffle.HandleDeleteFile).Methods("DELETE", "OPTIONS") r.HandleFunc("/api/v1/files", shuffle.HandleGetFiles).Methods("GET", "OPTIONS") + // Introduced in 0.9.21 to handle notifications for e.g. failed Workflow r.HandleFunc("/api/v1/notifications", shuffle.HandleGetNotifications).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/notifications/{notificationId}/markasread", shuffle.HandleMarkAsRead).Methods("GET", "OPTIONS") //r.HandleFunc("/api/v1/notifications/{notificationId}/markasread", shuffle.HandleMarkAsRead).Methods("GET", "OPTIONS") diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 80296a32..a736599f 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -49,6 +49,36 @@ if ( window.location.port === "3000") { const App = (message, props) => { const [userdata, setUserData] = useState({}); + const [notifications, setNotifications] = useState([ + { + "image": "https://dytvr9ot2sszz.cloudfront.net/whats-new-announcements/billboard_metricsdashbd_sept2021.png", + "created_at": 1519211809934, + "updated_at": 1519211809934, + "title": "some title", + "description": "This is a description", + "dismissable": true, + "personal": false, + "org_id": "", + "tags": ["tag1", "tag2"], + "amount": 3, + "id": "123", + "read": false, + }, + { + "image": "https://dytvr9ot2sszz.cloudfront.net/whats-new-announcements/billboard_metricsdashbd_sept2021.png", + "created_at": 1519211809934, + "updated_at": 1519211809934, + "title": "some title", + "description": "This is a description", + "dismissable": true, + "personal": false, + "org_id": "", + "tags": ["tag1", "tag2"], + "amount": 3, + "id": "456", + "read": true, + } + ]); const [cookies, setCookie, removeCookie] = useCookies([]); const [isLoggedIn, setIsLoggedIn] = useState(false); const [dataset, setDataset] = useState(false); @@ -57,6 +87,7 @@ const App = (message, props) => { useEffect(() => { if (dataset === false) { + getUserNotifications() checkLogin() setDataset(true) } @@ -66,6 +97,25 @@ const App = (message, props) => { window.location = "/login" } + const getUserNotifications = () => { + fetch(`${globalUrl}/api/v1/notifications`, { + credentials: "include", + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(response => response.json()) + .then(responseJson => { + if (responseJson.success === true && responseJson.notifications !== null && responseJson.notifications !== undefined) { + console.log("RESP: ", responseJson) + setNotifications(responseJson.notifications) + } + }) + .catch(error => { + console.log("Failed getting notifications for user: ", error) + }); + } + const checkLogin = () => { var baseurl = globalUrl fetch(baseurl + "/api/v1/users/getinfo", { @@ -107,7 +157,7 @@ const App = (message, props) => { :
-
+
} /> } /> diff --git a/frontend/src/components/Header.js b/frontend/src/components/Header.js index bc50ef15..ce5dab2f 100644 --- a/frontend/src/components/Header.js +++ b/frontend/src/components/Header.js @@ -5,7 +5,7 @@ import {Link} from 'react-router-dom'; import { useTheme } from '@material-ui/core/styles'; -import { Badge, Typography, Paper, Tooltip, List, Avatar, Menu, ListItem, MenuItem, Select, Button, IconButton, Grid } from '@material-ui/core'; +import { Chip, Badge, Typography, Paper, Tooltip, List, Avatar, Menu, ListItem, MenuItem, Select, Button, IconButton, Grid } from '@material-ui/core'; import { Notifications as NotificationsIcon, Home as HomeIcon, Polymer as PolymerIcon, Apps as AppsIcon, Description as DescriptionIcon} from '@material-ui/icons'; import { useAlert } from "react-alert"; @@ -13,7 +13,7 @@ const hoverColor = "#f85a3e" const hoverOutColor = "#e8eaf6" const Header = props => { - const { globalUrl, isLoggedIn, removeCookie, homePage, isLoaded, userdata, cookies } = props; + const { globalUrl, notifications, isLoggedIn, removeCookie, homePage, isLoaded, userdata, cookies } = props; const theme = useTheme(); const [HomeHoverColor, setHomeHoverColor] = useState(hoverOutColor); @@ -22,6 +22,7 @@ const Header = props => { const [DocsHoverColor, setDocsHoverColor] = useState(hoverOutColor); const [HelpHoverColor, setHelpHoverColor] = useState(hoverOutColor); const [anchorEl, setAnchorEl] = React.useState(null); + const [anchorElAvatar, setAnchorElAvatar] = React.useState(null); const alert = useAlert() const hrefStyle = { @@ -29,6 +30,36 @@ const Header = props => { textDecoration: "none", } + const dismissNotification = (alert_id) => { + // Don't really care about the logout + fetch(`${globalUrl}/api/v1/notifications/${alert_id}/markasread`, { + credentials: "include", + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }) + .then(function(response) { + if (response.status !== 200) { + console.log("Error in response") + } + + return response.json(); + }).then(function(responseJson) { + if (responseJson.success !== undefined && responseJson.success) { + setTimeout(() => { + window.location.reload() + }, 2000) + } else { + alert.error("Failed changing org: ", responseJson.reason) + } + }) + .catch(error => { + console.log("error changing: ", error) + //removeCookie("session_token", {path: "/"}) + }) + } + // DEBUG HERE const handleClickLogout = () => { console.log("COOKIES: ", cookies, "Remover: ", removeCookie) @@ -146,17 +177,56 @@ const Header = props => { const handleClose = () => { setAnchorEl(null); + setAnchorElAvatar(null); }; - const notifications = [{ - "image": "https://dytvr9ot2sszz.cloudfront.net/whats-new-announcements/billboard_metricsdashbd_sept2021.png", - "date": "1519211809934", - "title": "some title", - "description": "This is a escription", - "dismissable": true, - "personal": false, - "org_id": "", - }] + const chipStyle = { + backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white", + } + const NotificationItem = (props) => { + const {data} = props + + return ( + + + {new Date(data.updated_at).toISOString()} + + + {data.title} + + {data.image !== undefined && data.image !== null && data.image.length > 0 ? + {data.title} + : + null + } + + {data.description} + + {/*data.tags !== undefined && data.tags !== null && data.tags.length > 0 ? + data.tags.map((tag, index) => { + return ( + { + }} + variant="outlined" + color="primary" + /> + ) + }) + : null */} + {data.read === false ? + + : null} + + ) + } const notificationMenu = @@ -172,27 +242,14 @@ const Header = props => { anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} - style={{zIndex: 10002}} + style={{zIndex: 10002, maxHeight: "100vh", overflowX: "hidden", overflowY: "auto",}} onClose={() => { handleClose() }} > {notifications.map((data, index) => { return ( - {}}> - - - - - {new Date(data.date).toISOString()} - - - {data.title} - - - - - + ) })} @@ -202,15 +259,15 @@ const Header = props => { const avatarMenu = { - setAnchorEl(event.currentTarget); + setAnchorElAvatar(event.currentTarget); }}> { handleClose() @@ -315,7 +372,7 @@ const Header = props => {
{avatarMenu} - {notificationMenu} + {/*notificationMenu*/} {userdata === undefined || userdata.admin === undefined || userdata.admin === null || !userdata.admin ? null :