-
Notifications
You must be signed in to change notification settings - Fork 135
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
[POC] WS browser events #1895
[POC] WS browser events #1895
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import { | ||
Drawer, | ||
DrawerActions, | ||
DrawerCloseButton, | ||
DrawerContent, | ||
DrawerContentBody, | ||
DrawerPanelContent, | ||
NotificationDrawer, | ||
NotificationDrawerBody, | ||
NotificationDrawerGroup, | ||
NotificationDrawerGroupList, | ||
NotificationDrawerHeader, | ||
NotificationDrawerList, | ||
NotificationDrawerListItem, | ||
NotificationDrawerListItemBody, | ||
NotificationDrawerListItemHeader, | ||
} from '@patternfly/react-core'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
|
||
const NotificationsContent = () => { | ||
const [isBroadcastExpanded, setBroadcastExpanded] = useState(false); | ||
const notifications = useSelector(({ chrome: { notifications } }) => notifications || []); | ||
const dispatch = useDispatch(); | ||
return ( | ||
<DrawerPanelContent> | ||
<NotificationDrawer> | ||
<NotificationDrawerHeader customText="Foo bar"> | ||
<DrawerActions> | ||
<DrawerCloseButton onClick={() => dispatch({ type: 'toggle-notifications-drawer' })} /> | ||
</DrawerActions> | ||
</NotificationDrawerHeader> | ||
<NotificationDrawerBody> | ||
<NotificationDrawerGroupList> | ||
<NotificationDrawerGroup onExpand={(_e, value) => setBroadcastExpanded(value)} isExpanded={isBroadcastExpanded} title="Boradcast"> | ||
<NotificationDrawerList isHidden={!isBroadcastExpanded}> | ||
{notifications.map(({ variant = 'info', title, description }, idx) => ( | ||
<NotificationDrawerListItem key={idx} variant={variant}> | ||
<NotificationDrawerListItemHeader variant={variant} title={title} /> | ||
<NotificationDrawerListItemBody timestamp="Just now">{description}</NotificationDrawerListItemBody> | ||
</NotificationDrawerListItem> | ||
))} | ||
</NotificationDrawerList> | ||
</NotificationDrawerGroup> | ||
</NotificationDrawerGroupList> | ||
</NotificationDrawerBody> | ||
</NotificationDrawer> | ||
</DrawerPanelContent> | ||
); | ||
}; | ||
|
||
const Notifications = ({ children }) => { | ||
const isNotificationsDrawerOpen = useSelector(({ chrome: { isNotificationsDrawerOpen } }) => isNotificationsDrawerOpen); | ||
return ( | ||
<Drawer isExpanded={isNotificationsDrawerOpen}> | ||
<DrawerContent panelContent={<NotificationsContent />}> | ||
<DrawerContentBody>{children}</DrawerContentBody> | ||
</DrawerContent> | ||
</Drawer> | ||
); | ||
}; | ||
|
||
export default Notifications; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,4 +1,4 @@ | ||||||
import React from 'react'; | ||||||
import React, { useCallback, useEffect, useRef } from 'react'; | ||||||
import { Router } from 'react-router-dom'; | ||||||
import { HelpTopicContainer, QuickStartContainer } from '@patternfly/quickstarts'; | ||||||
|
||||||
|
@@ -12,11 +12,73 @@ import useQuickstartsStates from '../QuickStart/useQuickstartsStates'; | |||||
import { populateQuickstartsCatalog } from '../../redux/actions'; | ||||||
import { LazyQuickStartCatalog } from '../QuickStart/LazyQuickStartCatalog'; | ||||||
import useHelpTopicState from '../QuickStart/useHelpTopicState'; | ||||||
import Notifications from '../Notifications'; | ||||||
|
||||||
const useEvents = () => { | ||||||
console.log('Use events was for some reason triggered'); | ||||||
const events = useRef({}); | ||||||
const conn = useRef(); | ||||||
const activeModule = useSelector(({ chrome: { activeModule } }) => activeModule); | ||||||
const dispatch = useDispatch(); | ||||||
function handleEvent(payload) { | ||||||
if (payload.type === 'new-notification') { | ||||||
dispatch({ type: 'add-notification', payload }); | ||||||
} else if (payload.type === 'invalidate') { | ||||||
Object.values(events.current) | ||||||
.flat() | ||||||
.forEach((cb) => { | ||||||
cb(payload); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd check if the callback is defined in here
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's checked when a callback is registered. It will not register listener if a callback is not a function |
||||||
}); | ||||||
} | ||||||
console.log(events); | ||||||
} | ||||||
|
||||||
/** | ||||||
* Establish connection | ||||||
*/ | ||||||
useEffect(() => { | ||||||
const x = new WebSocket('ws://localhost:8080/ws'); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather see a proxy config in webpack for websockets. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have to do some research on this. I am not sure how the webpack proxy works with WS. Not sure if our implementation will work properly. |
||||||
x.onmessage = (messageEvent) => { | ||||||
const { data } = messageEvent; | ||||||
try { | ||||||
const payload = JSON.parse(data); | ||||||
handleEvent(payload); | ||||||
} catch (error) { | ||||||
console.error('Unable to parse WS message data: ', error); | ||||||
} | ||||||
}; | ||||||
conn.current = x; | ||||||
}, []); | ||||||
|
||||||
const registerEvent = useCallback( | ||||||
(type, app, entity, cb) => { | ||||||
if (typeof app !== 'string' || typeof type !== 'string' || typeof entity !== 'string' || typeof cb !== 'function') { | ||||||
throw new Error('Invalid registerEvents parameters'); | ||||||
} | ||||||
const listener = (data) => { | ||||||
if (data.type === type && data.app === app && data.entity === entity) { | ||||||
cb(data); | ||||||
} | ||||||
}; | ||||||
if (Array.isArray(events.current[activeModule])) { | ||||||
events.current[activeModule].push(listener); | ||||||
} else { | ||||||
events.current[activeModule] = [listener]; | ||||||
} | ||||||
}, | ||||||
[activeModule] | ||||||
); | ||||||
|
||||||
return registerEvent; | ||||||
}; | ||||||
|
||||||
const RootApp = (props) => { | ||||||
const dispatch = useDispatch(); | ||||||
|
||||||
const registerEvent = useEvents(); | ||||||
|
||||||
const { allQuickStartStates, setAllQuickStartStates, activeQuickStartID, setActiveQuickStartID } = useQuickstartsStates(); | ||||||
const { helpTopics, addHelpTopics, disableTopics, enableTopics } = useHelpTopicState(); | ||||||
const dispatch = useDispatch(); | ||||||
const quickStarts = useSelector( | ||||||
({ | ||||||
chrome: { | ||||||
|
@@ -69,7 +131,13 @@ const RootApp = (props) => { | |||||
|
||||||
<QuickStartContainer className="pf-u-h-100vh" {...quickStartProps}> | ||||||
<HelpTopicContainer helpTopics={helpTopics}> | ||||||
<ScalprumRoot {...props} helpTopics={helpTopics} quickstartsAPI={quickstartsAPI} helpTopicsAPI={helpTopicsAPI} /> | ||||||
<ScalprumRoot | ||||||
{...props} | ||||||
registerEvent={registerEvent} | ||||||
helpTopics={helpTopics} | ||||||
quickstartsAPI={quickstartsAPI} | ||||||
helpTopicsAPI={helpTopicsAPI} | ||||||
/> | ||||||
</HelpTopicContainer> | ||||||
</QuickStartContainer> | ||||||
</IDPChecker> | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,8 @@ import { | |
populateQuickstartsReducer, | ||
disableQuickstartsReducer, | ||
documentTitleReducer, | ||
notificationsDrawerReducer, | ||
addNewNotificationReducer, | ||
} from './reducers'; | ||
import { | ||
onGetAllTags, | ||
|
@@ -80,6 +82,8 @@ const reducers = { | |
[POPULATE_QUICKSTARTS_CATALOG]: populateQuickstartsReducer, | ||
[DISABLE_QUICKSTARTS]: disableQuickstartsReducer, | ||
[UPDATE_DOCUMENT_TITLE_REDUCER]: documentTitleReducer, | ||
'toggle-notifications-drawer': notificationsDrawerReducer, | ||
'add-notification': addNewNotificationReducer, | ||
Comment on lines
+85
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make these into constants? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely. This is just a draft to demo the features. Do not take anything seriously, only the concept. |
||
}; | ||
|
||
const globalFilter = { | ||
|
@@ -109,6 +113,7 @@ export default function () { | |
quickstarts: { | ||
quickstarts: {}, | ||
}, | ||
notifications: [], | ||
}, | ||
action | ||
) => applyReducerHash(reducers)(state, action), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about
wss:
? Also, shouldn't there be awss:///.redhat.com
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't take these seriously we I don't even know where the service will live