mirror of
https://github.com/mattermost/focalboard.git
synced 2024-11-24 08:22:29 +02:00
Added tests
This commit is contained in:
parent
e2ce4b76c8
commit
e5bc177345
@ -19,6 +19,7 @@ import {Permission} from '../../../../webapp/src/constants'
|
||||
|
||||
import './rhsChannelBoardItem.scss'
|
||||
import BoardPermissionGate from '../../../../webapp/src/components/permissions/boardPermissionGate'
|
||||
import {MenuText} from '../../../../webapp/src/widgets/menu/menu'
|
||||
|
||||
const windowAny = (window as SuiteWindow)
|
||||
|
||||
@ -66,7 +67,7 @@ const RHSChannelBoardItem = (props: Props) => {
|
||||
teamId={team.id}
|
||||
permissions={[Permission.ManageBoardRoles]}
|
||||
>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={`unlinkBoard-${board.id}`}
|
||||
id='unlinkBoard'
|
||||
name={intl.formatMessage({id: 'rhs-boards.unlink-board', defaultMessage: 'Unlink board'})}
|
||||
@ -82,7 +83,7 @@ const RHSChannelBoardItem = (props: Props) => {
|
||||
permissions={[Permission.ManageBoardRoles]}
|
||||
invert={true}
|
||||
>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={`unlinkBoard-${board.id}`}
|
||||
id='unlinkBoard'
|
||||
disabled={true}
|
||||
|
@ -4,12 +4,13 @@
|
||||
import React from 'react'
|
||||
import {useIntl} from 'react-intl'
|
||||
|
||||
import {MenuText} from '../widgets/menu/menu'
|
||||
|
||||
import {BlockTypes, Block} from '../blocks/block'
|
||||
import {Card} from '../blocks/card'
|
||||
import mutator from '../mutator'
|
||||
import octoClient from '../octoClient'
|
||||
import {Utils} from '../utils'
|
||||
import Menu from '../widgets/menu'
|
||||
|
||||
import {contentRegistry} from './content/contentRegistry'
|
||||
|
||||
@ -31,7 +32,7 @@ const AddContentMenuItem = (props: Props): JSX.Element => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={type}
|
||||
id={type}
|
||||
name={handler.getDisplayText(intl)}
|
||||
|
@ -26,6 +26,7 @@ import {TOUR_SIDEBAR, SidebarTourSteps} from '../../components/onboardingTour'
|
||||
|
||||
import IconButton from '../../widgets/buttons/iconButton'
|
||||
import SearchForBoardsTourStep from '../../components/onboardingTour/searchForBoards/searchForBoards'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
onBoardTemplateSelectorOpen: () => void
|
||||
@ -109,13 +110,13 @@ const BoardsSwitcher = (props: Props): JSX.Element => {
|
||||
icon={<AddIcon/>}
|
||||
/>
|
||||
<Menu>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='create-new-board-option'
|
||||
icon={<CompassIcon icon='plus'/>}
|
||||
onClick={props.onBoardTemplateSelectorOpen}
|
||||
name='Create new board'
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='createNewCategory'
|
||||
name={intl.formatMessage({id: 'SidebarCategories.CategoryMenu.CreateNew', defaultMessage: 'Create New Category'})}
|
||||
icon={
|
||||
|
@ -16,6 +16,7 @@ import {IUser} from '../../user'
|
||||
import {getMe} from '../../store/users'
|
||||
import {useAppSelector} from '../../store/hooks'
|
||||
import TelemetryClient, {TelemetryActions, TelemetryCategory} from '../../telemetry/telemetryClient'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
cardId: string
|
||||
@ -46,14 +47,14 @@ export const CardActionsMenu = (props: Props): JSX.Element => {
|
||||
return (
|
||||
<Menu position='left'>
|
||||
<BoardPermissionGate permissions={[Permission.ManageBoardCards]}>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<DeleteIcon/>}
|
||||
id='delete'
|
||||
name={intl.formatMessage({id: 'CardActionsMenu.delete', defaultMessage: 'Delete'})}
|
||||
onClick={handleDeleteCard}
|
||||
/>
|
||||
{props.onClickDuplicate &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<DuplicateIcon/>}
|
||||
id='duplicate'
|
||||
name={intl.formatMessage({id: 'CardActionsMenu.duplicate', defaultMessage: 'Duplicate'})}
|
||||
@ -61,7 +62,7 @@ export const CardActionsMenu = (props: Props): JSX.Element => {
|
||||
/>}
|
||||
</BoardPermissionGate>
|
||||
{me?.id !== 'single-user' &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<LinkIcon/>}
|
||||
id='copy'
|
||||
name={intl.formatMessage({id: 'CardActionsMenu.copyLink', defaultMessage: 'Copy link'})}
|
||||
|
@ -7,6 +7,7 @@ import {BlockTypes} from '../../blocks/block'
|
||||
import {Utils} from '../../utils'
|
||||
import Button from '../../widgets/buttons/button'
|
||||
import Menu from '../../widgets/menu'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
import MenuWrapper from '../../widgets/menuWrapper'
|
||||
|
||||
import {contentRegistry} from '../content/contentRegistry'
|
||||
@ -27,7 +28,7 @@ function addContentMenu(intl: IntlShape, type: BlockTypes): JSX.Element {
|
||||
}, [cardDetail, handler])
|
||||
|
||||
return (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={type}
|
||||
id={type}
|
||||
name={handler.getDisplayText(intl)}
|
||||
|
@ -17,6 +17,7 @@ import Tooltip from '../../widgets/tooltip'
|
||||
import GuestBadge from '../../widgets/guestBadge'
|
||||
|
||||
import './comment.scss'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
comment: Block
|
||||
@ -55,7 +56,7 @@ const Comment: FC<Props> = (props: Props) => {
|
||||
<MenuWrapper>
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<DeleteIcon/>}
|
||||
id='delete'
|
||||
name={intl.formatMessage({id: 'Comment.delete', defaultMessage: 'Delete'})}
|
||||
|
@ -16,7 +16,6 @@ import {getCardAttachments, updateAttachments, updateUploadPrecent} from '../sto
|
||||
import TelemetryClient, {TelemetryActions, TelemetryCategory} from '../telemetry/telemetryClient'
|
||||
import {Utils} from '../utils'
|
||||
import CompassIcon from '../widgets/icons/compassIcon'
|
||||
import Menu from '../widgets/menu'
|
||||
import {sendFlashMessage} from '../components/flashMessages'
|
||||
|
||||
import ConfirmationDialogBox, {ConfirmationDialogBoxProps} from '../components/confirmationDialogBox'
|
||||
@ -32,6 +31,8 @@ import {Permission} from '../constants'
|
||||
import {Block, createBlock} from '../blocks/block'
|
||||
import {AttachmentBlock, createAttachmentBlock} from '../blocks/attachmentBlock'
|
||||
|
||||
import {MenuText} from '../widgets/menu/menu'
|
||||
|
||||
import BoardPermissionGate from './permissions/boardPermissionGate'
|
||||
|
||||
import CardDetail from './cardDetail/cardDetail'
|
||||
@ -125,7 +126,7 @@ const CardDialog = (props: Props): JSX.Element => {
|
||||
>
|
||||
{!isTemplate &&
|
||||
<BoardPermissionGate permissions={[Permission.ManageBoardProperties]}>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='makeTemplate'
|
||||
icon={
|
||||
<CompassIcon
|
||||
|
@ -17,14 +17,15 @@ import {getUploadPercent} from '../../store/attachments'
|
||||
import {useAppSelector} from '../../store/hooks'
|
||||
import {Permission} from '../../constants'
|
||||
|
||||
import ArchivedFile from './archivedFile/archivedFile'
|
||||
|
||||
import './attachmentElement.scss'
|
||||
import CompassIcon from './../../widgets/icons/compassIcon'
|
||||
import MenuWrapper from './../../widgets/menuWrapper'
|
||||
import IconButton from './../../widgets/buttons/iconButton'
|
||||
import Menu from './../../widgets/menu'
|
||||
import Tooltip from './../../widgets/tooltip'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
import CompassIcon from '../../widgets/icons/compassIcon'
|
||||
import MenuWrapper from '../../widgets/menuWrapper'
|
||||
import IconButton from '../../widgets/buttons/iconButton'
|
||||
import Menu from '../../widgets/menu'
|
||||
import Tooltip from '../../widgets/tooltip'
|
||||
|
||||
import ArchivedFile from './archivedFile/archivedFile'
|
||||
|
||||
type Props = {
|
||||
block: AttachmentBlock
|
||||
@ -171,7 +172,7 @@ const AttachmentElement = (props: Props): JSX.Element|null => {
|
||||
/>
|
||||
<div className='delete-menu'>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='makeTemplate'
|
||||
icon={
|
||||
<CompassIcon
|
||||
|
@ -19,6 +19,7 @@ import Menu from '../widgets/menu'
|
||||
import MenuWrapper from '../widgets/menuWrapper'
|
||||
import {useSortableWithGrip} from '../hooks/sortable'
|
||||
import {Position} from '../components/cardDetail/cardDetailContents'
|
||||
import {MenuSubMenu, MenuText} from '../widgets/menu/menu'
|
||||
|
||||
import ContentElement from './content/contentElement'
|
||||
import AddContentMenuItem from './addContentMenuItem'
|
||||
@ -76,7 +77,7 @@ const ContentBlock = (props: Props): JSX.Element => {
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu>
|
||||
{index > 0 &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='moveUp'
|
||||
name={intl.formatMessage({id: 'ContentBlock.moveUp', defaultMessage: 'Move up'})}
|
||||
icon={<SortUpIcon/>}
|
||||
@ -86,7 +87,7 @@ const ContentBlock = (props: Props): JSX.Element => {
|
||||
}}
|
||||
/>}
|
||||
{index < (contentOrder.length - 1) &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='moveDown'
|
||||
name={intl.formatMessage({id: 'ContentBlock.moveDown', defaultMessage: 'Move down'})}
|
||||
icon={<SortDownIcon/>}
|
||||
@ -95,7 +96,7 @@ const ContentBlock = (props: Props): JSX.Element => {
|
||||
mutator.changeCardContentOrder(props.card.boardId, card.id, card.fields.contentOrder, contentOrder)
|
||||
}}
|
||||
/>}
|
||||
<Menu.SubMenu
|
||||
<MenuSubMenu
|
||||
id='insertAbove'
|
||||
name={intl.formatMessage({id: 'ContentBlock.insertAbove', defaultMessage: 'Insert above'})}
|
||||
icon={<AddIcon/>}
|
||||
@ -109,8 +110,8 @@ const ContentBlock = (props: Props): JSX.Element => {
|
||||
cords={cords}
|
||||
/>
|
||||
))}
|
||||
</Menu.SubMenu>
|
||||
<Menu.Text
|
||||
</MenuSubMenu>
|
||||
<MenuText
|
||||
icon={<DeleteIcon/>}
|
||||
id='delete'
|
||||
name={intl.formatMessage({id: 'ContentBlock.Delete', defaultMessage: 'Delete'})}
|
||||
|
@ -14,6 +14,8 @@ import Menu from '../widgets/menu'
|
||||
|
||||
import OptionsIcon from '../widgets/icons/options'
|
||||
|
||||
import {MenuText} from '../widgets/menu/menu'
|
||||
|
||||
import Dialog from './dialog'
|
||||
|
||||
describe('components/dialog', () => {
|
||||
@ -48,7 +50,7 @@ describe('components/dialog', () => {
|
||||
onClose={onCloseMethod}
|
||||
>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='test'
|
||||
icon={<OptionsIcon/>}
|
||||
name='Test'
|
||||
@ -70,7 +72,7 @@ describe('components/dialog', () => {
|
||||
<Dialog
|
||||
onClose={jest.fn()}
|
||||
toolsMenu={<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='test'
|
||||
icon={<OptionsIcon/>}
|
||||
name='Test'
|
||||
@ -94,7 +96,7 @@ describe('components/dialog', () => {
|
||||
<Dialog
|
||||
onClose={jest.fn()}
|
||||
toolsMenu={<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='test'
|
||||
icon={<OptionsIcon/>}
|
||||
name='Test'
|
||||
|
@ -21,6 +21,7 @@ import {Constants} from '../../constants'
|
||||
import TelemetryClient, {TelemetryCategory, TelemetryActions} from '../../telemetry/telemetryClient'
|
||||
|
||||
import './globalHeaderSettingsMenu.scss'
|
||||
import {MenuSubMenu, MenuText, MenuSwitch} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
history: History<unknown>
|
||||
@ -45,12 +46,12 @@ const GlobalHeaderSettingsMenu = (props: Props) => {
|
||||
<SettingsIcon/>
|
||||
</div>
|
||||
<Menu position='left'>
|
||||
<Menu.SubMenu
|
||||
<MenuSubMenu
|
||||
id='import'
|
||||
name={intl.formatMessage({id: 'Sidebar.import', defaultMessage: 'Import'})}
|
||||
position='left-bottom'
|
||||
>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='import_archive'
|
||||
name={intl.formatMessage({id: 'Sidebar.import-archive', defaultMessage: 'Import archive'})}
|
||||
onClick={async () => {
|
||||
@ -60,7 +61,7 @@ const GlobalHeaderSettingsMenu = (props: Props) => {
|
||||
/>
|
||||
{
|
||||
Constants.imports.map((i) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={`${i.id}-import`}
|
||||
id={`${i.id}-import`}
|
||||
name={i.displayName}
|
||||
@ -71,15 +72,15 @@ const GlobalHeaderSettingsMenu = (props: Props) => {
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
</MenuSubMenu>
|
||||
<MenuSubMenu
|
||||
id='lang'
|
||||
name={intl.formatMessage({id: 'Sidebar.set-language', defaultMessage: 'Set language'})}
|
||||
position='left-bottom'
|
||||
>
|
||||
{
|
||||
Constants.languages.map((language) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={language.code}
|
||||
id={`${language.name}-lang`}
|
||||
name={language.displayName}
|
||||
@ -88,8 +89,8 @@ const GlobalHeaderSettingsMenu = (props: Props) => {
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Menu.SubMenu>
|
||||
<Menu.Switch
|
||||
</MenuSubMenu>
|
||||
<MenuSwitch
|
||||
id='random-icons'
|
||||
name={intl.formatMessage({id: 'Sidebar.random-icons', defaultMessage: 'Random icons'})}
|
||||
isOn={randomIcons}
|
||||
@ -97,7 +98,7 @@ const GlobalHeaderSettingsMenu = (props: Props) => {
|
||||
suppressItemClicked={true}
|
||||
/>
|
||||
{me?.is_guest !== true &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='product-tour'
|
||||
className='product-tour'
|
||||
name={intl.formatMessage({id: 'Sidebar.product-tour', defaultMessage: 'Product tour'})}
|
||||
|
@ -10,6 +10,7 @@ import EmojiIcon from '../widgets/icons/emoji'
|
||||
import Menu from '../widgets/menu'
|
||||
import MenuWrapper from '../widgets/menuWrapper'
|
||||
import './iconSelector.scss'
|
||||
import {MenuText, MenuSubMenu} from '../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
readonly?: boolean
|
||||
@ -29,20 +30,20 @@ const IconSelector = React.memo((props: Props) => {
|
||||
<MenuWrapper>
|
||||
{props.iconElement}
|
||||
<Menu>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='random'
|
||||
icon={<RandomIcon/>}
|
||||
name={intl.formatMessage({id: 'ViewTitle.random-icon', defaultMessage: 'Random'})}
|
||||
onClick={props.onAddRandomIcon}
|
||||
/>
|
||||
<Menu.SubMenu
|
||||
<MenuSubMenu
|
||||
id='pick'
|
||||
icon={<EmojiIcon/>}
|
||||
name={intl.formatMessage({id: 'ViewTitle.pick-icon', defaultMessage: 'Pick icon'})}
|
||||
>
|
||||
<EmojiPicker onSelect={props.onSelectEmoji}/>
|
||||
</Menu.SubMenu>
|
||||
<Menu.Text
|
||||
</MenuSubMenu>
|
||||
<MenuText
|
||||
id='remove'
|
||||
icon={<DeleteIcon/>}
|
||||
name={intl.formatMessage({id: 'ViewTitle.remove-icon', defaultMessage: 'Remove icon'})}
|
||||
|
@ -23,6 +23,8 @@ import {useHasCurrentBoardPermissions} from '../../hooks/permissions'
|
||||
|
||||
import BoardPermissionGate from '../permissions/boardPermissionGate'
|
||||
|
||||
import {MenuText, MenuSeparator, MenuColor} from '../../widgets/menu/menu'
|
||||
|
||||
import {KanbanCalculation} from './calculation/calculation'
|
||||
|
||||
type Props = {
|
||||
@ -164,7 +166,7 @@ export default function KanbanColumnHeader(props: Props): JSX.Element {
|
||||
<MenuWrapper>
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='hide'
|
||||
icon={<HideIcon/>}
|
||||
name={intl.formatMessage({id: 'BoardComponent.hide', defaultMessage: 'Hide'})}
|
||||
@ -172,15 +174,15 @@ export default function KanbanColumnHeader(props: Props): JSX.Element {
|
||||
/>
|
||||
{canEditOption &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='delete'
|
||||
icon={<DeleteIcon/>}
|
||||
name={intl.formatMessage({id: 'BoardComponent.delete', defaultMessage: 'Delete'})}
|
||||
onClick={() => mutator.deletePropertyOption(board.id, board.cardProperties, groupByProperty!, group.option)}
|
||||
/>
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
{Object.entries(Constants.menuColors).map(([key, color]) => (
|
||||
<Menu.Color
|
||||
<MenuColor
|
||||
key={key}
|
||||
id={key}
|
||||
name={color}
|
||||
|
@ -15,6 +15,7 @@ import {BoardGroup} from '../../blocks/board'
|
||||
import {BoardView} from '../../blocks/boardView'
|
||||
|
||||
import Button from '../../widgets/buttons/button'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
activeView: BoardView
|
||||
@ -59,7 +60,7 @@ export default function KanbanHiddenColumnItem(props: Props): JSX.Element {
|
||||
{group.option.value}
|
||||
</Label>
|
||||
<Menu>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='show'
|
||||
icon={<ShowIcon/>}
|
||||
name={intl.formatMessage({id: 'BoardComponent.show', defaultMessage: 'Show'})}
|
||||
|
@ -24,6 +24,7 @@ import CompassIcon from '../../widgets/icons/compassIcon'
|
||||
import ConfirmationDialogBox from '../confirmationDialogBox'
|
||||
|
||||
import BoardPermissionGate from '../permissions/boardPermissionGate'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
teammateNameDisplay?: string
|
||||
@ -129,7 +130,7 @@ const ChannelPermissionsRow = (props: Props): JSX.Element => {
|
||||
/>
|
||||
</button>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='Unlink'
|
||||
icon={<DeleteIcon/>}
|
||||
name={intl.formatMessage({id: 'BoardMember.unlinkChannel', defaultMessage: 'Unlink'})}
|
||||
|
@ -21,6 +21,7 @@ import BoardPermissionGate from '../permissions/boardPermissionGate'
|
||||
import ConfirmationDialogBox from '../confirmationDialogBox'
|
||||
|
||||
import mutator from '../../mutator'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
async function updateBoardType(board: Board, newType: string, newMinimumRole: MemberRole) {
|
||||
if (board.type === newType && board.minimumRole === newMinimumRole) {
|
||||
@ -110,7 +111,7 @@ const TeamPermissionsRow = (): JSX.Element => {
|
||||
</button>
|
||||
<Menu position='left'>
|
||||
{!board.isTemplate &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id={MemberRole.Editor}
|
||||
check={board.minimumRole === undefined || board.minimumRole === MemberRole.Editor}
|
||||
icon={board.type === BoardTypeOpen && board.minimumRole === MemberRole.Editor ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
@ -118,21 +119,21 @@ const TeamPermissionsRow = (): JSX.Element => {
|
||||
onClick={() => setChangeRoleConfirmation(MemberRole.Editor)}
|
||||
/>}
|
||||
{!board.isTemplate &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id={MemberRole.Commenter}
|
||||
check={board.minimumRole === MemberRole.Commenter}
|
||||
icon={board.type === BoardTypeOpen && board.minimumRole === MemberRole.Commenter ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
name={intl.formatMessage({id: 'BoardMember.schemeCommenter', defaultMessage: 'Commenter'})}
|
||||
onClick={() => setChangeRoleConfirmation(MemberRole.Commenter)}
|
||||
/>}
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id={MemberRole.Viewer}
|
||||
check={board.minimumRole === MemberRole.Viewer}
|
||||
icon={board.type === BoardTypeOpen && board.minimumRole === MemberRole.Viewer ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
name={intl.formatMessage({id: 'BoardMember.schemeViewer', defaultMessage: 'Viewer'})}
|
||||
onClick={() => updateBoardType(board, BoardTypeOpen, MemberRole.Viewer)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id={MemberRole.None}
|
||||
check={true}
|
||||
icon={board.type === BoardTypePrivate ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
|
@ -19,6 +19,7 @@ import {useAppSelector} from '../../store/hooks'
|
||||
import {getCurrentBoard} from '../../store/boards'
|
||||
|
||||
import BoardPermissionGate from '../permissions/boardPermissionGate'
|
||||
import {MenuText, MenuSeparator} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
user: IUser
|
||||
@ -82,7 +83,7 @@ const UserPermissionsRow = (props: Props): JSX.Element => {
|
||||
parentRef={menuWrapperRef}
|
||||
>
|
||||
{(board.minimumRole === MemberRole.Viewer || board.minimumRole === MemberRole.None) &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id={MemberRole.Viewer}
|
||||
check={true}
|
||||
icon={currentRole === MemberRole.Viewer ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
@ -90,14 +91,14 @@ const UserPermissionsRow = (props: Props): JSX.Element => {
|
||||
onClick={() => props.onUpdateBoardMember(member, MemberRole.Viewer)}
|
||||
/>}
|
||||
{!board.isTemplate && (board.minimumRole === MemberRole.None || board.minimumRole === MemberRole.Commenter || board.minimumRole === MemberRole.Viewer) &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id={MemberRole.Commenter}
|
||||
check={true}
|
||||
icon={currentRole === MemberRole.Commenter ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
name={intl.formatMessage({id: 'BoardMember.schemeCommenter', defaultMessage: 'Commenter'})}
|
||||
onClick={() => props.onUpdateBoardMember(member, MemberRole.Commenter)}
|
||||
/>}
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id={MemberRole.Editor}
|
||||
check={true}
|
||||
icon={currentRole === MemberRole.Editor ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
@ -105,15 +106,15 @@ const UserPermissionsRow = (props: Props): JSX.Element => {
|
||||
onClick={() => props.onUpdateBoardMember(member, MemberRole.Editor)}
|
||||
/>
|
||||
{user.is_guest !== true &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id={MemberRole.Admin}
|
||||
check={true}
|
||||
icon={currentRole === MemberRole.Admin ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||
name={intl.formatMessage({id: 'BoardMember.schemeAdmin', defaultMessage: 'Admin'})}
|
||||
onClick={() => props.onUpdateBoardMember(member, MemberRole.Admin)}
|
||||
/>}
|
||||
<Menu.Separator/>
|
||||
<Menu.Text
|
||||
<MenuSeparator/>
|
||||
<MenuText
|
||||
id='Remove'
|
||||
name={intl.formatMessage({id: 'ShareBoard.userPermissionsRemoveMemberText', defaultMessage: 'Remove member'})}
|
||||
onClick={() => props.onDeleteBoardMember(member)}
|
||||
|
@ -40,6 +40,7 @@ import octoClient from '../../octoClient'
|
||||
import {getCurrentBoardId} from '../../store/boards'
|
||||
import {UserSettings} from '../../userSettings'
|
||||
import {Archiver} from '../../archiver'
|
||||
import {MenuText, MenuSubMenu} from '../../widgets/menu/menu'
|
||||
|
||||
const iconForViewType = (viewType: IViewType): JSX.Element => {
|
||||
switch (viewType) {
|
||||
@ -82,7 +83,7 @@ const SidebarBoardItem = (props: Props) => {
|
||||
|
||||
const generateMoveToCategoryOptions = (boardID: string) => {
|
||||
return props.allCategories.map((category) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={category.id}
|
||||
id={category.id}
|
||||
name={category.name}
|
||||
@ -237,7 +238,7 @@ const SidebarBoardItem = (props: Props) => {
|
||||
position='auto'
|
||||
parentRef={boardItemRef}
|
||||
>
|
||||
<Menu.SubMenu
|
||||
<MenuSubMenu
|
||||
key={`moveBlock-${board.id}`}
|
||||
id='moveBlock'
|
||||
className='boardMoveToCategorySubmenu'
|
||||
@ -246,28 +247,28 @@ const SidebarBoardItem = (props: Props) => {
|
||||
position='auto'
|
||||
>
|
||||
{generateMoveToCategoryOptions(board.id)}
|
||||
</Menu.SubMenu>
|
||||
</MenuSubMenu>
|
||||
{!me?.is_guest &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='duplicateBoard'
|
||||
name={intl.formatMessage({id: 'Sidebar.duplicate-board', defaultMessage: 'Duplicate board'})}
|
||||
icon={<DuplicateIcon/>}
|
||||
onClick={() => handleDuplicateBoard(board.isTemplate)}
|
||||
/>}
|
||||
{!me?.is_guest &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='templateFromBoard'
|
||||
name={intl.formatMessage({id: 'Sidebar.template-from-board', defaultMessage: 'New template from board'})}
|
||||
icon={<AddIcon/>}
|
||||
onClick={() => handleDuplicateBoard(true)}
|
||||
/>}
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='exportBoardArchive'
|
||||
name={intl.formatMessage({id: 'ViewHeader.export-board-archive', defaultMessage: 'Export board archive'})}
|
||||
icon={<CompassIcon icon='export-variant'/>}
|
||||
onClick={() => Archiver.exportBoardArchive(board)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='hideBoard'
|
||||
name={intl.formatMessage({id: 'HideBoard.MenuOption', defaultMessage: 'Hide board'})}
|
||||
icon={<CloseIcon/>}
|
||||
@ -277,7 +278,7 @@ const SidebarBoardItem = (props: Props) => {
|
||||
boardId={board.id}
|
||||
permissions={[Permission.DeleteBoard]}
|
||||
>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={`deleteBlock-${board.id}`}
|
||||
id='deleteBlock'
|
||||
className='text-danger'
|
||||
|
@ -44,6 +44,8 @@ import ConfirmationDialogBox, {ConfirmationDialogBoxProps} from '../confirmation
|
||||
import SidebarCategoriesTourStep from '../../components/onboardingTour/sidebarCategories/sidebarCategories'
|
||||
import ManageCategoriesTourStep from '../../components/onboardingTour/manageCategories/manageCategories'
|
||||
|
||||
import {MenuText, MenuSeparator} from '../../widgets/menu/menu'
|
||||
|
||||
import DeleteBoardDialog from './deleteBoardDialog'
|
||||
import SidebarBoardItem from './sidebarBoardItem'
|
||||
|
||||
@ -318,23 +320,23 @@ const SidebarCategory = (props: Props) => {
|
||||
{
|
||||
props.categoryBoards.type === 'custom' &&
|
||||
<React.Fragment>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='updateCategory'
|
||||
name={intl.formatMessage({id: 'SidebarCategories.CategoryMenu.Update', defaultMessage: 'Rename Category'})}
|
||||
icon={<CompassIcon icon='pencil-outline'/>}
|
||||
onClick={handleUpdateCategory}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='deleteCategory'
|
||||
className='text-danger'
|
||||
name={intl.formatMessage({id: 'SidebarCategories.CategoryMenu.Delete', defaultMessage: 'Delete Category'})}
|
||||
icon={<DeleteIcon/>}
|
||||
onClick={() => setShowDeleteCategoryDialog(true)}
|
||||
/>
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
</React.Fragment>
|
||||
}
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='createNewCategory'
|
||||
name={intl.formatMessage({id: 'SidebarCategories.CategoryMenu.CreateNew', defaultMessage: 'Create New Category'})}
|
||||
icon={<CreateNewFolder/>}
|
||||
|
@ -26,6 +26,7 @@ import CheckIcon from '../../widgets/icons/check'
|
||||
import {Constants} from '../../constants'
|
||||
|
||||
import TelemetryClient, {TelemetryCategory, TelemetryActions} from '../../telemetry/telemetryClient'
|
||||
import {MenuSubMenu, MenuText, MenuSwitch} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
activeTheme: string
|
||||
@ -85,12 +86,12 @@ const SidebarSettingsMenu = (props: Props) => {
|
||||
/>
|
||||
</div>
|
||||
<Menu position='top'>
|
||||
<Menu.SubMenu
|
||||
<MenuSubMenu
|
||||
id='import'
|
||||
name={intl.formatMessage({id: 'Sidebar.import', defaultMessage: 'Import'})}
|
||||
position='top'
|
||||
>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='import_archive'
|
||||
name={intl.formatMessage({id: 'Sidebar.import-archive', defaultMessage: 'Import archive'})}
|
||||
onClick={async () => {
|
||||
@ -100,7 +101,7 @@ const SidebarSettingsMenu = (props: Props) => {
|
||||
/>
|
||||
{
|
||||
Constants.imports.map((i) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={`${i.id}-import`}
|
||||
id={`${i.id}-import`}
|
||||
name={i.displayName}
|
||||
@ -111,8 +112,8 @@ const SidebarSettingsMenu = (props: Props) => {
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Menu.SubMenu>
|
||||
<Menu.Text
|
||||
</MenuSubMenu>
|
||||
<MenuText
|
||||
id='export'
|
||||
name={intl.formatMessage({id: 'Sidebar.export-archive', defaultMessage: 'Export archive'})}
|
||||
onClick={async () => {
|
||||
@ -122,14 +123,14 @@ const SidebarSettingsMenu = (props: Props) => {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Menu.SubMenu
|
||||
<MenuSubMenu
|
||||
id='lang'
|
||||
name={intl.formatMessage({id: 'Sidebar.set-language', defaultMessage: 'Set language'})}
|
||||
position='top'
|
||||
>
|
||||
{
|
||||
Constants.languages.map((language) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={language.code}
|
||||
id={`${language.name}-lang`}
|
||||
name={language.displayName}
|
||||
@ -138,8 +139,8 @@ const SidebarSettingsMenu = (props: Props) => {
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Menu.SubMenu>
|
||||
<Menu.SubMenu
|
||||
</MenuSubMenu>
|
||||
<MenuSubMenu
|
||||
id='theme'
|
||||
name={intl.formatMessage({id: 'Sidebar.set-theme', defaultMessage: 'Set theme'})}
|
||||
position='top'
|
||||
@ -147,7 +148,7 @@ const SidebarSettingsMenu = (props: Props) => {
|
||||
{
|
||||
themes.map((theme) =>
|
||||
(
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={theme.id}
|
||||
id={theme.id}
|
||||
name={intl.formatMessage({id: `Sidebar.${theme.id}`, defaultMessage: theme.displayName})}
|
||||
@ -157,8 +158,8 @@ const SidebarSettingsMenu = (props: Props) => {
|
||||
),
|
||||
)
|
||||
}
|
||||
</Menu.SubMenu>
|
||||
<Menu.Switch
|
||||
</MenuSubMenu>
|
||||
<MenuSwitch
|
||||
id='random-icons'
|
||||
name={intl.formatMessage({id: 'Sidebar.random-icons', defaultMessage: 'Random icons'})}
|
||||
isOn={randomIcons}
|
||||
|
@ -19,6 +19,8 @@ import ModalWrapper from '../modalWrapper'
|
||||
|
||||
import {IAppWindow} from '../../types'
|
||||
|
||||
import {MenuLabel, MenuText, MenuSeparator} from '../../widgets/menu/menu'
|
||||
|
||||
import RegistrationLink from './registrationLink'
|
||||
|
||||
import './sidebarUserMenu.scss'
|
||||
@ -55,8 +57,8 @@ const SidebarUserMenu = () => {
|
||||
</div>
|
||||
<Menu>
|
||||
{user && user.username !== 'single-user' && <>
|
||||
<Menu.Label><b>{user.username}</b></Menu.Label>
|
||||
<Menu.Text
|
||||
<MenuLabel><b>{user.username}</b></MenuLabel>
|
||||
<MenuText
|
||||
id='logout'
|
||||
name={intl.formatMessage({id: 'Sidebar.logout', defaultMessage: 'Log out'})}
|
||||
onClick={async () => {
|
||||
@ -65,14 +67,14 @@ const SidebarUserMenu = () => {
|
||||
history.push('/login')
|
||||
}}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='changePassword'
|
||||
name={intl.formatMessage({id: 'Sidebar.changePassword', defaultMessage: 'Change password'})}
|
||||
onClick={async () => {
|
||||
history.push('/change_password')
|
||||
}}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='invite'
|
||||
name={intl.formatMessage({id: 'Sidebar.invite-users', defaultMessage: 'Invite users'})}
|
||||
onClick={async () => {
|
||||
@ -80,10 +82,10 @@ const SidebarUserMenu = () => {
|
||||
}}
|
||||
/>
|
||||
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
</>}
|
||||
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='about'
|
||||
name={intl.formatMessage({id: 'Sidebar.about', defaultMessage: 'About Focalboard'})}
|
||||
onClick={async () => {
|
||||
|
@ -82,4 +82,175 @@ describe('components/standardProperties/statusProperty/EditStatusPropertyDialog'
|
||||
const {container} = render(component)
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('no value in any column', () => {
|
||||
const noValueConfig: StatusCategory[] = [
|
||||
{
|
||||
id: 'category_id_1',
|
||||
title: 'Not Started',
|
||||
options: [],
|
||||
emptyState: {
|
||||
icon: (<BlackCheckboxOutline/>),
|
||||
color: '--sys-dnd-indicator-rgb',
|
||||
text: {
|
||||
id: 'statusProperty.configDialog.todo.emptyText',
|
||||
defaultMessage: 'Drag statuses here to consider tasks with these statuses “Not Started”',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'category_id_2',
|
||||
title: 'In progress',
|
||||
options: [],
|
||||
emptyState: {
|
||||
icon: (<ClockOutline/>),
|
||||
color: '--away-indicator-rgb',
|
||||
text: {
|
||||
id: 'statusProperty.configDialog.inProgress.emptyText',
|
||||
defaultMessage: 'Drag statuses here to consider tasks with these statuses “in progress”',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'category_id_3',
|
||||
title: 'Completed',
|
||||
options: [],
|
||||
emptyState: {
|
||||
icon: (<CheckIcon/>),
|
||||
color: '--online-indicator-rgb',
|
||||
text: {
|
||||
id: 'statusProperty.configDialog.complete.emptyText',
|
||||
defaultMessage: 'Drag statuses here to consider tasks with these statuses ”Done”',
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const component = wrapRBDNDContext(
|
||||
wrapIntl(
|
||||
<EditStatusPropertyDialog
|
||||
valueCategories={noValueConfig}
|
||||
onClose={() => {}}
|
||||
onUpdate={() => {}}
|
||||
/>,
|
||||
))
|
||||
|
||||
const {container} = render(component)
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('5 columns', () => {
|
||||
const initialValueCategoryValue: StatusCategory[] = [
|
||||
{
|
||||
id: 'category_id_1',
|
||||
title: 'Column 1',
|
||||
options: [
|
||||
{id: 'status_id_1', value: 'Pending Design', color: 'propColorPurple'},
|
||||
{id: 'status_id_2', value: 'TODO', color: 'propColorYellow'},
|
||||
{id: 'status_id_3', value: 'Pending Specs', color: 'propColorGray'},
|
||||
],
|
||||
emptyState: {
|
||||
icon: (<BlackCheckboxOutline/>),
|
||||
color: '--sys-dnd-indicator-rgb',
|
||||
text: {
|
||||
id: 'statusProperty.configDialog.todo.emptyText',
|
||||
defaultMessage: 'Drag statuses here to consider tasks with these statuses “Not Started”',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'category_id_2',
|
||||
title: 'Column 2',
|
||||
options: [
|
||||
{id: 'status_id_4', value: 'In Progress', color: 'propColorBrown'},
|
||||
{id: 'status_id_5', value: 'In Review', color: 'propColorRed'},
|
||||
{id: 'status_id_6', value: 'In QA', color: 'propColorPink'},
|
||||
{id: 'status_id_7', value: 'Awaiting Cherrypick', color: 'propColorOrange'},
|
||||
],
|
||||
emptyState: {
|
||||
icon: (<ClockOutline/>),
|
||||
color: '--away-indicator-rgb',
|
||||
text: {
|
||||
id: 'statusProperty.configDialog.inProgress.emptyText',
|
||||
defaultMessage: 'Drag statuses here to consider tasks with these statuses “in progress”',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'category_id_3',
|
||||
title: 'Column 3',
|
||||
options: [
|
||||
{id: 'status_id_20', value: 'Done', color: 'propColorPink'},
|
||||
{id: 'status_id_21', value: 'Branch Cut', color: 'propColorGreen'},
|
||||
{id: 'status_id_22', value: 'Released', color: 'propColorDefault'},
|
||||
],
|
||||
emptyState: {
|
||||
icon: (<CheckIcon/>),
|
||||
color: '--online-indicator-rgb',
|
||||
text: {
|
||||
id: 'statusProperty.configDialog.complete.emptyText',
|
||||
defaultMessage: 'Drag statuses here to consider tasks with these statuses ”Done”',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'category_id_2',
|
||||
title: 'Column 4',
|
||||
options: [
|
||||
{id: 'status_id_54', value: 'Michael Scott', color: 'propColorOrange'},
|
||||
],
|
||||
emptyState: {
|
||||
icon: (<ClockOutline/>),
|
||||
color: '--away-indicator-rgb',
|
||||
text: {
|
||||
id: 'statusProperty.configDialog.inProgress.emptyText',
|
||||
defaultMessage: 'Drag statuses here to consider tasks with these statuses “in progress”',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'category_id_3',
|
||||
title: 'Column 5',
|
||||
options: [
|
||||
{id: 'status_id_22', value: 'Jim Halpert', color: 'propColorDefault'},
|
||||
],
|
||||
emptyState: {
|
||||
icon: (<CheckIcon/>),
|
||||
color: '--online-indicator-rgb',
|
||||
text: {
|
||||
id: 'statusProperty.configDialog.complete.emptyText',
|
||||
defaultMessage: 'Drag statuses here to consider tasks with these statuses ”Done”',
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const component = wrapRBDNDContext(
|
||||
wrapIntl(
|
||||
<EditStatusPropertyDialog
|
||||
valueCategories={initialValueCategoryValue}
|
||||
onClose={() => {}}
|
||||
onUpdate={() => {}}
|
||||
/>,
|
||||
))
|
||||
|
||||
const {container} = render(component)
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('0 columns', () => {
|
||||
const initialValueCategoryValue: StatusCategory[] = []
|
||||
|
||||
const component = wrapRBDNDContext(
|
||||
wrapIntl(
|
||||
<EditStatusPropertyDialog
|
||||
valueCategories={initialValueCategoryValue}
|
||||
onClose={() => {}}
|
||||
onUpdate={() => {}}
|
||||
/>,
|
||||
))
|
||||
|
||||
const {container} = render(component)
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
@ -10,7 +10,7 @@ import {Constants} from '../../../constants'
|
||||
|
||||
import DragHandle from '../../../widgets/icons/dragHandle'
|
||||
import EditIcon from '../../../widgets/icons/edit'
|
||||
import Menu from '../../../widgets/menu/menu'
|
||||
import Menu, {MenuColor, MenuText} from '../../../widgets/menu/menu'
|
||||
import MenuWrapper from '../../../widgets/menuWrapper'
|
||||
|
||||
import {IPropertyOption} from '../../../blocks/board'
|
||||
@ -98,7 +98,7 @@ const ValueRow = (props: Props) => {
|
||||
{
|
||||
Object.entries(Constants.menuColors).map(
|
||||
([key, color]: [string, string]) => (
|
||||
<Menu.Color
|
||||
<MenuColor
|
||||
key={key}
|
||||
id={key}
|
||||
name={color}
|
||||
@ -125,13 +125,13 @@ const ValueRow = (props: Props) => {
|
||||
menuMargin={30}
|
||||
fixed={true}
|
||||
>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='editText'
|
||||
name={'Edit'}
|
||||
icon={<EditIcon/>}
|
||||
onClick={handleEditButtonClick}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='deleteOption'
|
||||
name={'Delete'}
|
||||
icon={<DeleteIcon/>}
|
||||
|
@ -21,6 +21,8 @@ import MenuWrapper from '../../widgets/menuWrapper'
|
||||
import Editable from '../../widgets/editable'
|
||||
import Label from '../../widgets/label'
|
||||
|
||||
import {MenuText, MenuSeparator, MenuColor} from '../../widgets/menu/menu'
|
||||
|
||||
import {useColumnResize} from './tableColumnResizeContext'
|
||||
|
||||
type Props = {
|
||||
@ -122,7 +124,7 @@ const TableGroupHeaderRow = (props: Props): JSX.Element => {
|
||||
<MenuWrapper>
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='hide'
|
||||
icon={<HideIcon/>}
|
||||
name={intl.formatMessage({id: 'BoardComponent.hide', defaultMessage: 'Hide'})}
|
||||
@ -130,15 +132,15 @@ const TableGroupHeaderRow = (props: Props): JSX.Element => {
|
||||
/>
|
||||
{canEditOption &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='delete'
|
||||
icon={<DeleteIcon/>}
|
||||
name={intl.formatMessage({id: 'BoardComponent.delete', defaultMessage: 'Delete'})}
|
||||
onClick={() => mutator.deletePropertyOption(board.id, board.cardProperties, groupByProperty!, group.option)}
|
||||
/>
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
{Object.entries(Constants.menuColors).map(([key, color]) => (
|
||||
<Menu.Color
|
||||
<MenuColor
|
||||
key={key}
|
||||
id={key}
|
||||
name={color}
|
||||
|
@ -10,6 +10,7 @@ import {BoardView} from '../../blocks/boardView'
|
||||
import {Card} from '../../blocks/card'
|
||||
import mutator from '../../mutator'
|
||||
import Menu from '../../widgets/menu'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
templateId: string
|
||||
@ -24,17 +25,17 @@ const TableHeaderMenu: FC<Props> = (props: Props): JSX.Element => {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='sortAscending'
|
||||
name={intl.formatMessage({id: 'TableHeaderMenu.sort-ascending', defaultMessage: 'Sort ascending'})}
|
||||
onClick={() => mutator.changeViewSortOptions(board.id, activeView.id, activeView.fields.sortOptions, [{propertyId: templateId, reversed: false}])}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='sortDescending'
|
||||
name={intl.formatMessage({id: 'TableHeaderMenu.sort-descending', defaultMessage: 'Sort descending'})}
|
||||
onClick={() => mutator.changeViewSortOptions(board.id, activeView.id, activeView.fields.sortOptions, [{propertyId: templateId, reversed: true}])}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='insertLeft'
|
||||
name={intl.formatMessage({id: 'TableHeaderMenu.insert-left', defaultMessage: 'Insert left'})}
|
||||
onClick={() => {
|
||||
@ -47,7 +48,7 @@ const TableHeaderMenu: FC<Props> = (props: Props): JSX.Element => {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='insertRight'
|
||||
name={intl.formatMessage({id: 'TableHeaderMenu.insert-right', defaultMessage: 'Insert right'})}
|
||||
onClick={() => {
|
||||
@ -62,17 +63,17 @@ const TableHeaderMenu: FC<Props> = (props: Props): JSX.Element => {
|
||||
/>
|
||||
{props.templateId !== Constants.titleColumnId &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='hide'
|
||||
name={intl.formatMessage({id: 'TableHeaderMenu.hide', defaultMessage: 'Hide'})}
|
||||
onClick={() => mutator.changeViewVisibleProperties(board.id, activeView.id, activeView.fields.visiblePropertyIds, activeView.fields.visiblePropertyIds.filter((o: string) => o !== templateId))}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='duplicate'
|
||||
name={intl.formatMessage({id: 'TableHeaderMenu.duplicate', defaultMessage: 'Duplicate'})}
|
||||
onClick={() => mutator.duplicatePropertyTemplate(board, activeView, templateId)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='delete'
|
||||
name={intl.formatMessage({id: 'TableHeaderMenu.delete', defaultMessage: 'Delete'})}
|
||||
onClick={() => mutator.deleteProperty(board, views, cards, templateId)}
|
||||
|
@ -16,6 +16,7 @@ import mutator from '../../mutator'
|
||||
import {useAppSelector} from '../../store/hooks'
|
||||
import {getCurrentView} from '../../store/views'
|
||||
import {getCurrentBoardId} from '../../store/boards'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
addCard: () => void
|
||||
@ -27,7 +28,7 @@ const EmptyCardButton = (props: Props) => {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<CardIcon/>}
|
||||
id='empty-template'
|
||||
name={intl.formatMessage({id: 'ViewHeader.empty-card', defaultMessage: 'Empty card'})}
|
||||
@ -39,7 +40,7 @@ const EmptyCardButton = (props: Props) => {
|
||||
<MenuWrapper stopPropagationOnToggle={true}>
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<CheckIcon/>}
|
||||
id='default'
|
||||
name={intl.formatMessage({
|
||||
|
@ -14,6 +14,7 @@ import Button from '../../widgets/buttons/button'
|
||||
import Menu from '../../widgets/menu'
|
||||
import MenuWrapper from '../../widgets/menuWrapper'
|
||||
import propsRegistry from '../../properties'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
import FilterValue from './filterValue'
|
||||
|
||||
@ -46,7 +47,7 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
<MenuWrapper>
|
||||
<Button>{propertyName}</Button>
|
||||
<Menu>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={'title'}
|
||||
id={'title'}
|
||||
name={'Title'}
|
||||
@ -64,7 +65,7 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
}}
|
||||
/>
|
||||
{board.cardProperties.filter((o: IPropertyTemplate) => propsRegistry.get(o.type).canFilter).map((o: IPropertyTemplate) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={o.id}
|
||||
id={o.id}
|
||||
name={o.name}
|
||||
@ -89,22 +90,22 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
<Menu>
|
||||
{propertyType.filterValueType === 'options' &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='includes'
|
||||
name={intl.formatMessage({id: 'Filter.includes', defaultMessage: 'includes'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='notIncludes'
|
||||
name={intl.formatMessage({id: 'Filter.not-includes', defaultMessage: 'doesn\'t include'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isEmpty'
|
||||
name={intl.formatMessage({id: 'Filter.is-empty', defaultMessage: 'is empty'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isNotEmpty'
|
||||
name={intl.formatMessage({id: 'Filter.is-not-empty', defaultMessage: 'is not empty'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
@ -112,12 +113,12 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
</>}
|
||||
{propertyType.filterValueType === 'person' &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='includes'
|
||||
name={intl.formatMessage({id: 'Filter.includes', defaultMessage: 'includes'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='notIncludes'
|
||||
name={intl.formatMessage({id: 'Filter.not-includes', defaultMessage: 'doesn\'t include'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
@ -125,12 +126,12 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
</>}
|
||||
{(propertyType.type === 'person' || propertyType.type === 'multiPerson') &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isEmpty'
|
||||
name={intl.formatMessage({id: 'Filter.is-empty', defaultMessage: 'is empty'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isNotEmpty'
|
||||
name={intl.formatMessage({id: 'Filter.is-not-empty', defaultMessage: 'is not empty'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
@ -138,12 +139,12 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
</>}
|
||||
{propertyType.filterValueType === 'boolean' &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isSet'
|
||||
name={intl.formatMessage({id: 'Filter.is-set', defaultMessage: 'is set'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isNotSet'
|
||||
name={intl.formatMessage({id: 'Filter.is-not-set', defaultMessage: 'is not set'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
@ -151,37 +152,37 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
</>}
|
||||
{propertyType.filterValueType === 'text' &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='is'
|
||||
name={intl.formatMessage({id: 'Filter.is', defaultMessage: 'is'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='contains'
|
||||
name={intl.formatMessage({id: 'Filter.contains', defaultMessage: 'contains'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='notContains'
|
||||
name={intl.formatMessage({id: 'Filter.not-contains', defaultMessage: 'doesn\'t contain'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='startsWith'
|
||||
name={intl.formatMessage({id: 'Filter.starts-with', defaultMessage: 'starts with'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='notStartsWith'
|
||||
name={intl.formatMessage({id: 'Filter.not-starts-with', defaultMessage: 'doesn\'t start with'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='endsWith'
|
||||
name={intl.formatMessage({id: 'Filter.ends-with', defaultMessage: 'ends with'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='notEndsWith'
|
||||
name={intl.formatMessage({id: 'Filter.not-ends-with', defaultMessage: 'doesn\'t end with'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
@ -189,17 +190,17 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
</>}
|
||||
{propertyType.filterValueType === 'date' &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='is'
|
||||
name={intl.formatMessage({id: 'Filter.is', defaultMessage: 'is'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isBefore'
|
||||
name={intl.formatMessage({id: 'Filter.isbefore', defaultMessage: 'is before'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isAfter'
|
||||
name={intl.formatMessage({id: 'Filter.isafter', defaultMessage: 'is after'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
@ -207,12 +208,12 @@ const FilterEntry = (props: Props): JSX.Element => {
|
||||
</>}
|
||||
{propertyType.type === 'date' &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isSet'
|
||||
name={intl.formatMessage({id: 'Filter.is-set', defaultMessage: 'is set'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='isNotSet'
|
||||
name={intl.formatMessage({id: 'Filter.is-not-set', defaultMessage: 'is not set'})}
|
||||
onClick={(id) => props.conditionClicked(id, filter)}
|
||||
|
@ -16,6 +16,8 @@ import Menu from '../../widgets/menu'
|
||||
import Editable from '../../widgets/editable'
|
||||
import MenuWrapper from '../../widgets/menuWrapper'
|
||||
|
||||
import {MenuSwitch} from '../../widgets/menu/menu'
|
||||
|
||||
import DateFilter from './dateFilter'
|
||||
|
||||
import './filterValue.scss'
|
||||
@ -103,7 +105,7 @@ const filterValue = (props: Props): JSX.Element|null => {
|
||||
|
||||
<Menu>
|
||||
{template?.options.map((o) => (
|
||||
<Menu.Switch
|
||||
<MenuSwitch
|
||||
key={o.id}
|
||||
id={o.id}
|
||||
name={o.value}
|
||||
|
@ -12,6 +12,8 @@ import {useAppSelector} from '../../store/hooks'
|
||||
import {getCurrentBoardTemplates} from '../../store/cards'
|
||||
import {getCurrentView} from '../../store/views'
|
||||
|
||||
import {MenuLabel, MenuSeparator, MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
import NewCardButtonTemplateItem from './newCardButtonTemplateItem'
|
||||
import EmptyCardButton from './emptyCardButton'
|
||||
|
||||
@ -46,16 +48,16 @@ const NewCardButton = (props: Props): JSX.Element => {
|
||||
>
|
||||
<Menu position='left'>
|
||||
{cardTemplates.length > 0 && <>
|
||||
<Menu.Label>
|
||||
<MenuLabel>
|
||||
<b>
|
||||
<FormattedMessage
|
||||
id='ViewHeader.select-a-template'
|
||||
defaultMessage='Select a template'
|
||||
/>
|
||||
</b>
|
||||
</Menu.Label>
|
||||
</MenuLabel>
|
||||
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
</>}
|
||||
|
||||
{cardTemplates.map((cardTemplate) => {
|
||||
@ -76,7 +78,7 @@ const NewCardButton = (props: Props): JSX.Element => {
|
||||
addCard={props.addCard}
|
||||
/>
|
||||
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<AddIcon/>}
|
||||
id='add-template'
|
||||
name={intl.formatMessage({id: 'ViewHeader.add-template', defaultMessage: 'New template'})}
|
||||
|
@ -16,6 +16,7 @@ import CheckIcon from '../../widgets/icons/check'
|
||||
import {useAppSelector} from '../../store/hooks'
|
||||
import {getCurrentView} from '../../store/views'
|
||||
import {getCurrentBoardId} from '../../store/boards'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
cardTemplate: Card
|
||||
@ -32,7 +33,7 @@ const NewCardButtonTemplateItem = (props: Props) => {
|
||||
const boardId = useAppSelector(getCurrentBoardId)
|
||||
|
||||
return (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={cardTemplate.id}
|
||||
id={cardTemplate.id}
|
||||
name={displayName}
|
||||
@ -45,7 +46,7 @@ const NewCardButtonTemplateItem = (props: Props) => {
|
||||
<MenuWrapper stopPropagationOnToggle={true}>
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<CheckIcon/>}
|
||||
id='default'
|
||||
name={intl.formatMessage({id: 'ViewHeader.set-default-template', defaultMessage: 'Set as default'})}
|
||||
@ -53,7 +54,7 @@ const NewCardButtonTemplateItem = (props: Props) => {
|
||||
await mutator.setDefaultTemplate(boardId, currentView.id, currentView.fields.defaultTemplateId, cardTemplate.id)
|
||||
}}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<EditIcon/>}
|
||||
id='edit'
|
||||
name={intl.formatMessage({id: 'ViewHeader.edit-template', defaultMessage: 'Edit'})}
|
||||
@ -61,7 +62,7 @@ const NewCardButtonTemplateItem = (props: Props) => {
|
||||
props.editCardTemplate(cardTemplate.id)
|
||||
}}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
icon={<DeleteIcon/>}
|
||||
id='delete'
|
||||
name={intl.formatMessage({id: 'ViewHeader.delete-template', defaultMessage: 'Delete'})}
|
||||
|
@ -16,6 +16,7 @@ import {Utils} from '../../utils'
|
||||
|
||||
import ModalWrapper from '../modalWrapper'
|
||||
import {sendFlashMessage} from '../flashMessages'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
board: Board
|
||||
@ -103,35 +104,35 @@ const ViewHeaderActionsMenu = (props: Props) => {
|
||||
<MenuWrapper label={intl.formatMessage({id: 'ViewHeader.view-header-menu', defaultMessage: 'View header menu'})}>
|
||||
<IconButton icon={<OptionsIcon/>}/>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='exportCsv'
|
||||
name={intl.formatMessage({id: 'ViewHeader.export-csv', defaultMessage: 'Export to CSV'})}
|
||||
onClick={() => onExportCsvTrigger(board, activeView, cards, intl)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='exportBoardArchive'
|
||||
name={intl.formatMessage({id: 'ViewHeader.export-board-archive', defaultMessage: 'Export board archive'})}
|
||||
onClick={() => Archiver.exportBoardArchive(board)}
|
||||
/>
|
||||
{/*
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='testAdd100Cards'
|
||||
name={intl.formatMessage({id: 'ViewHeader.test-add-100-cards', defaultMessage: 'TEST: Add 100 cards'})}
|
||||
onClick={() => testAddCards(board, activeView, cards.length, 100)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='testAdd1000Cards'
|
||||
name={intl.formatMessage({id: 'ViewHeader.test-add-1000-cards', defaultMessage: 'TEST: Add 1,000 cards'})}
|
||||
onClick={() => testAddCards(board, activeView, cards.length, 1000)}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='testDistributeCards'
|
||||
name={intl.formatMessage({id: 'ViewHeader.test-distribute-cards', defaultMessage: 'TEST: Distribute cards'})}
|
||||
onClick={() => testDistributeCards()}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='testRandomizeIcons'
|
||||
name={intl.formatMessage({id: 'ViewHeader.test-randomize-icons', defaultMessage: 'TEST: Randomize icons'})}
|
||||
onClick={() => testRandomizeIcons()}
|
||||
|
@ -15,6 +15,7 @@ import MenuWrapper from '../../widgets/menuWrapper'
|
||||
import CheckIcon from '../../widgets/icons/check'
|
||||
|
||||
import propsRegistry from '../../properties'
|
||||
import {MenuText} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
properties: readonly IPropertyTemplate[]
|
||||
@ -52,7 +53,7 @@ const ViewHeaderDisplayByMenu = (props: Props) => {
|
||||
</Button>
|
||||
<Menu>
|
||||
{getDateProperties().length > 0 && getDateProperties().map((date: IPropertyTemplate) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={date.id}
|
||||
id={date.id}
|
||||
name={date.name}
|
||||
@ -66,7 +67,7 @@ const ViewHeaderDisplayByMenu = (props: Props) => {
|
||||
/>
|
||||
))}
|
||||
{getDateProperties().length === 0 &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={'createdDate'}
|
||||
id={'createdDate'}
|
||||
name={createdDateName}
|
||||
|
@ -17,6 +17,7 @@ import {useAppSelector} from '../../store/hooks'
|
||||
import {getCurrentViewCardsSortedFilteredAndGrouped} from '../../store/cards'
|
||||
import {getVisibleAndHiddenGroups} from '../../boardUtils'
|
||||
import propsRegistry from '../../properties'
|
||||
import {MenuText, MenuSeparator} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
properties: readonly IPropertyTemplate[]
|
||||
@ -69,7 +70,7 @@ const ViewHeaderGroupByMenu = (props: Props) => {
|
||||
{activeView.fields.viewType === 'table' && activeView.fields.groupById &&
|
||||
<>
|
||||
{emptyVisibleGroupsCount > 0 &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={'hideEmptyGroups'}
|
||||
id={'hideEmptyGroups'}
|
||||
name={intl.formatMessage({id: 'GroupBy.hideEmptyGroups', defaultMessage: 'Hide {count} empty groups'}, {count: emptyVisibleGroupsCount})}
|
||||
@ -77,14 +78,14 @@ const ViewHeaderGroupByMenu = (props: Props) => {
|
||||
onClick={() => handleToggleGroups(false)}
|
||||
/>}
|
||||
{hiddenGroupsCount > 0 &&
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={'showHiddenGroups'}
|
||||
id={'showHiddenGroups'}
|
||||
name={intl.formatMessage({id: 'GroupBy.showHiddenGroups', defaultMessage: 'Show {count} hidden groups'}, {count: hiddenGroupsCount})}
|
||||
rightIcon={<ShowIcon/>}
|
||||
onClick={() => handleToggleGroups(true)}
|
||||
/>}
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={'ungroup'}
|
||||
id={''}
|
||||
name={intl.formatMessage({id: 'GroupBy.ungroup', defaultMessage: 'Ungroup'})}
|
||||
@ -96,10 +97,10 @@ const ViewHeaderGroupByMenu = (props: Props) => {
|
||||
mutator.changeViewGroupById(activeView.boardId, activeView.id, activeView.fields.groupById, id)
|
||||
}}
|
||||
/>
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
</>}
|
||||
{properties?.filter((o: IPropertyTemplate) => propsRegistry.get(o.type).canGroup).map((option: IPropertyTemplate) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={option.id}
|
||||
id={option.id}
|
||||
name={option.name}
|
||||
|
@ -10,6 +10,7 @@ import mutator from '../../mutator'
|
||||
import Button from '../../widgets/buttons/button'
|
||||
import Menu from '../../widgets/menu'
|
||||
import MenuWrapper from '../../widgets/menuWrapper'
|
||||
import {MenuSwitch} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
properties: readonly IPropertyTemplate[]
|
||||
@ -41,7 +42,7 @@ const ViewHeaderPropertiesMenu = (props: Props) => {
|
||||
</Button>
|
||||
<Menu>
|
||||
{activeView.fields.viewType === 'gallery' &&
|
||||
<Menu.Switch
|
||||
<MenuSwitch
|
||||
key={Constants.titleColumnId}
|
||||
id={Constants.titleColumnId}
|
||||
name={intl.formatMessage({id: 'default-properties.title', defaultMessage: 'Title'})}
|
||||
@ -50,7 +51,7 @@ const ViewHeaderPropertiesMenu = (props: Props) => {
|
||||
onClick={toggleVisibility}
|
||||
/>}
|
||||
{properties?.map((option: IPropertyTemplate) => (
|
||||
<Menu.Switch
|
||||
<MenuSwitch
|
||||
key={option.id}
|
||||
id={option.id}
|
||||
name={option.name}
|
||||
@ -60,7 +61,7 @@ const ViewHeaderPropertiesMenu = (props: Props) => {
|
||||
/>
|
||||
))}
|
||||
{canShowBadges &&
|
||||
<Menu.Switch
|
||||
<MenuSwitch
|
||||
key={Constants.badgesColumnId}
|
||||
id={Constants.badgesColumnId}
|
||||
name={intl.formatMessage({id: 'default-properties.badges', defaultMessage: 'Comments and description'})}
|
||||
|
@ -13,6 +13,7 @@ import Menu from '../../widgets/menu'
|
||||
import MenuWrapper from '../../widgets/menuWrapper'
|
||||
import SortDownIcon from '../../widgets/icons/sortDown'
|
||||
import SortUpIcon from '../../widgets/icons/sortUp'
|
||||
import {MenuText, MenuSeparator} from '../../widgets/menu/menu'
|
||||
|
||||
type Props = {
|
||||
properties: readonly IPropertyTemplate[]
|
||||
@ -64,19 +65,19 @@ const ViewHeaderSortMenu = (props: Props) => {
|
||||
<Menu>
|
||||
{(activeView.fields.sortOptions?.length > 0) &&
|
||||
<>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='manual'
|
||||
name='Manual'
|
||||
onClick={onManualSort}
|
||||
/>
|
||||
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='revert'
|
||||
name='Revert'
|
||||
onClick={onRevertSort}
|
||||
/>
|
||||
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
</>
|
||||
}
|
||||
|
||||
@ -89,7 +90,7 @@ const ViewHeaderSortMenu = (props: Props) => {
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={option.id}
|
||||
id={option.id}
|
||||
name={option.name}
|
||||
|
@ -19,8 +19,10 @@ import DuplicateIcon from '../widgets/icons/duplicate'
|
||||
import GalleryIcon from '../widgets/icons/gallery'
|
||||
import TableIcon from '../widgets/icons/table'
|
||||
import Menu from '../widgets/menu'
|
||||
import {MenuText, MenuSeparator, MenuSubMenu} from '../widgets/menu/menu'
|
||||
|
||||
import BoardPermissionGate from './permissions/boardPermissionGate'
|
||||
|
||||
import './viewMenu.scss'
|
||||
|
||||
type Props = {
|
||||
@ -273,7 +275,7 @@ const ViewMenu = (props: Props) => {
|
||||
<Menu>
|
||||
<div className='view-list'>
|
||||
{views.map((view: BoardView) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={view.id}
|
||||
id={view.id}
|
||||
name={view.title}
|
||||
@ -282,11 +284,11 @@ const ViewMenu = (props: Props) => {
|
||||
/>))}
|
||||
</div>
|
||||
<BoardPermissionGate permissions={[Permission.ManageBoardProperties]}>
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
</BoardPermissionGate>
|
||||
{!props.readonly &&
|
||||
<BoardPermissionGate permissions={[Permission.ManageBoardProperties]}>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='__duplicateView'
|
||||
name={duplicateViewText}
|
||||
icon={<DuplicateIcon/>}
|
||||
@ -296,7 +298,7 @@ const ViewMenu = (props: Props) => {
|
||||
}
|
||||
{!props.readonly && views.length > 1 &&
|
||||
<BoardPermissionGate permissions={[Permission.ManageBoardProperties]}>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='__deleteView'
|
||||
name={deleteViewText}
|
||||
icon={<DeleteIcon/>}
|
||||
@ -306,38 +308,38 @@ const ViewMenu = (props: Props) => {
|
||||
}
|
||||
{!props.readonly &&
|
||||
<BoardPermissionGate permissions={[Permission.ManageBoardProperties]}>
|
||||
<Menu.SubMenu
|
||||
<MenuSubMenu
|
||||
id='__addView'
|
||||
name={addViewText}
|
||||
icon={<AddIcon/>}
|
||||
>
|
||||
<div className='subMenu'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='board'
|
||||
name={boardText}
|
||||
icon={<BoardIcon/>}
|
||||
onClick={handleAddViewBoard}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='table'
|
||||
name={tableText}
|
||||
icon={<TableIcon/>}
|
||||
onClick={handleAddViewTable}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='gallery'
|
||||
name={galleryText}
|
||||
icon={<GalleryIcon/>}
|
||||
onClick={handleAddViewGallery}
|
||||
/>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='calendar'
|
||||
name='Calendar'
|
||||
icon={<CalendarIcon/>}
|
||||
onClick={handleAddViewCalendar}
|
||||
/>
|
||||
</div>
|
||||
</Menu.SubMenu>
|
||||
</MenuSubMenu>
|
||||
</BoardPermissionGate>
|
||||
}
|
||||
</Menu>
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React, {CSSProperties} from 'react'
|
||||
import React, {CSSProperties, useCallback, useEffect, useRef, useState} from 'react'
|
||||
|
||||
import SeparatorOption from './separatorOption'
|
||||
import SwitchOption from './switchOption'
|
||||
@ -21,71 +21,74 @@ type Props = {
|
||||
menuMargin?: number
|
||||
}
|
||||
|
||||
export default class Menu extends React.PureComponent<Props> {
|
||||
static Color = ColorOption
|
||||
static SubMenu = SubMenuOption
|
||||
static Switch = SwitchOption
|
||||
static Separator = SeparatorOption
|
||||
static Text = TextOption
|
||||
static TextInput = textInputOption
|
||||
static Label = LabelOption
|
||||
const MenuColor = ColorOption
|
||||
const MenuSubMenu = SubMenuOption
|
||||
const MenuSwitch = SwitchOption
|
||||
const MenuSeparator = SeparatorOption
|
||||
const MenuText = TextOption
|
||||
const MenuTextInput = textInputOption
|
||||
const MenuLabel = LabelOption
|
||||
|
||||
menuRef: React.RefObject<HTMLDivElement>
|
||||
const Menu = (props: Props): JSX.Element => {
|
||||
const menuRef = useRef<HTMLDivElement>(null)
|
||||
const [hovering, setHovering] = useState<React.ReactNode>(null)
|
||||
const [menuStyle, setMenuStyle] = useState<CSSProperties>({})
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
this.menuRef = React.createRef<HTMLDivElement>()
|
||||
}
|
||||
|
||||
public state = {
|
||||
hovering: null,
|
||||
menuStyle: {},
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
const {position, fixed, children} = this.props
|
||||
const {position, menuMargin, fixed, children} = props
|
||||
|
||||
useEffect(() => {
|
||||
let style: CSSProperties = {}
|
||||
if (this.props.parentRef) {
|
||||
if (props.parentRef) {
|
||||
const forceBottom = position ? ['bottom', 'left', 'right'].includes(position) : false
|
||||
style = MenuUtil.openUp(this.props.parentRef, forceBottom, this.props.menuMargin).style
|
||||
style = MenuUtil.openUp(props.parentRef, forceBottom, menuMargin).style
|
||||
}
|
||||
setMenuStyle(style)
|
||||
}, [props.parentRef, props.position, props.menuMargin])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`Menu noselect ${position || 'bottom'} ${fixed ? ' fixed' : ''}`}
|
||||
style={style}
|
||||
ref={this.menuRef}
|
||||
>
|
||||
<div className='menu-contents'>
|
||||
<div className='menu-options'>
|
||||
{React.Children.map(children, (child) => (
|
||||
<div
|
||||
onMouseEnter={() => this.setState({hovering: child})}
|
||||
>
|
||||
<HoveringContext.Provider value={child === this.state.hovering}>
|
||||
{child}
|
||||
</HoveringContext.Provider>
|
||||
</div>))}
|
||||
</div>
|
||||
const onCancel = useCallback(() => {
|
||||
// No need to do anything, as click bubbled up to MenuWrapper, which closes
|
||||
}, [])
|
||||
|
||||
<div className='menu-spacer hideOnWidescreen'/>
|
||||
return (
|
||||
<div
|
||||
className={`Menu noselect ${position || 'bottom'} ${fixed ? ' fixed' : ''}`}
|
||||
style={menuStyle}
|
||||
ref={menuRef}
|
||||
>
|
||||
<div className='menu-contents'>
|
||||
<div className='menu-options'>
|
||||
{React.Children.map(children, (child) => (
|
||||
<div
|
||||
onMouseEnter={() => setHovering(child)}
|
||||
>
|
||||
<HoveringContext.Provider value={child === hovering}>
|
||||
{child}
|
||||
</HoveringContext.Provider>
|
||||
</div>))}
|
||||
</div>
|
||||
|
||||
<div className='menu-options hideOnWidescreen'>
|
||||
<Menu.Text
|
||||
id='menu-cancel'
|
||||
name={'Cancel'}
|
||||
className='menu-cancel'
|
||||
onClick={this.onCancel}
|
||||
/>
|
||||
</div>
|
||||
<div className='menu-spacer hideOnWidescreen'/>
|
||||
|
||||
<div className='menu-options hideOnWidescreen'>
|
||||
<MenuText
|
||||
id='menu-cancel'
|
||||
name={'Cancel'}
|
||||
className='menu-cancel'
|
||||
onClick={onCancel}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private onCancel = () => {
|
||||
// No need to do anything, as click bubbled up to MenuWrapper, which closes
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Menu
|
||||
export {
|
||||
MenuColor,
|
||||
MenuSubMenu,
|
||||
MenuSwitch,
|
||||
MenuSeparator,
|
||||
MenuText,
|
||||
MenuTextInput,
|
||||
MenuLabel,
|
||||
}
|
||||
|
@ -6,9 +6,8 @@ import CompassIcon from '../../widgets/icons/compassIcon'
|
||||
|
||||
import MenuUtil from './menuUtil'
|
||||
|
||||
import Menu from '.'
|
||||
|
||||
import './subMenuOption.scss'
|
||||
import {MenuText} from './menu'
|
||||
|
||||
export const HoveringContext = React.createContext(false)
|
||||
|
||||
@ -77,7 +76,7 @@ function SubMenuOption(props: SubMenuOptionProps): JSX.Element {
|
||||
<div className='menu-spacer hideOnWidescreen'/>
|
||||
|
||||
<div className='menu-options hideOnWidescreen'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='menu-cancel'
|
||||
name={'Cancel'}
|
||||
className='menu-cancel'
|
||||
|
@ -6,7 +6,9 @@ import {useIntl, IntlShape} from 'react-intl'
|
||||
import Menu from '../widgets/menu'
|
||||
import propsRegistry from '../properties'
|
||||
import {PropertyType} from '../properties/types'
|
||||
|
||||
import './propertyMenu.scss'
|
||||
import {MenuLabel, MenuSeparator, MenuText, MenuTextInput, MenuSubMenu} from './menu/menu'
|
||||
|
||||
type Props = {
|
||||
propertyId: string
|
||||
@ -29,15 +31,15 @@ export const PropertyTypes = (props: TypesProps): JSX.Element => {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<>
|
||||
<Menu.Label>
|
||||
<MenuLabel>
|
||||
<b>{props.label}</b>
|
||||
</Menu.Label>
|
||||
</MenuLabel>
|
||||
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
|
||||
{
|
||||
propsRegistry.list().map((p) => (
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
key={p.type}
|
||||
id={p.type}
|
||||
name={p.displayName(intl)}
|
||||
@ -60,7 +62,7 @@ const PropertyMenu = (props: Props) => {
|
||||
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.TextInput
|
||||
<MenuTextInput
|
||||
initialValue={props.propertyName}
|
||||
onConfirmValue={(n) => {
|
||||
props.onTypeAndNameChanged(props.propertyType, n)
|
||||
@ -70,7 +72,7 @@ const PropertyMenu = (props: Props) => {
|
||||
currentPropertyName = n
|
||||
}}
|
||||
/>
|
||||
<Menu.SubMenu
|
||||
<MenuSubMenu
|
||||
id='type'
|
||||
name={typeMenuTitle(intl, props.propertyType)}
|
||||
>
|
||||
@ -78,8 +80,8 @@ const PropertyMenu = (props: Props) => {
|
||||
label={intl.formatMessage({id: 'PropertyMenu.changeType', defaultMessage: 'Change property type'})}
|
||||
onTypeSelected={(type: PropertyType) => props.onTypeAndNameChanged(type, currentPropertyName)}
|
||||
/>
|
||||
</Menu.SubMenu>
|
||||
<Menu.Text
|
||||
</MenuSubMenu>
|
||||
<MenuText
|
||||
id='delete'
|
||||
name={deleteText}
|
||||
onClick={() => props.onDelete(props.propertyId)}
|
||||
|
@ -22,6 +22,7 @@ import CloseIcon from './icons/close'
|
||||
import Label from './label'
|
||||
|
||||
import './valueSelector.scss'
|
||||
import {MenuText, MenuSeparator, MenuColor} from './menu/menu'
|
||||
|
||||
type Props = {
|
||||
options: IPropertyOption[]
|
||||
@ -84,15 +85,15 @@ const ValueSelectorLabel = (props: LabelProps): JSX.Element => {
|
||||
icon={<OptionsIcon/>}
|
||||
/>
|
||||
<Menu position='left'>
|
||||
<Menu.Text
|
||||
<MenuText
|
||||
id='delete'
|
||||
icon={<DeleteIcon/>}
|
||||
name={intl.formatMessage({id: 'BoardComponent.delete', defaultMessage: 'Delete'})}
|
||||
onClick={() => props.onDeleteOption(option)}
|
||||
/>
|
||||
<Menu.Separator/>
|
||||
<MenuSeparator/>
|
||||
{Object.entries(Constants.menuColors).map(([key, color]: [string, string]) => (
|
||||
<Menu.Color
|
||||
<MenuColor
|
||||
key={key}
|
||||
id={key}
|
||||
name={color}
|
||||
|
Loading…
Reference in New Issue
Block a user