Merge pull request #13 from mattermost/sidebar-menu-migration

Sidebar menus migrated to the new menus system
This commit is contained in:
chenilim 2020-10-15 11:47:31 -07:00 committed by GitHub
commit 3192271e7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 62 deletions

View file

@ -2,9 +2,9 @@ import React from "react"
import { Archiver } from "../archiver" import { Archiver } from "../archiver"
import { Board } from "../board" import { Board } from "../board"
import { BoardTree } from "../boardTree" import { BoardTree } from "../boardTree"
import { Menu, MenuOption } from "../menu" import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import mutator from "../mutator" import mutator from "../mutator"
import { IPageController } from "../octoTypes"
import { WorkspaceTree } from "../workspaceTree" import { WorkspaceTree } from "../workspaceTree"
type Props = { type Props = {
@ -32,7 +32,19 @@ class Sidebar extends React.Component<Props> {
<div key={board.id} className="octo-sidebar-item octo-hover-container"> <div key={board.id} className="octo-sidebar-item octo-hover-container">
<div className="octo-sidebar-title" onClick={() => { this.boardClicked(board) }}>{board.icon ? `${board.icon} ${displayTitle}` : displayTitle}</div> <div className="octo-sidebar-title" onClick={() => { this.boardClicked(board) }}>{board.icon ? `${board.icon} ${displayTitle}` : displayTitle}</div>
<div className="octo-spacer"></div> <div className="octo-spacer"></div>
<div className="octo-button square octo-hover-item" onClick={(e) => { this.showOptions(e, board) }}><div className="imageOptions" /></div> <MenuWrapper>
<div className="octo-button square octo-hover-item"><div className="imageOptions" /></div>
<Menu>
<Menu.Text id="delete" name="Delete board" onClick={async () => {
const nextBoardId = boards.length > 1 ? boards.find(o => o.id !== board.id).id : undefined
mutator.deleteBlock(
board,
"delete block",
async () => { nextBoardId && this.props.showBoard(nextBoardId!) },
async () => { this.props.showBoard(board.id) },
)}} />
</Menu>
</MenuWrapper>
</div> </div>
) )
}) })
@ -44,66 +56,17 @@ class Sidebar extends React.Component<Props> {
<div className="octo-spacer"></div> <div className="octo-spacer"></div>
<div className="octo-button" onClick={(e) => { this.settingsClicked(e) }}>Settings</div> <MenuWrapper>
<div className="octo-button">Settings</div>
<Menu position="top">
<Menu.Text id="import" name="Import Archive" onClick={async () => Archiver.importFullArchive(() => { this.forceUpdate() })} />
<Menu.Text id="export" name="Export Archive" onClick={async () => Archiver.exportFullArchive()} />
</Menu>
</MenuWrapper>
</div> </div>
) )
} }
private showOptions(e: React.MouseEvent, board: Board) {
const { showBoard, workspaceTree } = this.props
const { boards } = workspaceTree
const options: MenuOption[] = []
const nextBoardId = boards.length > 1 ? boards.find(o => o.id !== board.id).id : undefined
if (nextBoardId) {
options.push({ id: "delete", name: "Delete board" })
}
Menu.shared.options = options
Menu.shared.onMenuClicked = (optionId: string, type?: string) => {
switch (optionId) {
case "delete": {
mutator.deleteBlock(
board,
"delete block",
async () => { showBoard(nextBoardId!) },
async () => { showBoard(board.id) },
)
break
}
}
}
Menu.shared.showAtElement(e.target as HTMLElement)
}
private settingsClicked(e: React.MouseEvent) {
Menu.shared.options = [
{ id: "import", name: "Import Archive" },
{ id: "export", name: "Export Archive" },
]
Menu.shared.onMenuClicked = (optionId: string, type?: string) => {
switch (optionId) {
case "import": {
Archiver.importFullArchive(() => {
this.forceUpdate()
})
break
}
case "export": {
Archiver.exportFullArchive()
break
}
}
}
// HACKHACK: Show menu above (TODO: refactor menu code to do this automatically)
const element = e.target as HTMLElement
const bodyRect = document.body.getBoundingClientRect()
const rect = element.getBoundingClientRect()
Menu.shared.showAt(rect.left - bodyRect.left + 20, rect.top - bodyRect.top - 30 * Menu.shared.options.length)
}
private boardClicked(board: Board) { private boardClicked(board: Board) {
this.props.showBoard(board.id) this.props.showBoard(board.id)
} }

View file

@ -117,6 +117,7 @@ class TextOption extends React.Component<TextOptionProps> {
type MenuProps = { type MenuProps = {
children: React.ReactNode children: React.ReactNode
position?: 'top'|'bottom'
} }
export default class Menu extends React.Component<MenuProps> { export default class Menu extends React.Component<MenuProps> {
@ -127,10 +128,11 @@ export default class Menu extends React.Component<MenuProps> {
static Text = TextOption static Text = TextOption
render() { render() {
const {position, children} = this.props
return ( return (
<div className="Menu menu noselect"> <div className={"Menu menu noselect " + (position ? position : "bottom")}>
<div className="menu-options"> <div className="menu-options">
{this.props.children} {children}
</div> </div>
</div> </div>
) )

View file

@ -82,7 +82,7 @@ export default class MenuWrapper extends React.PureComponent<Props, State> {
return ( return (
<div <div
className={'MenuWrapper'} className={'MenuWrapper menu-wrapper'}
onClick={this.toggle} onClick={this.toggle}
ref={this.node} ref={this.node}
> >

View file

@ -329,6 +329,14 @@ hr {
background-color: #ffffff; background-color: #ffffff;
} }
.menu.top {
bottom: 100%;
}
.menu-wrapper {
position: relative;
}
.menu-options { .menu-options {
display: flex; display: flex;
flex-direction: column; flex-direction: column;