-
Notifications
You must be signed in to change notification settings - Fork 26
feat(UserNicknamesPanel): add ability to set IRC display nickname #449
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
base: develop
Are you sure you want to change the base?
Changes from all commits
57091d6
82a1a37
1d5a845
d6d113d
01f2d22
7bb727c
64c2433
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,11 @@ | ||
| --- | ||
| "fuelrats.com": minor | ||
| --- | ||
|
|
||
| Add ability to set IRC display nickname in user profile | ||
|
|
||
| Users can now choose which of their registered IRC nicknames appears as their primary display name. In the IRC Nicknames section of your profile: | ||
|
|
||
| - A filled star indicates your current display nickname | ||
| - Click the outline star next to any other nickname to set it as your new display nickname | ||
| - Hover over the star icons for helpful tooltips |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import { HttpStatus } from '@fuelrats/web-util/http' | ||
| import PropTypes from 'prop-types' | ||
|
|
||
| import ApiErrorBox from '~/components/MessageBox/ApiErrorBox' | ||
|
|
||
|
|
||
| function getErrorText (error) { | ||
| switch (error.code) { | ||
| case HttpStatus.CONFLICT: | ||
| return 'Nickname already registered.' | ||
|
|
||
| case HttpStatus.NOT_FOUND: | ||
| return 'Nickname not found or no longer exists.' | ||
|
|
||
| case HttpStatus.UNPROCESSABLE_ENTITY: | ||
| return 'Nickname format is invalid.' | ||
|
|
||
| default: | ||
| return undefined | ||
| } | ||
| } | ||
|
|
||
| function NicknameErrorBox (props) { | ||
| const { error } = props | ||
|
|
||
| if (!error) { | ||
| return null | ||
| } | ||
|
|
||
| return (<ApiErrorBox error={error} renderError={getErrorText} />) | ||
| } | ||
|
|
||
| NicknameErrorBox.propTypes = { | ||
| error: PropTypes.object, | ||
| } | ||
|
|
||
|
|
||
| export default NicknameErrorBox |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,18 @@ | ||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||
| import { HttpStatus } from '@fuelrats/web-util/http' | ||
| import { isError } from 'flux-standard-action' | ||
| import { useCallback, useState } from 'react' | ||
| import { useDispatch, useSelector } from 'react-redux' | ||
|
|
||
| import ConfirmActionButton from '~/components/ConfirmActionButton' | ||
| import AddNicknameForm from '~/components/Forms/AddNicknameForm/AddNicknameForm' | ||
| import MessageBox from '~/components/MessageBox' | ||
| import { deleteNickname } from '~/store/actions/user' | ||
| import { deleteNickname, setDisplayNickname, getUserProfile } from '~/store/actions/user' | ||
| import { | ||
| selectUserById, | ||
| withCurrentUserId, | ||
| selectNicknamesByUserId, | ||
| } from '~/store/selectors' | ||
| import getResponseError from '~/util/getResponseError' | ||
|
|
||
| import NicknameErrorBox from './NicknameErrorBox' | ||
| import styles from './UserNicknamesPanel.module.scss' | ||
|
|
||
|
|
||
|
|
@@ -34,28 +33,38 @@ function UserNicknamesPanel () { | |
| const user = useSelector(withCurrentUserId(selectUserById)) | ||
|
|
||
| const handleDeleteNickname = useCallback(async (event) => { | ||
| setError(null) | ||
| const response = await dispatch(deleteNickname(user, nicknames.find((nick) => { | ||
| return nick.id === event.target.name | ||
| }))) | ||
|
|
||
| if (isError(response)) { | ||
| const { meta, payload } = response | ||
| let errorMessage = 'Unknown error occurred.' | ||
| const responseError = getResponseError(response) | ||
| if (responseError) { | ||
| setError(responseError) | ||
| return responseError | ||
| } | ||
|
|
||
| if (HttpStatus.isClientError(meta.response.status)) { | ||
| errorMessage = payload.errors?.length ? payload.errors[0].detail : 'Client communication error' | ||
| } | ||
| return true | ||
| }, [dispatch, nicknames, user]) | ||
|
|
||
| if (HttpStatus.isServerError(meta.response.status)) { | ||
| errorMessage = 'Server communication error' | ||
| } | ||
| const handleSetDisplayNickname = useCallback(async (event) => { | ||
| setError(null) | ||
| const nickname = nicknames.find((nick) => { | ||
| return nick.id === event.target.name | ||
| }) | ||
|
|
||
| setError(errorMessage) | ||
| return errorMessage | ||
| const response = await dispatch(setDisplayNickname(nickname.id, nickname.attributes.nick)) | ||
|
|
||
| const responseError = getResponseError(response) | ||
| if (responseError) { | ||
| setError(responseError) | ||
| return responseError | ||
| } | ||
|
|
||
| return undefined | ||
| }, [dispatch, nicknames, user]) | ||
| // Refresh user profile to get updated nicknames | ||
| await dispatch(getUserProfile()) | ||
| return true | ||
| }, [dispatch, nicknames]) | ||
|
|
||
| const nickCount = nicknames?.length | ||
| const maxNicksReached = (nickCount >= MAX_NICKS) | ||
|
|
@@ -72,7 +81,7 @@ function UserNicknamesPanel () { | |
| <div className={styles.userNicknames}> | ||
| { | ||
| error && ( | ||
| <MessageBox>{error}</MessageBox> | ||
| <NicknameErrorBox error={error} /> | ||
| ) | ||
| } | ||
| <ul className={styles.nickList}> | ||
|
|
@@ -83,24 +92,52 @@ function UserNicknamesPanel () { | |
| } | ||
| { | ||
| nicknames?.map((nickname) => { | ||
| const isDisplayNick = nickname.attributes?.display === nickname.attributes?.nick | ||
| return ( | ||
| <li key={nickname.id}> | ||
| <span>{nickname.attributes?.nick}</span> | ||
| { | ||
| // Only render for additional nicks, prevent for display nick. | ||
| nickname.attributes?.display !== nickname.attributes?.nick && ( | ||
| <ConfirmActionButton | ||
| className="icon" | ||
| confirmButtonText={`Delete nickname '${nickname.attributes?.nick}'`} | ||
| confirmSubText="" | ||
| denyButtonText="Cancel" | ||
| name={nickname.id} | ||
| onConfirm={handleDeleteNickname} | ||
| onConfirmText=""> | ||
| <FontAwesomeIcon fixedWidth icon="trash" /> | ||
| </ConfirmActionButton> | ||
| ) | ||
| } | ||
| <span> | ||
| {nickname.attributes?.nick} | ||
| { | ||
| isDisplayNick && ( | ||
| <FontAwesomeIcon | ||
| fixedWidth | ||
| className={styles.displayIcon} | ||
| icon="star" | ||
| title="Current display nickname" /> | ||
| ) | ||
| } | ||
| </span> | ||
| <div className={styles.controlContainer}> | ||
| { | ||
| // Only show buttons for non-display nicks | ||
| !isDisplayNick && ( | ||
| <> | ||
| <ConfirmActionButton | ||
| className="icon" | ||
| confirmButtonText={`Set '${nickname.attributes?.nick}' as display nickname`} | ||
| confirmSubText="" | ||
| denyButtonText="Cancel" | ||
| name={nickname.id} | ||
| title="Set as display nickname" | ||
| onConfirm={handleSetDisplayNickname} | ||
| onConfirmText=""> | ||
| <FontAwesomeIcon fixedWidth icon="farStar" title="Set as display nickname" /> | ||
|
Member
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. the previous We only need to rename the export in |
||
| </ConfirmActionButton> | ||
| <ConfirmActionButton | ||
| className="icon" | ||
| confirmButtonText={`Delete nickname '${nickname.attributes?.nick}'`} | ||
| confirmSubText="" | ||
| denyButtonText="Cancel" | ||
| name={nickname.id} | ||
| title="Delete nickname" | ||
| onConfirm={handleDeleteNickname} | ||
| onConfirmText=""> | ||
| <FontAwesomeIcon fixedWidth icon="trash" title="Delete nickname" /> | ||
| </ConfirmActionButton> | ||
| </> | ||
| ) | ||
| } | ||
| </div> | ||
| </li> | ||
| ) | ||
| }) ?? null | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,6 +36,7 @@ export { | |
| faSignature, | ||
| faSpaceShuttle, | ||
| faSpinner, | ||
| faStar, | ||
|
Member
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. we also need to provide the regular version, since this only provides the solid version. Sorry I forgot we don't actually have this icon pack in here yet. without adding it the icon won't load properly.
To fix:
export {
faStar as farStar,
} from '@fortawesome/free-regular-svg-icons' |
||
| faSync, | ||
| faTimes, | ||
| faTimesCircle, | ||
|
|
@@ -55,3 +56,7 @@ export { | |
| faPlaystation, | ||
| faXbox, | ||
| } from '@fortawesome/free-brands-svg-icons' | ||
|
|
||
| export { | ||
| faStar as farStar, | ||
| } from '@fortawesome/free-regular-svg-icons' | ||

Uh oh!
There was an error while loading. Please reload this page.