Adding menu options in sidebar, and improving order (#3713)
* Adding category and board options at the top * Updating UI * Updating test * Updating test * Updating icon * Fixing bug and translation * Updating createCategory component * Removing unused vars * Removing unused vars * Updating UI * fixed tests * fixed tests * fixed tests * Updating test Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Harshil Sharma <harshilsharma63@gmail.com>
This commit is contained in:
parent
61a8af8f34
commit
62ffa9c39a
24 changed files with 355 additions and 246 deletions
|
@ -23,7 +23,7 @@ exports[`components/boardSelector renders with no results 1`] = `
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -126,7 +126,7 @@ exports[`components/boardSelector renders with some results 1`] = `
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -327,7 +327,7 @@ exports[`components/boardSelector renders without start searching 1`] = `
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
|
@ -23,15 +23,8 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
height: 450px;
|
height: 450px;
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute;
|
|
||||||
right: 18px;
|
|
||||||
top: 18px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirmation-dialog-box {
|
.confirmation-dialog-box {
|
||||||
.dialog {
|
.dialog {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
|
@ -242,6 +242,7 @@
|
||||||
"Sidebar.untitled-view": "(Untitled View)",
|
"Sidebar.untitled-view": "(Untitled View)",
|
||||||
"SidebarCategories.BlocksMenu.Move": "Move To...",
|
"SidebarCategories.BlocksMenu.Move": "Move To...",
|
||||||
"SidebarCategories.CategoryMenu.CreateNew": "Create New Category",
|
"SidebarCategories.CategoryMenu.CreateNew": "Create New Category",
|
||||||
|
"SidebarCategories.CategoryMenu.CreateBoard": "Create New Board",
|
||||||
"SidebarCategories.CategoryMenu.Delete": "Delete Category",
|
"SidebarCategories.CategoryMenu.Delete": "Delete Category",
|
||||||
"SidebarCategories.CategoryMenu.DeleteModal.Body": "Boards in <b>{categoryName}</b> will move back to the Boards categories. You're not removed from any boards.",
|
"SidebarCategories.CategoryMenu.DeleteModal.Body": "Boards in <b>{categoryName}</b> will move back to the Boards categories. You're not removed from any boards.",
|
||||||
"SidebarCategories.CategoryMenu.DeleteModal.Title": "Delete this category?",
|
"SidebarCategories.CategoryMenu.DeleteModal.Title": "Delete this category?",
|
||||||
|
@ -400,4 +401,4 @@
|
||||||
"tutorial_tip.ok": "Next",
|
"tutorial_tip.ok": "Next",
|
||||||
"tutorial_tip.out": "Opt out of these tips.",
|
"tutorial_tip.out": "Opt out of these tips.",
|
||||||
"tutorial_tip.seen": "Seen this before?"
|
"tutorial_tip.seen": "Seen this before?"
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ exports[`/components/confirmationDialogBox confirmDialog should match snapshot 1
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -95,7 +95,7 @@ exports[`/components/confirmationDialogBox confirmDialog with Confirm Button Tex
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
|
@ -20,7 +20,7 @@ exports[`components/dialog should match snapshot 1`] = `
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -61,7 +61,7 @@ exports[`components/dialog should return dialog and click on cancel button 1`] =
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
background-color: rgba(var(--sidebar-text-rgb), 0.08);
|
background-color: rgba(var(--sidebar-text-rgb), 0.08);
|
||||||
color: rgba(var(--sidebar-text-rgb), 0.56);
|
color: rgba(var(--sidebar-text-rgb), 0.56);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 6px 8px;
|
padding: 6px 8px 6px 4px;
|
||||||
gap: 6px;
|
gap: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
|
@ -28,9 +28,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-board-icon {
|
.add-board-icon {
|
||||||
margin-left: 4px;
|
border-radius: 28px;
|
||||||
|
margin-left: 8px;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
flex: 0 0 28px;
|
flex: 0 0 28px;
|
||||||
|
background-color: rgba(var(--sidebar-text-rgb), 0.08);
|
||||||
|
color: rgba(var(--sidebar-text-rgb), 0.72);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(var(--sidebar-text-rgb), 0.16);
|
||||||
|
color: var(--sidebar-text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,19 @@
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
import React, {useEffect, useState} from 'react'
|
import React, {useEffect, useState} from 'react'
|
||||||
|
|
||||||
import {useIntl} from 'react-intl'
|
import {FormattedMessage, useIntl} from 'react-intl'
|
||||||
|
|
||||||
|
import MenuWrapper from '../../widgets/menuWrapper'
|
||||||
|
import CompassIcon from '../../widgets/icons/compassIcon'
|
||||||
|
import Menu from '../../widgets/menu'
|
||||||
import Search from '../../widgets/icons/search'
|
import Search from '../../widgets/icons/search'
|
||||||
|
import CreateCategory from '../createCategory/createCategory'
|
||||||
import {useAppSelector} from '../../store/hooks'
|
import {useAppSelector} from '../../store/hooks'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getOnboardingTourCategory,
|
getOnboardingTourCategory,
|
||||||
getOnboardingTourStep,
|
getOnboardingTourStep,
|
||||||
} from '../../store/users'
|
} from '../../store/users'
|
||||||
|
|
||||||
import {getCurrentCard} from '../../store/cards'
|
import {getCurrentCard} from '../../store/cards'
|
||||||
|
|
||||||
import './boardsSwitcher.scss'
|
import './boardsSwitcher.scss'
|
||||||
|
@ -26,7 +28,7 @@ import IconButton from '../../widgets/buttons/iconButton'
|
||||||
import SearchForBoardsTourStep from '../../components/onboardingTour/searchForBoards/searchForBoards'
|
import SearchForBoardsTourStep from '../../components/onboardingTour/searchForBoards/searchForBoards'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onBoardTemplateSelectorOpen?: () => void,
|
onBoardTemplateSelectorOpen: () => void,
|
||||||
userIsGuest?: boolean,
|
userIsGuest?: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,11 +37,11 @@ const BoardsSwitcher = (props: Props): JSX.Element => {
|
||||||
|
|
||||||
const [showSwitcher, setShowSwitcher] = useState<boolean>(false)
|
const [showSwitcher, setShowSwitcher] = useState<boolean>(false)
|
||||||
const onboardingTourCategory = useAppSelector(getOnboardingTourCategory)
|
const onboardingTourCategory = useAppSelector(getOnboardingTourCategory)
|
||||||
|
const [showCreateCategoryModal, setShowCreateCategoryModal] = useState(false)
|
||||||
const onboardingTourStep = useAppSelector(getOnboardingTourStep)
|
const onboardingTourStep = useAppSelector(getOnboardingTourStep)
|
||||||
const currentCard = useAppSelector(getCurrentCard)
|
const currentCard = useAppSelector(getCurrentCard)
|
||||||
const noCardOpen = !currentCard
|
const noCardOpen = !currentCard
|
||||||
|
|
||||||
|
|
||||||
const shouldViewSearchForBoardsTour = noCardOpen &&
|
const shouldViewSearchForBoardsTour = noCardOpen &&
|
||||||
onboardingTourCategory === TOUR_SIDEBAR &&
|
onboardingTourCategory === TOUR_SIDEBAR &&
|
||||||
onboardingTourStep === SidebarTourSteps.SEARCH_FOR_BOARDS.toString()
|
onboardingTourStep === SidebarTourSteps.SEARCH_FOR_BOARDS.toString()
|
||||||
|
@ -68,6 +70,10 @@ const BoardsSwitcher = (props: Props): JSX.Element => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleCreateNewCategory = () => {
|
||||||
|
setShowCreateCategoryModal(true)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.addEventListener('keydown', handleQuickSwitchKeyPress)
|
document.addEventListener('keydown', handleQuickSwitchKeyPress)
|
||||||
document.addEventListener('keydown', handleEscKeyPress)
|
document.addEventListener('keydown', handleEscKeyPress)
|
||||||
|
@ -95,19 +101,53 @@ const BoardsSwitcher = (props: Props): JSX.Element => {
|
||||||
{shouldViewSearchForBoardsTour && <div><SearchForBoardsTourStep/></div>}
|
{shouldViewSearchForBoardsTour && <div><SearchForBoardsTourStep/></div>}
|
||||||
{
|
{
|
||||||
Utils.isFocalboardPlugin() && !props.userIsGuest &&
|
Utils.isFocalboardPlugin() && !props.userIsGuest &&
|
||||||
<IconButton
|
<MenuWrapper>
|
||||||
size='small'
|
<IconButton
|
||||||
inverted={true}
|
size='small'
|
||||||
className='add-board-icon'
|
inverted={true}
|
||||||
onClick={props.onBoardTemplateSelectorOpen}
|
className='add-board-icon'
|
||||||
icon={<AddIcon/>}
|
icon={<AddIcon/>}
|
||||||
/>
|
/>
|
||||||
|
<Menu>
|
||||||
|
<Menu.Text
|
||||||
|
id='create-new-board-option'
|
||||||
|
icon={<CompassIcon icon='plus' />}
|
||||||
|
onClick={props.onBoardTemplateSelectorOpen}
|
||||||
|
name='Create new board'
|
||||||
|
/>
|
||||||
|
<Menu.Text
|
||||||
|
id='createNewCategory'
|
||||||
|
name={intl.formatMessage({id: 'SidebarCategories.CategoryMenu.CreateNew', defaultMessage: 'Create New Category'})}
|
||||||
|
icon={
|
||||||
|
<CompassIcon
|
||||||
|
icon='folder-plus-outline'
|
||||||
|
className='CreateNewFolderIcon'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onClick={handleCreateNewCategory}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
</MenuWrapper>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
showSwitcher &&
|
showSwitcher &&
|
||||||
<BoardSwitcherDialog onClose={() => setShowSwitcher(false)} />
|
<BoardSwitcherDialog onClose={() => setShowSwitcher(false)} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
showCreateCategoryModal && (
|
||||||
|
<CreateCategory
|
||||||
|
onClose={() => setShowCreateCategoryModal(false)}
|
||||||
|
title={(
|
||||||
|
<FormattedMessage
|
||||||
|
id='SidebarCategories.CategoryMenu.CreateNew'
|
||||||
|
defaultMessage='Create New Category'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ exports[`component/BoardSwitcherDialog base case 1`] = `
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
|
@ -10,10 +10,6 @@
|
||||||
color: rgba(var(--center-channel-color-rgb), 0.56);
|
color: rgba(var(--center-channel-color-rgb), 0.56);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -20,7 +20,7 @@ exports[`components/createCategory/CreateCategory base case should match snapsho
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -35,7 +35,9 @@ exports[`components/createCategory/CreateCategory base case should match snapsho
|
||||||
<div
|
<div
|
||||||
class="CreateCategory"
|
class="CreateCategory"
|
||||||
>
|
>
|
||||||
<h3>
|
<h3
|
||||||
|
class="dialog-title"
|
||||||
|
>
|
||||||
<span>
|
<span>
|
||||||
title
|
title
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -4,20 +4,14 @@
|
||||||
.wrapper {
|
.wrapper {
|
||||||
.dialog {
|
.dialog {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
height: 260px;
|
height: auto;
|
||||||
}
|
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
padding: 2px 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.CreateCategory {
|
.CreateCategory {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 0 40px 30px;
|
padding: 0 32px 24px;
|
||||||
gap: 12px;
|
gap: 24px;
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
.inputWrapper {
|
.inputWrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -38,18 +32,20 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
height: 48px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
padding: 6px 12px;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 2px solid rgba(var(--center-channel-color-rgb), 0.16);
|
border: 1px solid rgba(var(--center-channel-color-rgb), 0.16);
|
||||||
|
background: var(--center-channel-bg);
|
||||||
|
color: var(--center-channel-color);
|
||||||
|
padding: 0 16px;
|
||||||
|
flex: 1;
|
||||||
|
transition: border 0.15s ease-in;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: var(--button-bg);
|
border-color: var(--button-bg);
|
||||||
|
box-shadow: inset 0 0 0 1px var(--button-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,59 @@ import {render} from "@testing-library/react"
|
||||||
|
|
||||||
import userEvent from "@testing-library/user-event"
|
import userEvent from "@testing-library/user-event"
|
||||||
|
|
||||||
import {wrapIntl} from "../../testUtils"
|
import thunk from "redux-thunk"
|
||||||
|
|
||||||
|
import {Provider as ReduxProvider} from 'react-redux'
|
||||||
|
|
||||||
|
import {mocked} from "jest-mock"
|
||||||
|
|
||||||
|
import {mockStateStore, wrapIntl} from "../../testUtils"
|
||||||
|
|
||||||
|
import {IUser} from "../../user"
|
||||||
|
|
||||||
|
import mutator from "../../mutator"
|
||||||
|
|
||||||
import CreateCategory from "./createCategory"
|
import CreateCategory from "./createCategory"
|
||||||
|
|
||||||
|
jest.mock('../../mutator')
|
||||||
|
const mockedMutator = mocked(mutator, true)
|
||||||
|
|
||||||
describe('components/createCategory/CreateCategory', () => {
|
describe('components/createCategory/CreateCategory', () => {
|
||||||
|
const me: IUser = {
|
||||||
|
id: 'user-id-1',
|
||||||
|
username: 'username_1',
|
||||||
|
email: '',
|
||||||
|
nickname: '',
|
||||||
|
firstname: '',
|
||||||
|
lastname: '',
|
||||||
|
props: {},
|
||||||
|
create_at: 0,
|
||||||
|
update_at: 0,
|
||||||
|
is_bot: false,
|
||||||
|
roles: 'system_user',
|
||||||
|
is_guest: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
teams: {
|
||||||
|
current: {id: 'team-id', title: 'Test Team'},
|
||||||
|
},
|
||||||
|
users: {
|
||||||
|
me,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const store = mockStateStore([thunk], state)
|
||||||
|
|
||||||
it('base case should match snapshot', () => {
|
it('base case should match snapshot', () => {
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<CreateCategory
|
<ReduxProvider store={store}>
|
||||||
onClose={jest.fn()}
|
<CreateCategory
|
||||||
onCreate={jest.fn()}
|
onClose={jest.fn()}
|
||||||
title={
|
title={
|
||||||
<span>{'title'}</span>
|
<span>{'title'}</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</ReduxProvider>
|
||||||
)
|
)
|
||||||
|
|
||||||
const {container} = render(component)
|
const {container} = render(component)
|
||||||
|
@ -30,13 +69,14 @@ describe('components/createCategory/CreateCategory', () => {
|
||||||
it('should call onClose on being closed', () => {
|
it('should call onClose on being closed', () => {
|
||||||
const onCloseHandler = jest.fn()
|
const onCloseHandler = jest.fn()
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<CreateCategory
|
<ReduxProvider store={store}>
|
||||||
onClose={onCloseHandler}
|
<CreateCategory
|
||||||
onCreate={jest.fn()}
|
onClose={onCloseHandler}
|
||||||
title={
|
title={
|
||||||
<span>{'title'}</span>
|
<span>{'title'}</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</ReduxProvider>
|
||||||
)
|
)
|
||||||
|
|
||||||
const {container} = render(component)
|
const {container} = render(component)
|
||||||
|
@ -52,35 +92,39 @@ describe('components/createCategory/CreateCategory', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should call onCreate on pressing enter', () => {
|
it('should call onCreate on pressing enter', () => {
|
||||||
const onCreateHandler = jest.fn()
|
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<CreateCategory
|
<ReduxProvider store={store}>
|
||||||
onClose={jest.fn()}
|
<CreateCategory
|
||||||
onCreate={onCreateHandler}
|
onClose={jest.fn()}
|
||||||
title={
|
title={
|
||||||
<span>{'title'}</span>
|
<span>{'title'}</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</ReduxProvider>
|
||||||
)
|
)
|
||||||
|
|
||||||
const {container} = render(component)
|
const {container} = render(component)
|
||||||
const inputField = container.querySelector('.categoryNameInput')
|
const inputField = container.querySelector('.categoryNameInput')
|
||||||
expect(inputField).toBeTruthy()
|
expect(inputField).toBeTruthy()
|
||||||
userEvent.type(inputField as Element, 'category name{enter}')
|
userEvent.type(inputField as Element, 'category name{enter}')
|
||||||
expect(onCreateHandler).toBeCalledWith('category name')
|
expect(mockedMutator.createCategory).toBeCalledWith({
|
||||||
|
name: "category name",
|
||||||
|
teamID: "team-id",
|
||||||
|
userID: "user-id-1",
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should show initial value', () => {
|
it('should show initial value', () => {
|
||||||
const onCreateHandler = jest.fn()
|
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<CreateCategory
|
<ReduxProvider store={store}>
|
||||||
initialValue='Dwight prank ideas'
|
<CreateCategory
|
||||||
onClose={jest.fn()}
|
initialValue='Dwight prank ideas'
|
||||||
onCreate={onCreateHandler}
|
onClose={jest.fn()}
|
||||||
title={
|
title={
|
||||||
<span>{'title'}</span>
|
<span>{'title'}</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</ReduxProvider>
|
||||||
)
|
)
|
||||||
|
|
||||||
const {container} = render(component)
|
const {container} = render(component)
|
||||||
|
@ -90,16 +134,16 @@ describe('components/createCategory/CreateCategory', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should clear input field on clicking clear icon', () => {
|
it('should clear input field on clicking clear icon', () => {
|
||||||
const onCreateHandler = jest.fn()
|
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<CreateCategory
|
<ReduxProvider store={store}>
|
||||||
initialValue='Dunder Mifflin'
|
<CreateCategory
|
||||||
onClose={jest.fn()}
|
initialValue='Dunder Mifflin'
|
||||||
onCreate={onCreateHandler}
|
onClose={jest.fn()}
|
||||||
title={
|
title={
|
||||||
<span>{'title'}</span>
|
<span>{'title'}</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</ReduxProvider>
|
||||||
)
|
)
|
||||||
|
|
||||||
const {container} = render(component)
|
const {container} = render(component)
|
||||||
|
|
|
@ -5,6 +5,17 @@ import React, {useState, KeyboardEvent} from 'react'
|
||||||
|
|
||||||
import {useIntl} from 'react-intl'
|
import {useIntl} from 'react-intl'
|
||||||
|
|
||||||
|
import {IUser} from '../../user'
|
||||||
|
import {Category} from '../../store/sidebar'
|
||||||
|
import {getCurrentTeam} from '../../store/teams'
|
||||||
|
import mutator from '../../mutator'
|
||||||
|
import {useAppSelector} from '../../store/hooks'
|
||||||
|
import {
|
||||||
|
getMe,
|
||||||
|
} from '../../store/users'
|
||||||
|
|
||||||
|
import {Utils} from '../../utils'
|
||||||
|
|
||||||
import Dialog from '../dialog'
|
import Dialog from '../dialog'
|
||||||
import Button from '../../widgets/buttons/button'
|
import Button from '../../widgets/buttons/button'
|
||||||
|
|
||||||
|
@ -12,15 +23,18 @@ import './createCategory.scss'
|
||||||
import CloseCircle from "../../widgets/icons/closeCircle"
|
import CloseCircle from "../../widgets/icons/closeCircle"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
boardCategoryId?: string
|
||||||
|
renameModal?: boolean
|
||||||
initialValue?: string
|
initialValue?: string
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
onCreate: (name: string) => void
|
|
||||||
title: JSX.Element
|
title: JSX.Element
|
||||||
}
|
}
|
||||||
|
|
||||||
const CreateCategory = (props: Props): JSX.Element => {
|
const CreateCategory = (props: Props): JSX.Element => {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
const me = useAppSelector<IUser|null>(getMe)
|
||||||
|
const team = useAppSelector(getCurrentTeam)
|
||||||
|
const teamID = team?.id || ''
|
||||||
const placeholder = intl.formatMessage({id: 'Categories.CreateCategoryDialog.Placeholder', defaultMessage: 'Name your category' })
|
const placeholder = intl.formatMessage({id: 'Categories.CreateCategoryDialog.Placeholder', defaultMessage: 'Name your category' })
|
||||||
const cancelText = intl.formatMessage({id: 'Categories.CreateCategoryDialog.CancelText', defaultMessage: 'Cancel' })
|
const cancelText = intl.formatMessage({id: 'Categories.CreateCategoryDialog.CancelText', defaultMessage: 'Cancel' })
|
||||||
const createText = intl.formatMessage({id: 'Categories.CreateCategoryDialog.CreateText', defaultMessage: 'Create' })
|
const createText = intl.formatMessage({id: 'Categories.CreateCategoryDialog.CreateText', defaultMessage: 'Create' })
|
||||||
|
@ -30,17 +44,45 @@ const CreateCategory = (props: Props): JSX.Element => {
|
||||||
|
|
||||||
const handleKeypress = (e: KeyboardEvent) => {
|
const handleKeypress = (e: KeyboardEvent) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
props.onCreate(name)
|
onCreate(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onCreate = async (categoryName: string) => {
|
||||||
|
if (!me) {
|
||||||
|
Utils.logError('me not initialized')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.renameModal) {
|
||||||
|
const category: Category = {
|
||||||
|
name: categoryName,
|
||||||
|
id: props.boardCategoryId,
|
||||||
|
userID: me.id,
|
||||||
|
teamID,
|
||||||
|
} as Category
|
||||||
|
|
||||||
|
await mutator.updateCategory(category)
|
||||||
|
} else {
|
||||||
|
const category: Category = {
|
||||||
|
name: categoryName,
|
||||||
|
userID: me.id,
|
||||||
|
teamID,
|
||||||
|
} as Category
|
||||||
|
|
||||||
|
await mutator.createCategory(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
className='CreateCategoryModal'
|
className='CreateCategoryModal'
|
||||||
onClose={props.onClose}
|
onClose={props.onClose}
|
||||||
>
|
>
|
||||||
<div className='CreateCategory'>
|
<div className='CreateCategory'>
|
||||||
<h3>{props.title}</h3>
|
<h3 className='dialog-title'>{props.title}</h3>
|
||||||
<div className='inputWrapper'>
|
<div className='inputWrapper'>
|
||||||
<input
|
<input
|
||||||
className='categoryNameInput'
|
className='categoryNameInput'
|
||||||
|
@ -70,7 +112,7 @@ const CreateCategory = (props: Props): JSX.Element => {
|
||||||
<Button
|
<Button
|
||||||
size={'medium'}
|
size={'medium'}
|
||||||
filled={Boolean(name.trim())}
|
filled={Boolean(name.trim())}
|
||||||
onClick={() => props.onCreate(name.trim())}
|
onClick={() => onCreate(name.trim())}
|
||||||
disabled={!(name.trim())}
|
disabled={!(name.trim())}
|
||||||
>
|
>
|
||||||
{props.initialValue ? updateText : createText}
|
{props.initialValue ? updateText : createText}
|
||||||
|
|
|
@ -10,6 +10,19 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
margin-top: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog__close {
|
||||||
|
top: 18px;
|
||||||
|
right: 18px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
.backdrop {
|
.backdrop {
|
||||||
@include z-index(dialog-backdrop);
|
@include z-index(dialog-backdrop);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -26,14 +39,8 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
padding: 16px;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog {
|
.dialog {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: rgb(var(--center-channel-bg-rgb));
|
background-color: rgb(var(--center-channel-bg-rgb));
|
||||||
|
@ -55,6 +62,7 @@
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 975px) {
|
@media screen and (max-width: 975px) {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -63,26 +71,33 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
> * {
|
>* {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .banner {
|
>.banner {
|
||||||
background-color: rgba(230, 220, 192, 0.9);
|
background-color: rgba(230, 220, 192, 0.9);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: #222;
|
color: #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .banner.error {
|
>.banner.error {
|
||||||
background-color: rgba(230, 192, 192, 0.9);
|
background-color: rgba(230, 192, 192, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
> .toolbar {
|
.IconButton {
|
||||||
display: flex;
|
color: rgba(var(--center-channel-color-rgb), 0.56);
|
||||||
flex-direction: row;
|
|
||||||
padding: 24px;
|
&:hover {
|
||||||
justify-content: space-between;
|
color: rgba(var(--center-channel-color-rgb), 0.72);
|
||||||
|
background-color: rgba(var(--center-channel-color-rgb), 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: rgba(var(--button-bg-rgb), 0.08);
|
||||||
|
color: rgba(var(--button-bg-rgb), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar--right {
|
.toolbar--right {
|
||||||
|
@ -90,7 +105,7 @@
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .content {
|
>.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
@ -98,12 +113,13 @@
|
||||||
@media not screen and (max-width: 975px) {
|
@media not screen and (max-width: 975px) {
|
||||||
padding: 10px 126px;
|
padding: 10px 126px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 975px) {
|
@media screen and (max-width: 975px) {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .content.fullwidth {
|
>.content.fullwidth {
|
||||||
padding-left: 78px;
|
padding-left: 78px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ const Dialog = (props: Props) => {
|
||||||
}
|
}
|
||||||
isBackdropClickedRef.current = false
|
isBackdropClickedRef.current = false
|
||||||
props.onClose()
|
props.onClose()
|
||||||
|
|
||||||
}}
|
}}
|
||||||
onMouseDown={(e) => {
|
onMouseDown={(e) => {
|
||||||
if(e.target === e.currentTarget){
|
if(e.target === e.currentTarget){
|
||||||
|
@ -58,10 +58,11 @@ const Dialog = (props: Props) => {
|
||||||
className='dialog'
|
className='dialog'
|
||||||
>
|
>
|
||||||
<div className='toolbar'>
|
<div className='toolbar'>
|
||||||
{title && <h1 className='text-heading5 mt-2'>{title}</h1>}
|
{title && <h1 className='dialog-title'>{title}</h1>}
|
||||||
{
|
{
|
||||||
!props.hideCloseButton &&
|
!props.hideCloseButton &&
|
||||||
<IconButton
|
<IconButton
|
||||||
|
className='dialog__close'
|
||||||
onClick={props.onClose}
|
onClick={props.onClose}
|
||||||
icon={<CloseIcon/>}
|
icon={<CloseIcon/>}
|
||||||
title={closeDialogText}
|
title={closeDialogText}
|
||||||
|
|
|
@ -8,18 +8,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
.dialog {
|
|
||||||
.toolbar {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute;
|
|
||||||
right: 18px;
|
|
||||||
top: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
.dialog {
|
.dialog {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -58,7 +46,7 @@
|
||||||
padding: 0 32px;
|
padding: 0 32px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&.freesize {
|
&.freesize {
|
||||||
height: unset;
|
height: unset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,33 +107,6 @@ exports[`components/sidebarBoardItem sidebar board item 1`] = `
|
||||||
<div
|
<div
|
||||||
class="menu-options"
|
class="menu-options"
|
||||||
>
|
>
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
aria-label="Delete board"
|
|
||||||
class="MenuOption TextOption menu-option"
|
|
||||||
role="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="d-flex"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="CompassIcon icon-trash-can-outline DeleteIcon trash-can-outline"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="menu-option__content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-name"
|
|
||||||
>
|
|
||||||
Delete board
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="noicon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="MenuOption SubMenuOption menu-option boardMoveToCategorySubmenu"
|
class="MenuOption SubMenuOption menu-option boardMoveToCategorySubmenu"
|
||||||
|
@ -239,6 +212,33 @@ exports[`components/sidebarBoardItem sidebar board item 1`] = `
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
aria-label="Delete board"
|
||||||
|
class="MenuOption TextOption menu-option text-danger"
|
||||||
|
role="button"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="d-flex"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="CompassIcon icon-trash-can-outline DeleteIcon trash-can-outline"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="menu-option__content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="menu-name"
|
||||||
|
>
|
||||||
|
Delete board
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="noicon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="menu-spacer hideOnWidescreen"
|
class="menu-spacer hideOnWidescreen"
|
||||||
|
@ -349,33 +349,6 @@ exports[`components/sidebarBoardItem sidebar board item for guest 1`] = `
|
||||||
<div
|
<div
|
||||||
class="menu-options"
|
class="menu-options"
|
||||||
>
|
>
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
aria-label="Delete board"
|
|
||||||
class="MenuOption TextOption menu-option"
|
|
||||||
role="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="d-flex"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="CompassIcon icon-trash-can-outline DeleteIcon trash-can-outline"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="menu-option__content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-name"
|
|
||||||
>
|
|
||||||
Delete board
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="noicon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="MenuOption SubMenuOption menu-option boardMoveToCategorySubmenu"
|
class="MenuOption SubMenuOption menu-option boardMoveToCategorySubmenu"
|
||||||
|
@ -429,6 +402,33 @@ exports[`components/sidebarBoardItem sidebar board item for guest 1`] = `
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
aria-label="Delete board"
|
||||||
|
class="MenuOption TextOption menu-option text-danger"
|
||||||
|
role="button"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="d-flex"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="CompassIcon icon-trash-can-outline DeleteIcon trash-can-outline"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="menu-option__content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="menu-name"
|
||||||
|
>
|
||||||
|
Delete board
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="noicon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="menu-spacer hideOnWidescreen"
|
class="menu-spacer hideOnWidescreen"
|
||||||
|
|
|
@ -69,11 +69,12 @@ describe('components/sidebarSidebar', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const history = createMemoryHistory()
|
const history = createMemoryHistory()
|
||||||
|
const onBoardTemplateSelectorOpen = jest.fn()
|
||||||
|
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<ReduxProvider store={store}>
|
<ReduxProvider store={store}>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Sidebar/>
|
<Sidebar onBoardTemplateSelectorOpen={onBoardTemplateSelectorOpen}/>
|
||||||
</Router>
|
</Router>
|
||||||
</ReduxProvider>,
|
</ReduxProvider>,
|
||||||
)
|
)
|
||||||
|
@ -131,11 +132,12 @@ describe('components/sidebarSidebar', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const history = createMemoryHistory()
|
const history = createMemoryHistory()
|
||||||
|
const onBoardTemplateSelectorOpen = jest.fn()
|
||||||
|
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<ReduxProvider store={store}>
|
<ReduxProvider store={store}>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Sidebar/>
|
<Sidebar onBoardTemplateSelectorOpen={onBoardTemplateSelectorOpen}/>
|
||||||
</Router>
|
</Router>
|
||||||
</ReduxProvider>,
|
</ReduxProvider>,
|
||||||
)
|
)
|
||||||
|
@ -192,11 +194,12 @@ describe('components/sidebarSidebar', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const history = createMemoryHistory()
|
const history = createMemoryHistory()
|
||||||
|
const onBoardTemplateSelectorOpen = jest.fn()
|
||||||
|
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<ReduxProvider store={store}>
|
<ReduxProvider store={store}>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Sidebar/>
|
<Sidebar onBoardTemplateSelectorOpen={onBoardTemplateSelectorOpen}/>
|
||||||
</Router>
|
</Router>
|
||||||
</ReduxProvider>,
|
</ReduxProvider>,
|
||||||
)
|
)
|
||||||
|
@ -254,11 +257,12 @@ describe('components/sidebarSidebar', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const history = createMemoryHistory()
|
const history = createMemoryHistory()
|
||||||
|
const onBoardTemplateSelectorOpen = jest.fn()
|
||||||
|
|
||||||
const component = wrapIntl(
|
const component = wrapIntl(
|
||||||
<ReduxProvider store={store}>
|
<ReduxProvider store={store}>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Sidebar/>
|
<Sidebar onBoardTemplateSelectorOpen={onBoardTemplateSelectorOpen}/>
|
||||||
</Router>
|
</Router>
|
||||||
</ReduxProvider>,
|
</ReduxProvider>,
|
||||||
)
|
)
|
||||||
|
@ -305,7 +309,7 @@ describe('components/sidebarSidebar', () => {
|
||||||
// const component = wrapIntl(
|
// const component = wrapIntl(
|
||||||
// <ReduxProvider store={store}>
|
// <ReduxProvider store={store}>
|
||||||
// <Router history={history}>
|
// <Router history={history}>
|
||||||
// <Sidebar/>
|
// <Sidebar onBoardTemplateSelectorOpen={onBoardTemplateSelectorOpen}/>
|
||||||
// </Router>
|
// </Router>
|
||||||
// </ReduxProvider>,
|
// </ReduxProvider>,
|
||||||
// )
|
// )
|
||||||
|
|
|
@ -40,7 +40,7 @@ import {addMissingItems} from './utils'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
activeBoardId?: string
|
activeBoardId?: string
|
||||||
onBoardTemplateSelectorOpen?: () => void
|
onBoardTemplateSelectorOpen: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWindowDimensions() {
|
function getWindowDimensions() {
|
||||||
|
|
|
@ -235,20 +235,6 @@ const SidebarBoardItem = (props: Props) => {
|
||||||
position='auto'
|
position='auto'
|
||||||
parentRef={boardItemRef}
|
parentRef={boardItemRef}
|
||||||
>
|
>
|
||||||
<BoardPermissionGate
|
|
||||||
boardId={board.id}
|
|
||||||
permissions={[Permission.DeleteBoard]}
|
|
||||||
>
|
|
||||||
<Menu.Text
|
|
||||||
key={`deleteBlock-${board.id}`}
|
|
||||||
id='deleteBlock'
|
|
||||||
name={intl.formatMessage({id: 'Sidebar.delete-board', defaultMessage: 'Delete board'})}
|
|
||||||
icon={<DeleteIcon/>}
|
|
||||||
onClick={() => {
|
|
||||||
props.onDeleteRequest(board)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</BoardPermissionGate>
|
|
||||||
<Menu.SubMenu
|
<Menu.SubMenu
|
||||||
key={`moveBlock-${board.id}`}
|
key={`moveBlock-${board.id}`}
|
||||||
id='moveBlock'
|
id='moveBlock'
|
||||||
|
@ -279,6 +265,21 @@ const SidebarBoardItem = (props: Props) => {
|
||||||
icon={<CloseIcon/>}
|
icon={<CloseIcon/>}
|
||||||
onClick={() => handleHideBoard()}
|
onClick={() => handleHideBoard()}
|
||||||
/>
|
/>
|
||||||
|
<BoardPermissionGate
|
||||||
|
boardId={board.id}
|
||||||
|
permissions={[Permission.DeleteBoard]}
|
||||||
|
>
|
||||||
|
<Menu.Text
|
||||||
|
key={`deleteBlock-${board.id}`}
|
||||||
|
id='deleteBlock'
|
||||||
|
className='text-danger'
|
||||||
|
name={intl.formatMessage({id: 'Sidebar.delete-board', defaultMessage: 'Delete board'})}
|
||||||
|
icon={<DeleteIcon/>}
|
||||||
|
onClick={() => {
|
||||||
|
props.onDeleteRequest(board)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</BoardPermissionGate>
|
||||||
</Menu>
|
</Menu>
|
||||||
</MenuWrapper>
|
</MenuWrapper>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {Board} from '../../blocks/board'
|
||||||
import mutator from '../../mutator'
|
import mutator from '../../mutator'
|
||||||
import IconButton from '../../widgets/buttons/iconButton'
|
import IconButton from '../../widgets/buttons/iconButton'
|
||||||
import DeleteIcon from '../../widgets/icons/delete'
|
import DeleteIcon from '../../widgets/icons/delete'
|
||||||
|
import CompassIcon from '../../widgets/icons/compassIcon'
|
||||||
import OptionsIcon from '../../widgets/icons/options'
|
import OptionsIcon from '../../widgets/icons/options'
|
||||||
import Menu from '../../widgets/menu'
|
import Menu from '../../widgets/menu'
|
||||||
import MenuWrapper from '../../widgets/menuWrapper'
|
import MenuWrapper from '../../widgets/menuWrapper'
|
||||||
|
@ -30,7 +31,6 @@ import {
|
||||||
|
|
||||||
import {getCurrentCard} from '../../store/cards'
|
import {getCurrentCard} from '../../store/cards'
|
||||||
import {Utils} from '../../utils'
|
import {Utils} from '../../utils'
|
||||||
import Update from '../../widgets/icons/update'
|
|
||||||
|
|
||||||
import { TOUR_SIDEBAR, SidebarTourSteps, TOUR_BOARD, FINISHED } from '../../components/onboardingTour/index'
|
import { TOUR_SIDEBAR, SidebarTourSteps, TOUR_BOARD, FINISHED } from '../../components/onboardingTour/index'
|
||||||
import telemetryClient, {TelemetryActions, TelemetryCategory} from '../../telemetry/telemetryClient'
|
import telemetryClient, {TelemetryActions, TelemetryCategory} from '../../telemetry/telemetryClient'
|
||||||
|
@ -244,6 +244,12 @@ const SidebarCategory = (props: Props) => {
|
||||||
{
|
{
|
||||||
props.categoryBoards.id !== '' &&
|
props.categoryBoards.id !== '' &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
<Menu.Text
|
||||||
|
id='updateCategory'
|
||||||
|
name={intl.formatMessage({id: 'SidebarCategories.CategoryMenu.Update', defaultMessage: 'Rename Category'})}
|
||||||
|
icon={<CompassIcon icon='pencil-outline'/>}
|
||||||
|
onClick={handleUpdateCategory}
|
||||||
|
/>
|
||||||
<Menu.Text
|
<Menu.Text
|
||||||
id='deleteCategory'
|
id='deleteCategory'
|
||||||
className='text-danger'
|
className='text-danger'
|
||||||
|
@ -251,11 +257,12 @@ const SidebarCategory = (props: Props) => {
|
||||||
icon={<DeleteIcon/>}
|
icon={<DeleteIcon/>}
|
||||||
onClick={() => setShowDeleteCategoryDialog(true)}
|
onClick={() => setShowDeleteCategoryDialog(true)}
|
||||||
/>
|
/>
|
||||||
|
<Menu.Separator/>
|
||||||
<Menu.Text
|
<Menu.Text
|
||||||
id='updateCategory'
|
id='createNewCategory'
|
||||||
name={intl.formatMessage({id: 'SidebarCategories.CategoryMenu.Update', defaultMessage: 'Rename Category'})}
|
name={intl.formatMessage({id: 'SidebarCategories.CategoryMenu.CreateNew', defaultMessage: 'Create New Category'})}
|
||||||
icon={<Update/>}
|
icon={<CreateNewFolder/>}
|
||||||
onClick={handleUpdateCategory}
|
onClick={handleCreateNewCategory}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
|
@ -315,21 +322,6 @@ const SidebarCategory = (props: Props) => {
|
||||||
defaultMessage='Create New Category'
|
defaultMessage='Create New Category'
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
onCreate={async (name) => {
|
|
||||||
if (!me) {
|
|
||||||
Utils.logError('me not initialized')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const category: Category = {
|
|
||||||
name,
|
|
||||||
userID: me.id,
|
|
||||||
teamID,
|
|
||||||
} as Category
|
|
||||||
|
|
||||||
await mutator.createCategory(category)
|
|
||||||
setShowCreateCategoryModal(false)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -345,22 +337,6 @@ const SidebarCategory = (props: Props) => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
onClose={() => setShowUpdateCategoryModal(false)}
|
onClose={() => setShowUpdateCategoryModal(false)}
|
||||||
onCreate={async (name) => {
|
|
||||||
if (!me) {
|
|
||||||
Utils.logError('me not initialized')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const category: Category = {
|
|
||||||
name,
|
|
||||||
id: props.categoryBoards.id,
|
|
||||||
userID: me.id,
|
|
||||||
teamID,
|
|
||||||
} as Category
|
|
||||||
|
|
||||||
await mutator.updateCategory(category)
|
|
||||||
setShowUpdateCategoryModal(false)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ exports[`components/viewLimitDialog/ViewLiimitDialog show notify upgrade button
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -96,7 +96,7 @@ exports[`components/viewLimitDialog/ViewLiimitDialog show upgrade button for sys
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
|
@ -20,7 +20,7 @@ exports[`components/viewLimitDialog/ViewL]imitDialog show notify admin confirmat
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -130,7 +130,7 @@ exports[`components/viewLimitDialog/ViewL]imitDialog show view limit dialog 1`]
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
class="IconButton size--medium"
|
class="IconButton dialog__close size--medium"
|
||||||
title="Close dialog"
|
title="Close dialog"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
|
|
Loading…
Reference in a new issue