diff --git a/packages/app/obojobo-repository/shared/components/notification.jsx b/packages/app/obojobo-repository/shared/components/notification.jsx
index 516ed4c5d..5561ae278 100644
--- a/packages/app/obojobo-repository/shared/components/notification.jsx
+++ b/packages/app/obojobo-repository/shared/components/notification.jsx
@@ -1,12 +1,11 @@
import React from 'react'
-import { useState, useEffect } from 'react'
import './notification.scss'
const Notification = () => {
- const [notifications, setNotifications] = useState([])
- const [hiddenNotifications, setHiddenNotifications] = useState([])
+ const [notifications, setNotifications] = React.useState([])
+ const [hiddenNotifications, setHiddenNotifications] = React.useState([])
- useEffect(() => {
+ React.useEffect(() => {
if (document && document.cookie) {
const cookiePropsRaw = decodeURIComponent(document.cookie).split(';')
diff --git a/packages/app/obojobo-repository/shared/components/notification.scss b/packages/app/obojobo-repository/shared/components/notification.scss
index 5370a8007..e97e239cd 100644
--- a/packages/app/obojobo-repository/shared/components/notification.scss
+++ b/packages/app/obojobo-repository/shared/components/notification.scss
@@ -1,17 +1,9 @@
-@import '../../../obojobo-document-engine/src/scss/_includes.scss';
+@import '~styles/includes';
$poppin-pink: #af1b5c;
$focus-pink: #fbdae6;
$white: white;
-h1 {
- margin: 0;
-}
-
-p {
- display: block;
-}
-
.notification-banner {
background-color: $poppin-pink;
padding: 1em;
@@ -19,6 +11,38 @@ p {
border-radius: 0.5em;
margin: 0.1em;
border-width: 0.5em;
+
+ h1 {
+ margin: 0;
+ }
+
+ p {
+ display: block;
+ }
+
+ .notification-header {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+
+ .notification-exit-button {
+ color: $poppin-pink;
+ background-color: $white;
+ border: none;
+ border-radius: 6em;
+ font-size: 0.8cm;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ padding-top: 0.1em;
+ padding-bottom: 0.3em;
+ }
+
+ .notification-exit-button:hover {
+ color: $focus-pink;
+ background-color: $poppin-pink;
+ }
+ }
}
.notification-banner.hidden {
@@ -31,32 +55,3 @@ p {
transition: all 0.2s ease;
-webkit-transition: all 0.2s ease;
}
-
-.dashboard {
- margin: 0.1em;
- border-width: 1em;
-}
-
-.notification-header {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
-}
-
-.notification-exit-button {
- color: $poppin-pink;
- background-color: $white;
- border: none;
- border-radius: 6em;
- font-size: 0.8cm;
- padding-left: 0.5em;
- padding-right: 0.5em;
- padding-top: 0.1em;
- padding-bottom: 0.3em;
-}
-
-.notification-exit-button:hover {
- color: $focus-pink;
- background-color: $poppin-pink;
-}
diff --git a/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-error.test.js.snap b/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-error.test.js.snap
index a9684ee44..dcaf65143 100644
--- a/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-error.test.js.snap
+++ b/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-error.test.js.snap
@@ -85,6 +85,7 @@ exports[`PageError renders when given props 1`] = `
>
firstName lastName
diff --git a/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-homepage.test.js.snap b/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-homepage.test.js.snap
index 312fa840e..52b053f9b 100644
--- a/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-homepage.test.js.snap
+++ b/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-homepage.test.js.snap
@@ -87,6 +87,7 @@ exports[`PageHomepage renders when given props 1`] = `
>
firstName lastName
diff --git a/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-login.test.js.snap b/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-login.test.js.snap
index c376fa283..33a1cd5fa 100644
--- a/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-login.test.js.snap
+++ b/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-login.test.js.snap
@@ -87,6 +87,7 @@ exports[`PageLogin renders when given props 1`] = `
>
firstName lastName
diff --git a/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-module.test.js.snap b/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-module.test.js.snap
index 1f4ec5ed3..260c26420 100644
--- a/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-module.test.js.snap
+++ b/packages/app/obojobo-repository/shared/components/pages/__snapshots__/page-module.test.js.snap
@@ -46,6 +46,7 @@ exports[`PageModule renders when given props - current user can copy and preview
>
firstName lastName
@@ -349,6 +350,7 @@ exports[`PageModule renders when given props - current user can not copy or prev
>
firstName lastName
diff --git a/packages/app/obojobo-repository/shared/components/pages/page-dashboard-client.jsx b/packages/app/obojobo-repository/shared/components/pages/page-dashboard-client.jsx
index 8b007b17a..039c2ab60 100644
--- a/packages/app/obojobo-repository/shared/components/pages/page-dashboard-client.jsx
+++ b/packages/app/obojobo-repository/shared/components/pages/page-dashboard-client.jsx
@@ -1,10 +1,8 @@
import { hydrateEl, hydrateElWithoutStore } from '../../react-utils'
import Dashboard from '../dashboard-hoc'
import DashboardReducer from '../../reducers/dashboard-reducer'
-import Notification from '../notification.jsx'
// include LayoutDefault so client side react has a copy of it
import LayoutDefault from '../layouts/default' //eslint-disable-line no-unused-vars
hydrateEl(Dashboard, DashboardReducer, '#react-hydrate-root')
-hydrateElWithoutStore(Notification, '#repository-notifications')
diff --git a/packages/app/obojobo-repository/shared/components/repository-nav.jsx b/packages/app/obojobo-repository/shared/components/repository-nav.jsx
index 361dfd0fd..4775d8388 100644
--- a/packages/app/obojobo-repository/shared/components/repository-nav.jsx
+++ b/packages/app/obojobo-repository/shared/components/repository-nav.jsx
@@ -1,12 +1,16 @@
require('./repository-nav.scss')
const React = require('react')
-const { useState } = require('react')
const Avatar = require('./avatar')
+const { check } = require('express-validator')
+const Notification = require('./notification.jsx').default
const RepositoryNav = props => {
let timeOutId
- const [isMenuOpen, setMenuOpen] = useState(false)
+ const [isMenuOpen, setMenuOpen] = React.useState(false)
+ const [isNotificationsOpen, setNotificationsOpen] = React.useState(false) // New state for notification
+ const [notificationsExist, setNotificationsExist] = React.useState(false)
+
const onCloseMenu = () => setMenuOpen(false)
const onToggleMenu = e => {
setMenuOpen(!isMenuOpen)
@@ -21,6 +25,31 @@ const RepositoryNav = props => {
const onFocusHandler = () => {
clearTimeout(timeOutId)
}
+ const onNotifications = () => {
+ setNotificationsOpen(!isNotificationsOpen)
+ }
+ //write an if notifications exist in the cookie
+
+ React.useEffect(() => {
+ if (document && document.cookie) {
+ const cookiePropsRaw = decodeURIComponent(document.cookie).split(';')
+
+ let parsedValue
+ cookiePropsRaw.forEach(c => {
+ const parts = c.trim().split('=')
+ if (parts[0] === 'notifications') {
+ parsedValue = JSON.parse(parts[1])
+ }
+ })
+
+ //if there are notifications, set notificationsExist to true
+ if (parsedValue && parsedValue.length >= 1) {
+ setNotificationsExist(true)
+ }
+ } else {
+ //there is nothing to render
+ }
+ }, [])
return (
{
{props.userId !== 0 ? (
- {props.displayName}
+
+ {props.displayName}
+
+ {notificationsExist &&
}
+
+
{
)}
+ {isNotificationsOpen && (
+
+
+
+ )}
)
}
diff --git a/packages/app/obojobo-repository/shared/components/repository-nav.scss b/packages/app/obojobo-repository/shared/components/repository-nav.scss
index 92c67e760..bb128079e 100644
--- a/packages/app/obojobo-repository/shared/components/repository-nav.scss
+++ b/packages/app/obojobo-repository/shared/components/repository-nav.scss
@@ -1,5 +1,7 @@
@import '../../client/css/defaults';
+$poppin-pink: #af1b5c;
+
.repository--section-wrapper {
max-width: $dimension-width;
margin: 0 auto;
@@ -119,6 +121,19 @@
width: 2.9em;
margin: 0;
}
+
+ .notification-indicator {
+ background: $poppin-pink;
+ border-radius: 50%;
+ width: 15px;
+ height: 15px;
+ margin-left: 5px;
+ }
+
+ .repository--nav--current-user--name {
+ display: flex;
+ align-items: center;
+ }
}
// if the last child is a link (login link instead of logged in user avatar)
diff --git a/packages/app/obojobo-repository/shared/components/repository-nav.test.js b/packages/app/obojobo-repository/shared/components/repository-nav.test.js
index fe5b67205..46f61cd20 100644
--- a/packages/app/obojobo-repository/shared/components/repository-nav.test.js
+++ b/packages/app/obojobo-repository/shared/components/repository-nav.test.js
@@ -169,4 +169,80 @@ describe('RepositoryNav', () => {
})
expectMenuToBeClosed(component)
})
+ test('loads notifications from cookies on mount', () => {
+ document.cookie =
+ 'notifications=' +
+ JSON.stringify([{ key: 1, text: 'Test Notification', title: 'Test Title' }])
+
+ const component = create(
)
+ const tree = component.toJSON()
+
+ expect(tree).toMatchSnapshot()
+ expect(document.cookie).toBe(
+ 'notifications=[{"key":1,"text":"Test Notification","title":"Test Title"}]'
+ )
+ })
+ test('renders null when document.cookie is null', () => {
+ const originalDocument = document.cookie
+ document.cookie = null
+
+ const reusableComponent =
+ let component
+ act(() => {
+ component = create(reusableComponent)
+ })
+ const tree = component.toJSON()
+ expect(tree).toMatchSnapshot()
+
+ if (document && document.cookie) {
+ //don't get here
+ } else {
+ expect(document.cookie).toBe(null)
+ }
+ document.cookie = originalDocument
+ })
+ test('toggles notifications popup on button click', () => {
+ const component = create(
)
+ const notificationsButton = component.root.findByProps({
+ className: 'repository--nav--current-user--name'
+ })
+
+ expect(component.root.findAllByProps({ className: 'popup' }).length).toBe(0)
+
+ act(() => {
+ notificationsButton.props.onClick()
+ component.update(
)
+ })
+ expect(component.root.findAllByProps({ className: 'popup' }).length).toBe(1)
+
+ act(() => {
+ notificationsButton.props.onClick()
+ component.update(
)
+ })
+ expect(component.root.findAllByProps({ className: 'popup' }).length).toBe(0)
+ })
+
+ test('renders notifications indicator when notificationsExist is true', () => {
+ const navProps = {
+ userId: 99,
+ displayName: 'Display Name',
+ userPerms: [],
+ notificationsExist: true
+ }
+ const component = create(
)
+ const notificationsIndicator = component.root.findAllByProps({
+ className: 'notification-indicator'
+ })
+ expect(navProps.notificationsExist).toBe(true)
+ expect(notificationsIndicator).toBeTruthy()
+ })
+
+ test('does not render notifications indicator when notificationsExist is false', () => {
+ const component = create(
)
+
+ const notificationsIndicators = component.root.findAllByProps({
+ className: 'notification-indicator'
+ })
+ expect(notificationsIndicators).not.toBe()
+ })
})