-
Notifications
You must be signed in to change notification settings - Fork 273
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
Notifications frontend #904
Merged
Merged
Changes from all commits
Commits
Show all changes
116 commits
Select commit
Hold shift + click to select a range
603384d
Add subsection (2nd level) routing to global preferences
2color 3bd241d
Notifications: authentication flow
2color 56249a7
Pass apps to notifications
2color a555477
Move api functions to separate file
2color 53c0a6d
Move components and constants into separate file and add subscriptions
2color ce50333
Fix subsection parsing
2color 83725be
Export extend error
2color d1a0424
Notifications auth flow and layout
2color 1094ddd
Upgrade @aragon/ui
2color 4a6cf4d
Fix linting errors
2color 997132b
Remove unneeded comment
2color 3ec3dcb
Pass apps to subscriptions component
2color 46e759b
Improve state handling of verify flow
2color e3eb482
Update url of notification service to live one
2color 0df8fb7
Add create subscriptions function
2color 33ac665
Add subscription creation form
2color f472d3b
Vertically align notification login form
2color e94e361
Add logout function
2color 3cc6d02
Style preverify and verify steps
2color 62d1867
Handle and style email login/verification steps
2color 8dcb3de
Use css for circle around checkmark
2color 7fee586
Add delete account function
2color c03b565
Add parent component to manage notifications and delete account
2color cfa1ed1
Filter getSubscriptions for network
2color b83a16f
Create subscription journey
2color 47aef63
Bump @aragon/ui for disabled dropdown state
2color 790dd89
Remove dependency on email in hook
2color 7ccf751
Typo correction
2color 3dbb2bb
Use index when infering subsection in global preferences
2color 08aa412
Verify token and add failed and authenticating states
2color 1b51483
Make network type compatible with backend
2color 1140652
Take single argument for consistency
2color 9b01a77
Rename contractAddress to appContractAddress
2color 15f73f2
Wrap in form to allow submission with enter key
2color a054ba2
Add email validation and style login error
2color 9e76df6
Fix typo 🙈
2color 76ee465
Use strong instead of span
2color ebf001d
Disable button while awaiting server response
2color ab682ea
Fix typo
2color c2afb65
Ensure correct order to avoid rendering problems
2color 2585472
Use ButtonText for text link
2color b108200
Add comment about network type
2color 6f99616
Use symbols for constants
2color e8d7085
Rename token to authToken for clarity
2color 3df25fe
Bump @aragon/ui
2color f7201a2
Improve email validation
2color 836df88
Add email validation icon
2color ed6c63b
Add email regex source
2color 6577afa
Remove unused theme
2color 607747c
Merge remote-tracking branch 'origin/newstyle' into newstyle-notifica…
2color b2e2a46
Submit an ABI subset with only the relevant event
2color d932092
Add deleteSubscriptions method
2color bdb2ff6
Use DataView for subscriptions table
2color 6375f39
Fix prop type
2color 474c41a
Render subscription filters
2color fd24a56
Do not reset app after creating a subscription
2color 26afff7
Add subscription filters
2color 2a4bc57
Render appName
2color e8b869f
Refine the subscription form
2color ebe2512
Style the table correctly
2color 5c8808b
style and render clear filters conditionally
2color 9eec3e0
Enable sign in button when email is valid
2color 842a9b4
Disable the log in button initially
2color 3ef0938
Use constants instead of magic numbers
2color f4a2077
Set unauthenticated state as the default too
2color 2bd21d8
Update src/components/GlobalPreferences/Notifications/ManageNotificat…
2color 2a1c1cc
Handle network error in verification
2color 442467c
Handle verification errors more generally
2color ee7572e
Update login error
2color b0fdc3a
Show logout and reset email button in verification error states
2color e51e90b
Let there be consts
2color 34ac76e
Remove completed todo
2color b459901
Use useCallback
2color 55b77cb
Render loading ring when subscriptions are fetching
2color ba0a363
Add loading DAO state
2color c640eeb
Fix bugs in form when unsubscribing and subscribing to apps
2color 23898b9
Improve subscription filters styling
2color 2d25aa0
Use named function expression for subscriptions table
2color fa0e691
Style filter buttons vertically in small layouts
2color 5ba5b31
Make function statement
2color a1bfb22
Render nothing while authenticating
2color 352a7af
Set isFetching correctly and render table once fetched
2color 1b0fbf6
Add cleanup function to useEffect hook
2color 433ea60
Merge remote-tracking branch 'origin/newstyle' into newstyle-notifica…
2color 122cab0
Update login copy
2color 6554b8f
Update different verification states to align with designs
2color 1ea0ccc
Navigate back when resetting account
2color e7e6c8f
Filter out non-relevant eventa
2color 4034014
Prettify
2color 4975906
Move errors to manage notifications and use InfoBox more generally
2color 6dce2ee
Move subscriptions table to separate component
2color f2a2fb8
Merge remote-tracking branch 'origin/newstyle' into newstyle-notifica…
2color 0f88a81
Global network error page with retry action
2color 88f6300
Remove usused import
2color ff53022
Add confirmation modal and update images
2color 295dbe8
Show image in form when subscribed to all events
2color b975615
Update delete account confirmation copy
2color 93eed0c
notifications info-box: reduce margin between header and content
2color 87ecabc
manage-notifications: make buttons consistently wide
2color 484da85
Update expired magic link token message
2color a5f52ed
Refactor and simplify verification errors
2color 6564e7c
Center the text to be aligned with the loading ring
2color cb159c1
subscriptions from: make submit button wide
2color 0911d01
Revert "Render nothing while authenticating"
2color a4e109b
Style loading states
2color 2bda588
Merge remote-tracking branch 'origin/newstyle' into newstyle-notifica…
2color a3205d1
Set consistent padding of 2/3 GU
2color dfe4899
Remove unused var
2color 1992b1c
Style verify fetching state
2color 0f788d0
Add automatic redirection upon successful verification
2color 8eebf90
Unsubscribe from table modal
2color b8444bc
Render form loading only while apps are loading
2color 987d05b
Fix bug with email input losing focus
2color 1f1dec3
Merge branch 'master' into newstyle-notifications
2color 6bda0ca
Improve mobile styles for feedback box
2color aa813ed
Make subscribe wide only in small viewports
2color File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
195 changes: 195 additions & 0 deletions
195
src/components/GlobalPreferences/Notifications/ManageNotifications.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
import React, { useState, useEffect, useCallback } from 'react' | ||
import PropTypes from 'prop-types' | ||
import { AppType } from '../../../prop-types' | ||
import { | ||
Box, | ||
Button, | ||
GU, | ||
IconTrash, | ||
IconCheck, | ||
LoadingRing, | ||
useTheme, | ||
Split, | ||
} from '@aragon/ui' | ||
import { getSubscriptions, deleteAccount } from './notification-service-api' | ||
import { | ||
NOTIFICATION_SERVICE_TOKEN_KEY, | ||
NOTIFICATION_SERVICE_EMAIL_KEY, | ||
} from './constants' | ||
import SubscriptionsForm from './SubscriptionsForm' | ||
import SubscriptionsTable from './SubscriptionsTable' | ||
import { DeleteAccountConfirmationModal } from './NotificationModals' | ||
|
||
export default function ManageNotifications({ | ||
apps, | ||
dao, | ||
email, | ||
onLogout, | ||
token, | ||
onServiceUnavailable, | ||
}) { | ||
const [apiError, setApiError] = useState(null) | ||
const [isFetching, setIsFetching] = useState(true) | ||
const [subscriptions, setSubscriptions] = useState([]) | ||
|
||
const fetchSubscriptions = useCallback(() => { | ||
setIsFetching(true) | ||
return getSubscriptions(token) | ||
.then(subscriptions => { | ||
setApiError(null) // reset the error after successfully fetching | ||
setSubscriptions(subscriptions) | ||
setIsFetching(false) | ||
return subscriptions | ||
}) | ||
.catch(error => { | ||
setIsFetching(false) | ||
setApiError(error) | ||
}) | ||
}, [token, setSubscriptions, setIsFetching, setApiError]) | ||
|
||
useEffect(() => { | ||
if (!token) { | ||
return | ||
} | ||
fetchSubscriptions() | ||
}, [fetchSubscriptions, token]) | ||
|
||
useEffect(() => { | ||
// Effect for handling api errors | ||
if (!apiError) { | ||
return | ||
} | ||
if (apiError instanceof TypeError) { | ||
onServiceUnavailable() | ||
} else { | ||
console.error('Unhandled API error:', apiError) | ||
} | ||
}, [apiError, onServiceUnavailable]) | ||
|
||
return ( | ||
<React.Fragment> | ||
<Split | ||
primary={ | ||
<SubscriptionsForm | ||
onApiError={setApiError} | ||
fetchSubscriptions={fetchSubscriptions} | ||
dao={dao} | ||
apps={apps} | ||
token={token} | ||
isFetchingSubscriptions={isFetching} | ||
subscriptions={subscriptions} | ||
/> | ||
} | ||
secondary={ | ||
<React.Fragment> | ||
<Box heading="Signed In With Email"> | ||
{email} | ||
<Button | ||
css={` | ||
margin-top: ${2 * GU}px; | ||
`} | ||
wide | ||
onClick={onLogout} | ||
> | ||
Sign Out | ||
</Button> | ||
</Box> | ||
<DeleteAccount | ||
onApiError={setApiError} | ||
token={token} | ||
onLogout={onLogout} | ||
/> | ||
</React.Fragment> | ||
} | ||
/> | ||
{(apiError || subscriptions.length > 0) && ( | ||
<SubscriptionsTable | ||
apps={apps} | ||
apiError={apiError} | ||
onApiError={setApiError} | ||
authToken={token} | ||
subscriptions={subscriptions} | ||
fetchSubscriptions={fetchSubscriptions} | ||
isFetchingSubscriptions={isFetching} | ||
/> | ||
)} | ||
</React.Fragment> | ||
) | ||
} | ||
|
||
ManageNotifications.propTypes = { | ||
apps: PropTypes.arrayOf(AppType).isRequired, | ||
dao: PropTypes.string, | ||
email: PropTypes.string, | ||
onLogout: PropTypes.func, | ||
onServiceUnavailable: PropTypes.func, | ||
token: PropTypes.string, | ||
} | ||
|
||
function DeleteAccount({ token, onLogout, onApiError }) { | ||
const [isFetching, setIsFetching] = useState(false) | ||
const [isAccountDeleted, setIsAccountDeleted] = useState(false) | ||
const theme = useTheme() | ||
|
||
const handleDeleteAccount = useCallback(async () => { | ||
try { | ||
setIsFetching(true) | ||
await deleteAccount(token) | ||
localStorage.removeItem(NOTIFICATION_SERVICE_TOKEN_KEY) | ||
localStorage.removeItem(NOTIFICATION_SERVICE_EMAIL_KEY) | ||
setIsAccountDeleted(true) | ||
onLogout() | ||
} catch (e) { | ||
onApiError(e) | ||
} | ||
setIsFetching(false) | ||
}, [token, onLogout, onApiError]) | ||
|
||
const [isModalOpen, setIsModalOpen] = useState(false) | ||
|
||
const onClick = useCallback(() => { | ||
setIsModalOpen(true) | ||
}, [setIsModalOpen]) | ||
|
||
const onCloseModal = useCallback(() => { | ||
setIsModalOpen(false) | ||
}, [setIsModalOpen]) | ||
|
||
const onModalConfirm = useCallback(() => { | ||
setIsModalOpen(false) | ||
handleDeleteAccount() | ||
}, [handleDeleteAccount, setIsModalOpen]) | ||
|
||
return ( | ||
<React.Fragment> | ||
<DeleteAccountConfirmationModal | ||
visible={isModalOpen} | ||
onConfirm={onModalConfirm} | ||
onClose={onCloseModal} | ||
/> | ||
<Box heading="Email Notification Data"> | ||
<Button wide onClick={onClick}> | ||
{isFetching ? ( | ||
<LoadingRing /> | ||
) : isAccountDeleted ? ( | ||
<IconCheck /> | ||
) : ( | ||
<IconTrash | ||
css={` | ||
color: ${theme.negative}; | ||
margin-right: ${GU}px; | ||
`} | ||
/> | ||
)} | ||
Delete your email | ||
2color marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</Button> | ||
</Box> | ||
</React.Fragment> | ||
) | ||
} | ||
|
||
DeleteAccount.propTypes = { | ||
onApiError: PropTypes.func, | ||
onLogout: PropTypes.func, | ||
token: PropTypes.string, | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
or
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.
The subsection is derived from the current path. Splitting
PATHS[index]
doesn't take the current path into account. I don't think this would work.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.
Oh, true sorry about suggesting something erroneous, but you get the gist, just an idea to use split + array destructuring, nothing else