From 554453c9e61cfc86414459c147713c21511c272a Mon Sep 17 00:00:00 2001 From: Doug Lauder Date: Fri, 15 Apr 2022 12:59:26 -0400 Subject: [PATCH] GH-2812 Hide delete template and edit template icons unless user has permission (#2818) * hide delete template and edit template icons unless user has permission * fix jest tests --- .../boardTemplateSelector.test.tsx | 23 ++- .../boardTemplateSelectorItem.test.tsx | 134 ++++++++++++------ .../boardTemplateSelectorItem.tsx | 42 ++++-- 3 files changed, 139 insertions(+), 60 deletions(-) diff --git a/webapp/src/components/boardTemplateSelector/boardTemplateSelector.test.tsx b/webapp/src/components/boardTemplateSelector/boardTemplateSelector.test.tsx index b683903db..3ad656bbe 100644 --- a/webapp/src/components/boardTemplateSelector/boardTemplateSelector.test.tsx +++ b/webapp/src/components/boardTemplateSelector/boardTemplateSelector.test.tsx @@ -15,6 +15,7 @@ import {MemoryRouter, Router} from 'react-router-dom' import Mutator from '../../mutator' import {Utils} from '../../utils' import {Team} from '../../store/teams' +import {IUser} from '../../user' import {mockDOM, mockStateStore, wrapDNDIntl} from '../../testUtils' import BoardTemplateSelector from './boardTemplateSelector' @@ -47,6 +48,15 @@ describe('components/boardTemplateSelector/boardTemplateSelector', () => { updateAt: 0, modifiedBy: 'user-1', } + const me: IUser = { + id: 'user-id-1', + username: 'username_1', + email: '', + props: {}, + create_at: 0, + update_at: 0, + is_bot: false + } const template1Title = 'Template 1' const globalTemplateTitle = 'Template Global' const boardTitle = 'Board 1' @@ -59,9 +69,8 @@ describe('components/boardTemplateSelector/boardTemplateSelector', () => { current: team1, }, users: { - me: { - id: 'user_id_1', - }, + me, + boardUsers: [me], }, boards: { boards: [ @@ -88,6 +97,14 @@ describe('components/boardTemplateSelector/boardTemplateSelector', () => { dateDisplayPropertyId: 'id-5', }, ], + membersInBoards: { + ['1']: {userId: me.id, schemeAdmin: true}, + ['2']: {userId: me.id, schemeAdmin: true}, + }, + myBoardMemberships: { + ['1']: {userId: me.id, schemeAdmin: true}, + ['2']: {userId: me.id, schemeAdmin: true}, + }, cards: [], views: [], }, diff --git a/webapp/src/components/boardTemplateSelector/boardTemplateSelectorItem.test.tsx b/webapp/src/components/boardTemplateSelector/boardTemplateSelectorItem.test.tsx index 240bb126f..9bf2be4a6 100644 --- a/webapp/src/components/boardTemplateSelector/boardTemplateSelectorItem.test.tsx +++ b/webapp/src/components/boardTemplateSelector/boardTemplateSelectorItem.test.tsx @@ -3,9 +3,14 @@ import {render, within, act, waitFor} from '@testing-library/react' import userEvent from '@testing-library/user-event' import React from 'react' +import {MockStoreEnhanced} from 'redux-mock-store' +import {Provider as ReduxProvider} from 'react-redux' import {Board, IPropertyTemplate} from '../../blocks/board' -import {wrapDNDIntl} from '../../testUtils' +import {mockStateStore, wrapDNDIntl} from '../../testUtils' + +import {IUser} from '../../user' +import {Team} from '../../store/teams' import BoardTemplateSelectorItem from './boardTemplateSelectorItem' @@ -42,6 +47,14 @@ jest.mock('../../utils') jest.mock('../../mutator') describe('components/boardTemplateSelector/boardTemplateSelectorItem', () => { + const team1: Team = { + id: 'team-1', + title: 'Team 1', + signupToken: '', + updateAt: 0, + modifiedBy: 'user-1', + } + const template: Board = { id: '1', teamId: 'team-1', @@ -80,19 +93,44 @@ describe('components/boardTemplateSelector/boardTemplateSelectorItem', () => { properties: {}, } + const me: IUser = { + id: 'user-id-1', + username: 'username_1', + email: '', + props: {}, + create_at: 0, + update_at: 0, + is_bot: false + } + + let store:MockStoreEnhanced beforeEach(() => { jest.clearAllMocks() + const state = { + teams: { + current: team1, + }, + boards: { + current: '1', + myBoardMemberships: { + ['1']: {userId: me.id, schemeAdmin: true}, + }, + } + } + store = mockStateStore([], state) }) test('should match snapshot', async () => { const {container} = render(wrapDNDIntl( - + + + , )) expect(container).toMatchSnapshot() @@ -100,13 +138,15 @@ describe('components/boardTemplateSelector/boardTemplateSelectorItem', () => { test('should match snapshot when active', async () => { const {container} = render(wrapDNDIntl( - + + + , )) expect(container).toMatchSnapshot() @@ -114,13 +154,15 @@ describe('components/boardTemplateSelector/boardTemplateSelectorItem', () => { test('should match snapshot with global template', async () => { const {container} = render(wrapDNDIntl( - + + + , )) expect(container).toMatchSnapshot() @@ -131,13 +173,15 @@ describe('components/boardTemplateSelector/boardTemplateSelectorItem', () => { const onDelete = jest.fn() const onEdit = jest.fn() const {container} = render(wrapDNDIntl( - + + + , )) userEvent.click(container.querySelector('.BoardTemplateSelectorItem')!) @@ -152,13 +196,15 @@ describe('components/boardTemplateSelector/boardTemplateSelectorItem', () => { const onDelete = jest.fn() const onEdit = jest.fn() const {container} = render(wrapDNDIntl( - + + + , )) userEvent.click(container.querySelector('.BoardTemplateSelectorItem .EditIcon')!) @@ -176,13 +222,15 @@ describe('components/boardTemplateSelector/boardTemplateSelectorItem', () => { const root = document.createElement('div') root.setAttribute('id', 'focalboard-root-portal') render(wrapDNDIntl( - + + + , ), {container: document.body.appendChild(root)}) act(() => { diff --git a/webapp/src/components/boardTemplateSelector/boardTemplateSelectorItem.tsx b/webapp/src/components/boardTemplateSelector/boardTemplateSelectorItem.tsx index f1aa5a0df..74b514363 100644 --- a/webapp/src/components/boardTemplateSelector/boardTemplateSelectorItem.tsx +++ b/webapp/src/components/boardTemplateSelector/boardTemplateSelectorItem.tsx @@ -9,8 +9,10 @@ import DeleteIcon from '../../widgets/icons/delete' import EditIcon from '../../widgets/icons/edit' import DeleteBoardDialog from '../sidebar/deleteBoardDialog' +import BoardPermissionGate from '../permissions/boardPermissionGate' + import './boardTemplateSelectorItem.scss' -import {Constants} from "../../constants" +import {Constants, Permission} from "../../constants" type Props = { isActive: boolean @@ -43,19 +45,31 @@ const BoardTemplateSelectorItem = (props: Props) => { {/* don't show template menu options for default templates */} {template.teamId !== Constants.globalTeamId &&
- } - title={intl.formatMessage({id: 'BoardTemplateSelector.delete-template', defaultMessage: 'Delete'})} - onClick={(e: React.MouseEvent) => { - e.stopPropagation() - setDeleteOpen(true) - }} - /> - } - title={intl.formatMessage({id: 'BoardTemplateSelector.edit-template', defaultMessage: 'Edit'})} - onClick={onEditHandler} - /> + + } + title={intl.formatMessage({id: 'BoardTemplateSelector.delete-template', defaultMessage: 'Delete'})} + onClick={(e: React.MouseEvent) => { + e.stopPropagation() + setDeleteOpen(true) + }} + /> + + + } + title={intl.formatMessage({id: 'BoardTemplateSelector.edit-template', defaultMessage: 'Edit'})} + onClick={onEditHandler} + /> +
} {deleteOpen &&