Fixing minimum board roles behavior (#3836)
* Fixing minimum board roles behavior * fix unit tests * fix lint issues * update snapshot * attempt fix for unit test Co-authored-by: Scott Bishel <scott.bishel@mattermost.com> Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
parent
dfa9d8f452
commit
03d1b584ca
10 changed files with 59 additions and 43 deletions
|
@ -55,6 +55,9 @@ describe('components/rhsChannelBoardItem', () => {
|
|||
myBoardMemberships: {
|
||||
[board.id]: {userId: 'user_id_1', schemeAdmin: true},
|
||||
},
|
||||
boards: {
|
||||
[board.id]: board
|
||||
}
|
||||
}
|
||||
}
|
||||
board.updateAt = 1657311058157
|
||||
|
|
|
@ -13,6 +13,8 @@ const BoardTypePrivate = 'P'
|
|||
const boardTypes = [BoardTypeOpen, BoardTypePrivate]
|
||||
type BoardTypes = typeof boardTypes[number]
|
||||
|
||||
type MemberRole = ''|'viewer'|'commenter'|'editor'|'admin'
|
||||
|
||||
type Board = {
|
||||
id: string
|
||||
teamId: string
|
||||
|
@ -55,6 +57,7 @@ type BoardMember = {
|
|||
boardId: string
|
||||
userId: string
|
||||
roles?: string
|
||||
minimumRole: MemberRole
|
||||
schemeAdmin: boolean
|
||||
schemeEditor: boolean
|
||||
schemeCommenter: boolean
|
||||
|
|
|
@ -122,6 +122,9 @@ describe('components/boardTemplateSelector/boardTemplateSelectorItem', () => {
|
|||
myBoardMemberships: {
|
||||
1: {userId: me.id, schemeAdmin: true},
|
||||
},
|
||||
templates: {
|
||||
[template.id]: template,
|
||||
},
|
||||
},
|
||||
}
|
||||
store = mockStateStore([], state)
|
||||
|
|
|
@ -57,12 +57,8 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot 1`]
|
|||
class="d-flex menu-option__check"
|
||||
>
|
||||
<div
|
||||
class="menu-option__icon"
|
||||
>
|
||||
<div
|
||||
class="empty-icon"
|
||||
/>
|
||||
</div>
|
||||
class="noicon"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="menu-option__content"
|
||||
|
@ -310,12 +306,8 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in p
|
|||
class="d-flex menu-option__check"
|
||||
>
|
||||
<div
|
||||
class="menu-option__icon"
|
||||
>
|
||||
<div
|
||||
class="empty-icon"
|
||||
/>
|
||||
</div>
|
||||
class="noicon"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="menu-option__content"
|
||||
|
@ -563,12 +555,8 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in t
|
|||
class="d-flex menu-option__check"
|
||||
>
|
||||
<div
|
||||
class="menu-option__icon"
|
||||
>
|
||||
<div
|
||||
class="empty-icon"
|
||||
/>
|
||||
</div>
|
||||
class="noicon"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="menu-option__content"
|
||||
|
|
|
@ -103,7 +103,7 @@ const TeamPermissionsRow = (): JSX.Element => {
|
|||
check={true}
|
||||
icon={board.type === BoardTypePrivate ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
name={intl.formatMessage({id: 'BoardMember.schemeNone', defaultMessage: 'None'})}
|
||||
onClick={() => updateBoardType(board, BoardTypePrivate, 'editor')}
|
||||
onClick={() => updateBoardType(board, BoardTypePrivate, '')}
|
||||
/>
|
||||
</Menu>
|
||||
</MenuWrapper>
|
||||
|
|
|
@ -36,9 +36,9 @@ const UserPermissionsRow = (props: Props): JSX.Element => {
|
|||
let currentRole = 'Viewer'
|
||||
if (member.schemeAdmin) {
|
||||
currentRole = 'Admin'
|
||||
} else if (member.schemeEditor) {
|
||||
} else if (member.schemeEditor || member.minimumRole === 'editor') {
|
||||
currentRole = 'Editor'
|
||||
} else if (member.schemeCommenter) {
|
||||
} else if (member.schemeCommenter || member.minimumRole === 'commenter') {
|
||||
currentRole = 'Commenter'
|
||||
}
|
||||
|
||||
|
@ -69,14 +69,15 @@ const UserPermissionsRow = (props: Props): JSX.Element => {
|
|||
/>
|
||||
</button>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
id='Viewer'
|
||||
check={true}
|
||||
icon={currentRole === 'Viewer' ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
name={intl.formatMessage({id: 'BoardMember.schemeViewer', defaultMessage: 'Viewer'})}
|
||||
onClick={() => props.onUpdateBoardMember(member, 'Viewer')}
|
||||
/>
|
||||
{!board.isTemplate &&
|
||||
{(board.minimumRole === 'viewer' || board.minimumRole === '') &&
|
||||
<Menu.Text
|
||||
id='Viewer'
|
||||
check={true}
|
||||
icon={currentRole === 'Viewer' ? <CheckIcon/> : null}
|
||||
name={intl.formatMessage({id: 'BoardMember.schemeViewer', defaultMessage: 'Viewer'})}
|
||||
onClick={() => props.onUpdateBoardMember(member, 'Viewer')}
|
||||
/>}
|
||||
{!board.isTemplate && (board.minimumRole === '' || board.minimumRole === 'commenter' || board.minimumRole === 'viewer') &&
|
||||
<Menu.Text
|
||||
id='Commenter'
|
||||
check={true}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useAppSelector} from '../store/hooks'
|
||||
import {getMyBoardMembership, getCurrentBoardId} from '../store/boards'
|
||||
import {getMyBoardMembership, getCurrentBoardId, getBoard} from '../store/boards'
|
||||
import {getCurrentTeam} from '../store/teams'
|
||||
import {Utils} from '../utils'
|
||||
import {Permission} from '../constants'
|
||||
|
@ -13,6 +13,11 @@ export const useHasPermissions = (teamId: string, boardId: string, permissions:
|
|||
}
|
||||
|
||||
const member = useAppSelector(getMyBoardMembership(boardId))
|
||||
const board = useAppSelector(getBoard(boardId))
|
||||
|
||||
if (!board) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!member) {
|
||||
return false
|
||||
|
@ -31,13 +36,13 @@ export const useHasPermissions = (teamId: string, boardId: string, permissions:
|
|||
if (adminPermissions.includes(permission) && member.schemeAdmin) {
|
||||
return true
|
||||
}
|
||||
if (editorPermissions.includes(permission) && (member.schemeAdmin || member.schemeEditor)) {
|
||||
if (editorPermissions.includes(permission) && (member.schemeAdmin || member.schemeEditor || board.minimumRole === 'editor')) {
|
||||
return true
|
||||
}
|
||||
if (commenterPermissions.includes(permission) && (member.schemeAdmin || member.schemeEditor || member.schemeCommenter)) {
|
||||
if (commenterPermissions.includes(permission) && (member.schemeAdmin || member.schemeEditor || member.schemeCommenter || board.minimumRole === 'commenter')) {
|
||||
return true
|
||||
}
|
||||
if (viewerPermissions.includes(permission) && (member.schemeAdmin || member.schemeEditor || member.schemeCommenter || member.schemeViewer)) {
|
||||
if (viewerPermissions.includes(permission) && (member.schemeAdmin || member.schemeEditor || member.schemeCommenter || member.schemeViewer || board.minimumRole === 'viewer')) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,15 @@ const BoardPage = (props: Props): JSX.Element => {
|
|||
const incrementalBoardUpdate = (_: WSClient, boards: Board[]) => {
|
||||
// only takes into account the entities that belong to the team or the user boards
|
||||
const teamBoards = boards.filter((b: Board) => b.teamId === Constants.globalTeamId || b.teamId === teamId)
|
||||
const activeBoard = teamBoards.find((b: Board) => b.id === activeBoardId)
|
||||
dispatch(updateBoards(teamBoards))
|
||||
|
||||
if (activeBoard) {
|
||||
dispatch(fetchBoardMembers({
|
||||
teamId,
|
||||
boardId: activeBoardId,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
const incrementalBoardMemberUpdate = (_: WSClient, members: BoardMember[]) => {
|
||||
|
@ -157,7 +165,7 @@ const BoardPage = (props: Props): JSX.Element => {
|
|||
wsClient.removeOnChange(incrementalBoardMemberUpdate, 'boardMembers')
|
||||
wsClient.removeOnReconnect(() => dispatch(loadAction(match.params.boardId)))
|
||||
}
|
||||
}, [me?.id])
|
||||
}, [me?.id, activeBoardId])
|
||||
|
||||
const loadOrJoinBoard = useCallback(async (userId: string, boardTeamId: string, boardId: string) => {
|
||||
// and fetch its data
|
||||
|
|
|
@ -108,14 +108,6 @@ const Person = (props: PropertyProps): JSX.Element => {
|
|||
mutator.updateBoardMember(newMember, {...newMember, schemeAdmin: false, schemeEditor: true, schemeCommenter: true, schemeViewer: true})
|
||||
}, [board, card, propertyTemplate])
|
||||
|
||||
if (readOnly) {
|
||||
return (
|
||||
<div className={`Person ${props.property.valueClassName(true)}`}>
|
||||
{me ? formatOptionLabel(me) : propertyValue}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const boardUsers = useAppSelector<IUser[]>(getBoardUsersList)
|
||||
|
||||
const allowAddUsers = useHasPermissions(board.teamId, board.id, [Permission.ManageBoardRoles])
|
||||
|
@ -144,6 +136,14 @@ const Person = (props: PropertyProps): JSX.Element => {
|
|||
]
|
||||
}, [boardUsers, allowAddUsers, boardUsersById])
|
||||
|
||||
if (readOnly) {
|
||||
return (
|
||||
<div className={`Person ${props.property.valueClassName(true)}`}>
|
||||
{me ? formatOptionLabel(me) : propertyValue}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{confirmAddUser &&
|
||||
|
|
|
@ -234,7 +234,12 @@ export const getSortedTemplates = createSelector(
|
|||
|
||||
export function getBoard(boardId: string): (state: RootState) => Board|null {
|
||||
return (state: RootState): Board|null => {
|
||||
return state.boards.boards[boardId] || state.boards.templates[boardId] || null
|
||||
if (state.boards.boards && state.boards.boards[boardId]) {
|
||||
return state.boards.boards[boardId]
|
||||
} else if (state.boards.templates && state.boards.templates[boardId]) {
|
||||
return state.boards.templates[boardId]
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue