Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue/2009 Notifications Added #2064

Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
8ec51cc
migration files
RachelDau Feb 23, 2023
de8b055
display notification in nav
RachelDau Feb 23, 2023
9809933
notification css file
RachelDau Feb 23, 2023
83ee351
nav-util functions and viewer app update
RachelDau Feb 23, 2023
d74d2a1
nav code cleanup
RachelDau Feb 23, 2023
015f169
nav unit tests and snapshots
RachelDau Feb 23, 2023
16cb203
nav store and migration file update
RachelDau Mar 1, 2023
1fe112e
initial commit for new notifiction state viewer
RachelDau Mar 1, 2023
a40b891
initial commit for visits file
RachelDau Mar 1, 2023
12c9af3
viewer users state added
RachelDau Mar 2, 2023
5f60125
viewer notifications state updated
RachelDau Mar 2, 2023
1eee465
last login checked for logic
RachelDau Mar 2, 2023
a33a0b0
Merge branch 'dev/31-taconite' into issue/2009-notification-added
RachelDau May 16, 2023
7591c1a
adds notifications to dashboard
RachelDau May 16, 2023
73a7500
merge dev-32-pigeonite
RachelDau Sep 18, 2023
08f91c8
fix notification implementation and tests
RachelDau Dec 11, 2023
ac6f836
Merge branch 'dev/33-serpierite' into issue/2009-notification-added
RachelDau Dec 11, 2023
b954c5d
remove file
RachelDau Dec 11, 2023
86ff23e
fix dependencies
RachelDau Dec 11, 2023
e6e3e51
code clean-up
RachelDau Dec 11, 2023
b6d4df3
Nav Clean-up code
RachelDau Dec 11, 2023
1cd175a
Visits Code Clean-up
RachelDau Dec 11, 2023
acf12dd
Visits code clean-up
RachelDau Dec 11, 2023
a6b3660
Update visits.js
RachelDau Dec 11, 2023
b298b88
fix last notification fails to exit issue
RachelDau Dec 11, 2023
251bdc9
dashboard clean-up
RachelDau Dec 12, 2023
4b98337
CSS Style update for notifications
RachelDau Dec 12, 2023
0e3102c
notification indicator and drop down menu added
RachelDau Jan 22, 2024
af88209
Dashboard client and server code clean-up
RachelDau Jan 22, 2024
d6ca441
default.jsx code cleanup
RachelDau Jan 22, 2024
fce6ab2
imports updated for notification component
RachelDau Jan 23, 2024
2c76339
removed hidden Notifications updated logic
RachelDau Jan 30, 2024
ec3b5af
updated migration files
RachelDau Jan 30, 2024
846e6e4
notification style update and jest tests written
RachelDau Mar 6, 2024
d87cb8b
css style exit button outside scroll
RachelDau Mar 6, 2024
e4369ab
background removed exit button
RachelDau Mar 6, 2024
b96d0c1
tab order accessibility update
RachelDau Mar 13, 2024
674b75b
update no notifications screen
RachelDau Mar 25, 2024
d4830eb
updates scaling notifications to account for long strings
RachelDau Mar 27, 2024
5556eb5
fix for safari issue with notification indicator
RachelDau Mar 27, 2024
7c74f45
capitialized Index
RachelDau Apr 29, 2024
2add759
Modal added for notifications
RachelDau Apr 30, 2024
d758ecf
remove comments
RachelDau Apr 30, 2024
5dc37a8
migrations regenerated and unit tests updated
RachelDau May 6, 2024
6ca28de
unit tests updated for notifications
RachelDau May 7, 2024
c37cc24
notification unit tests for button click updated
RachelDau May 8, 2024
ad39599
express-current-user test updated date mock
RachelDau May 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ jest.mock('../../../src/scripts/viewer/util/nav-util', () => ({
getOrderedList: jest.fn(),
getNavTarget: jest.fn(),
close: jest.fn(),
open: jest.fn()
open: jest.fn(),
isNotificationEnabled: jest.fn(),
setNotificationStatus: jest.fn(),
getNotificationTitle: jest.fn(),
getNotificationText: jest.fn()
}))

// NavStore
Expand Down Expand Up @@ -699,4 +703,57 @@ describe('Nav', () => {
component.instance().closeNavOnMobile({ target: true })
expect(NavUtil.close).toHaveBeenCalled()
})

test('renders notification appropriately (isNotificationEnabled=true)', () => {
const notification = true
NavUtil.getOrderedList.mockReturnValueOnce(navItems)
NavUtil.isNotificationEnabled.mockReturnValueOnce(notification)
const props = {
navState: {
notification
}
}

const component = renderer.create(<Nav {...props} />)
const tree = component.toJSON()
expect(tree.props.className).toEqual(expect.stringContaining('is-notification-enabled'))
expect(tree).toMatchSnapshot()
})

test('renders notification appropriately (isNotificationEnabled=false)', () => {
const notification = false
NavUtil.getOrderedList.mockReturnValueOnce(navItems)
NavUtil.isNotificationEnabled.mockReturnValueOnce(notification)
const props = {
navState: {
notification
}
}

const component = renderer.create(<Nav {...props} />)
const tree = component.toJSON()
expect(tree.props.className).toEqual(expect.stringContaining('is-not-notification-enabled'))
expect(tree).toMatchSnapshot()
})

test('onClickExitNotification exits out the notification', () => {
const notification = true
NavUtil.getOrderedList.mockReturnValueOnce(navItems)
NavUtil.isNotificationEnabled.mockReturnValueOnce(notification)
const props = {
navState: {
notification
}
}

const component = mount(<Nav {...props} />)
component.instance().selfRef = {
current: {
contains: () => false
}
}
component.instance().onClickExitNotification()
expect(NavUtil.isNotificationEnabled).toHaveBeenCalled()
expect(NavUtil.setNotificationStatus).toHaveBeenCalledWith(notification)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Object {
"nav:resetContext": [Function],
"nav:setContext": [Function],
"nav:setFlag": [Function],
"nav:setNotificationStatus": [Function],
"nav:showChildren": [Function],
"nav:toggle": [Function],
"nav:unlock": [Function],
Expand Down Expand Up @@ -279,7 +280,10 @@ Object {
"locked": true,
"navTargetHistory": Array [],
"navTargetId": null,
"notification": undefined,
"open": true,
"text": undefined,
"title": undefined,
"visitId": 11,
}
`;
Expand All @@ -296,7 +300,10 @@ Object {
"locked": false,
"navTargetHistory": Array [],
"navTargetId": null,
"notification": undefined,
"open": true,
"text": undefined,
"title": undefined,
"visitId": 11,
}
`;
Expand All @@ -313,7 +320,10 @@ Object {
"locked": false,
"navTargetHistory": Array [],
"navTargetId": null,
"notification": undefined,
"open": true,
"text": undefined,
"title": undefined,
"visitId": 11,
}
`;
Expand Down Expand Up @@ -526,6 +536,33 @@ Object {
}
`;

exports[`NavStore nav:setNotificationStatus event fires and updates state 1`] = `
Array [
"navstore:change",
]
`;

exports[`NavStore nav:setNotificationStatus event fires and updates state 2`] = `
Array [
Object {
"action": "nav:setNotificationStatus",
"draftId": undefined,
"eventVersion": "1.0.0",
"payload": Object {
"from": true,
"to": false,
},
"visitId": undefined,
},
]
`;

exports[`NavStore nav:setNotificationStatus event fires and updates state 3`] = `
Object {
"notification": false,
}
`;

exports[`NavStore nav:showChildren event fires and updates state 1`] = `
Array [
"navstore:change",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1082,4 +1082,23 @@ describe('NavStore', () => {
expect(NavUtil.goto).toHaveBeenCalledWith('mockFirstTargetId')
expect(NavUtil.goto).toHaveBeenCalledTimes(1)
})

test('nav:setNotificationStatus event fires and updates state', () => {
const notification = true
NavStore.setState({
notification
})
// simulate trigger
Dispatcher.trigger.mockReturnValueOnce()

// go
eventCallbacks['nav:setNotificationStatus']({ value: { notification: !notification } })
expect(Dispatcher.trigger).toHaveBeenCalledTimes(1)
expect(Dispatcher.trigger.mock.calls[0]).toMatchSnapshot()
expect(ViewerAPI.postEvent).toHaveBeenCalledTimes(1)
expect(ViewerAPI.postEvent.mock.calls[0]).toMatchSnapshot()
const payloadToAPI = ViewerAPI.postEvent.mock.calls[0][0].payload
expect(payloadToAPI).toEqual({ from: notification, to: !notification })
expect(NavStore.getState()).toMatchSnapshot()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -531,4 +531,40 @@ describe('NavUtil', () => {
NavUtil.resetContext()
expect(Common.flux.Dispatcher.trigger).toHaveBeenCalledWith('nav:resetContext')
})

test('isNotificationEnabled returns the notification status from a state object', () => {
const notification = true
const navState = {
notification
}
const isNotificationEnabled = NavUtil.isNotificationEnabled(navState)
expect(isNotificationEnabled).toBe(notification)
})

test('getNotificationTitle returns the notification title from a state object', () => {
const title = 'example'
const navState = {
title
}
const getNotificationTitle = NavUtil.getNotificationTitle(navState)
expect(getNotificationTitle).toBe(title)
})

test('getNotificationText returns the notification text from a state object', () => {
const text = true
const navState = {
text
}
const getNotificationText = NavUtil.getNotificationText(navState)
expect(getNotificationText).toBe(text)
})

test('setNotificationStatus calls Dispatcher.trigger', () => {
const notification = true
NavUtil.setNotificationStatus(notification)

expect(Common.flux.Dispatcher.trigger).toHaveBeenCalledWith('nav:setNotificationStatus', {
value: { notification }
})
})
})
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import './nav.scss'
import './notification.scss'

import Common from '../../common'
import FocusUtil from '../util/focus-util'
import Logo from './logo'
import NavUtil from '../util/nav-util'
import AssessmentUtil from '../util/assessment-util'
import React from 'react'
import Notification from './notification.js'

const { Button } = Common.components
const { StyleableText } = Common.text
Expand All @@ -26,6 +28,7 @@ export default class Nav extends React.Component {
this.selfRef = React.createRef()
this.hideOrShowOnResize = this.hideOrShowOnResize.bind(this)
this.closeNavOnMobile = this.closeNavOnMobile.bind(this)
this.onClickExitNotification = this.onClickExitNotification.bind(this)
}

isMobileSize() {
Expand Down Expand Up @@ -222,16 +225,27 @@ export default class Nav extends React.Component {
}
}

onClickExitNotification() {
const isNotificationEnabled = NavUtil.isNotificationEnabled(this.props.navState)
NavUtil.setNotificationStatus(!isNotificationEnabled)
}

render() {
const navState = this.props.navState
const list = NavUtil.getOrderedList(navState)
const lockEl = this.getLockEl(navState.locked)
const isNavInaccessible = navState.disabled || !navState.open

const isNotificationEnabled = NavUtil.isNotificationEnabled(this.props.navState)
const notificationTitle = NavUtil.getNotificationTitle(this.props.navState)
const notificationText = NavUtil.getNotificationText(this.props.navState)

const className =
'viewer--components--nav' +
isOrNot(navState.locked, 'locked') +
isOrNot(navState.open, 'open') +
isOrNot(!navState.disabled, 'enabled')
isOrNot(!navState.disabled, 'enabled') +
isOrNot(isNotificationEnabled, 'notification-enabled')

return (
<nav
Expand All @@ -253,6 +267,11 @@ export default class Nav extends React.Component {
<button className="toggle-button" onClick={NavUtil.toggle}>
Toggle Navigation Menu
</button>
<Notification
title={notificationTitle}
text={notificationText}
onClick={this.onClickExitNotification}
/>
<ul aria-hidden={isNavInaccessible} tabIndex="-1">
{list.map((item, index) => {
switch (item.type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,12 @@
&.is-not-open .viewer--components--logo {
opacity: 0;
}

&.is-not-notification-enabled {
.nav-menu {
display: none;
}
}
}

.is-previewing .viewer--components--nav {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react'
import './notification.scss'

class Notification extends React.Component {
constructor(props) {
super(props)
this.notificationRef = React.createRef()
}

render() {
return (
<div className="notification-banner nav-menu">
<div className="notification-header">
<h1>{this.props.title}</h1>
<button onClick={this.props.onClick} className="notification-exit-button">
X
</button>
</div>
<p>{this.props.text}</p>
</div>
)
}
}

export default Notification
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
@import '../../../scss/_includes.scss';

$poppin-pink: #af1b5c;
$focus-pink: #fbdae6;
$white: white;

h1 {
margin: 0;
}

p {
display: block;
}

.notification-banner {
background-color: $poppin-pink;
padding: 1.5em;
color: $white;
border-radius: 0.5em;
}

.notification-banner:hover {
background-color: $focus-pink;
color: $poppin-pink;
transition: all 0.2s ease;
-webkit-transition: all 0.2s ease;
}

.dashboard {
margin: 0.1em;
border-width: 1em;
}

.viewer--components--nav .nav-menu {
margin-top: 3.5em;
margin-left: 0.1em;
border-width: 0.5em;
}

.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: 0.5em;
}

.notification-exit-button:hover {
color: $focus-pink;
background-color: $poppin-pink;
}
Loading