Removing the need of the global showCard
This commit is contained in:
parent
24916c83dc
commit
c6118dd447
7 changed files with 77 additions and 84 deletions
|
@ -15,12 +15,13 @@ import { BoardCard } from "./boardCard"
|
|||
import { BoardColumn } from "./boardColumn"
|
||||
import Button from "./button"
|
||||
import { Editable } from "./editable"
|
||||
import { CardDialog } from "./cardDialog"
|
||||
import RootPortal from "./rootPortal"
|
||||
|
||||
type Props = {
|
||||
mutator: Mutator,
|
||||
boardTree?: BoardTree
|
||||
showView: (id: string) => void
|
||||
showCard: (card: IBlock) => void
|
||||
showFilter: (el: HTMLElement) => void
|
||||
setSearchText: (text: string) => void
|
||||
}
|
||||
|
@ -28,6 +29,7 @@ type Props = {
|
|||
type State = {
|
||||
isHoverOnCover: boolean
|
||||
isSearching: boolean
|
||||
shownCard: IBlock | null
|
||||
}
|
||||
|
||||
class BoardComponent extends React.Component<Props, State> {
|
||||
|
@ -37,7 +39,7 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = { isHoverOnCover: false, isSearching: !!this.props.boardTree?.getSearchText() }
|
||||
this.state = { isHoverOnCover: false, isSearching: !!this.props.boardTree?.getSearchText(), shownCard: null }
|
||||
}
|
||||
|
||||
componentDidUpdate(prevPros: Props, prevState: State) {
|
||||
|
@ -66,6 +68,11 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
|
||||
return (
|
||||
<div className="octo-app">
|
||||
{this.state.shownCard &&
|
||||
<RootPortal>
|
||||
<CardDialog boardTree={boardTree} card={this.state.shownCard} mutator={mutator} onClose={() => this.setState({shownCard: null})}/>
|
||||
</RootPortal>}
|
||||
|
||||
<div className="octo-frame">
|
||||
<div
|
||||
className="octo-hovercontrols"
|
||||
|
@ -170,7 +177,7 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
card={card}
|
||||
visiblePropertyTemplates={visiblePropertyTemplates}
|
||||
key={card.id}
|
||||
onClick={() => { this.showCard(card) }}
|
||||
onClick={() => { this.setState({shownCard: card}) }}
|
||||
onDragStart={() => { this.draggedCard = card }}
|
||||
onDragEnd={() => { this.draggedCard = undefined }} />
|
||||
)}
|
||||
|
@ -187,7 +194,7 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
card={card}
|
||||
visiblePropertyTemplates={visiblePropertyTemplates}
|
||||
key={card.id}
|
||||
onClick={() => { this.showCard(card) }}
|
||||
onClick={() => { this.setState({shownCard: card}) }}
|
||||
onDragStart={() => { this.draggedCard = card }}
|
||||
onDragEnd={() => { this.draggedCard = undefined }} />
|
||||
)}
|
||||
|
@ -223,12 +230,6 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
Menu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
async showCard(card?: IBlock) {
|
||||
console.log(`showCard: ${card?.title}`)
|
||||
|
||||
await this.props.showCard(card)
|
||||
}
|
||||
|
||||
async addCard(groupByValue?: string) {
|
||||
const { mutator, boardTree } = this.props
|
||||
const { activeView, board } = boardTree
|
||||
|
@ -238,7 +239,7 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
if (boardTree.groupByProperty) {
|
||||
card.properties[boardTree.groupByProperty.id] = groupByValue
|
||||
}
|
||||
await mutator.insertBlock(card, "add card", async () => { await this.showCard(card) }, async () => { await this.showCard(undefined) })
|
||||
await mutator.insertBlock(card, "add card", async () => { await this.setState({shownCard: card}) }, async () => { await this.setState({shownCard: null}) })
|
||||
}
|
||||
|
||||
async propertyNameChanged(option: IPropertyOption, text: string) {
|
||||
|
|
|
@ -8,6 +8,8 @@ import { Mutator } from "../mutator"
|
|||
import { IBlock } from "../octoTypes"
|
||||
import { OctoUtils } from "../octoUtils"
|
||||
import { PropertyMenu } from "../propertyMenu"
|
||||
import { OctoListener } from "../octoListener"
|
||||
import { OctoClient } from "../octoClient"
|
||||
import { Utils } from "../utils"
|
||||
import Button from "./button"
|
||||
import { Editable } from "./editable"
|
||||
|
@ -15,45 +17,67 @@ import { MarkdownEditor } from "./markdownEditor"
|
|||
|
||||
type Props = {
|
||||
boardTree: BoardTree
|
||||
cardTree: CardTree
|
||||
card: IBlock
|
||||
mutator: Mutator
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
type State = {
|
||||
isHoverOnCover: boolean
|
||||
cardTree: CardTree | null
|
||||
}
|
||||
|
||||
class CardDialog extends React.Component<Props, State> {
|
||||
private titleRef = React.createRef<Editable>()
|
||||
private keydownHandler: any
|
||||
private cardListener: OctoListener
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = { isHoverOnCover: false }
|
||||
this.state = { isHoverOnCover: false, cardTree: null }
|
||||
}
|
||||
|
||||
keydownHandler = (e: KeyboardEvent) => {
|
||||
if (e.target !== document.body) { return }
|
||||
|
||||
if (e.keyCode === 27) {
|
||||
this.close()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.titleRef.current.focus()
|
||||
this.keydownHandler = (e: KeyboardEvent) => {
|
||||
if (e.target !== document.body) { return }
|
||||
this.cardListener = new OctoListener()
|
||||
this.cardListener.open(this.props.card.id, async () => {
|
||||
await cardTree.sync()
|
||||
this.setState({cardTree: cardTree})
|
||||
})
|
||||
const cardTree = new CardTree(new OctoClient(), this.props.card.id)
|
||||
cardTree.sync().then(() => {
|
||||
this.setState({cardTree})
|
||||
});
|
||||
|
||||
if (e.keyCode === 27) {
|
||||
this.close()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", this.keydownHandler)
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props, prevState: State) {
|
||||
if (this.titleRef.current && prevState.cardTree === null && this.state.cardTree !== null) {
|
||||
this.titleRef.current.focus()
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener("keydown", this.keydownHandler)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { boardTree, cardTree, mutator } = this.props
|
||||
const { boardTree, mutator, card } = this.props
|
||||
const { cardTree } = this.state
|
||||
const { board } = boardTree
|
||||
const { card, comments } = cardTree
|
||||
if (cardTree === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
const { comments } = cardTree
|
||||
|
||||
const newCommentPlaceholderText = "Add a comment..."
|
||||
|
||||
|
@ -332,8 +356,7 @@ class CardDialog extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
async sendComment(text: string) {
|
||||
const { mutator, cardTree } = this.props
|
||||
const { card } = cardTree
|
||||
const { mutator, card } = this.props
|
||||
|
||||
Utils.assertValue(card)
|
||||
|
||||
|
@ -342,8 +365,8 @@ class CardDialog extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
private showContentBlockMenu(e: React.MouseEvent, block: IBlock) {
|
||||
const { mutator, cardTree } = this.props
|
||||
const { card } = cardTree
|
||||
const { mutator, card } = this.props
|
||||
const { cardTree } = this.state
|
||||
const index = cardTree.contents.indexOf(block)
|
||||
|
||||
const options: MenuOption[] = []
|
||||
|
@ -409,8 +432,7 @@ class CardDialog extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
private iconClicked(e: React.MouseEvent) {
|
||||
const { mutator, cardTree } = this.props
|
||||
const { card } = cardTree
|
||||
const { mutator, card } = this.props
|
||||
|
||||
Menu.shared.options = [
|
||||
{ id: "random", name: "Random" },
|
||||
|
|
|
@ -13,12 +13,13 @@ import { Utils } from "../utils"
|
|||
import Button from "./button"
|
||||
import { Editable } from "./editable"
|
||||
import { TableRow } from "./tableRow"
|
||||
import { CardDialog } from "./cardDialog"
|
||||
import RootPortal from "./rootPortal"
|
||||
|
||||
type Props = {
|
||||
mutator: Mutator,
|
||||
boardTree?: BoardTree
|
||||
showView: (id: string) => void
|
||||
showCard: (card: IBlock) => void
|
||||
showFilter: (el: HTMLElement) => void
|
||||
setSearchText: (text: string) => void
|
||||
}
|
||||
|
@ -26,6 +27,7 @@ type Props = {
|
|||
type State = {
|
||||
isHoverOnCover: boolean
|
||||
isSearching: boolean
|
||||
shownCard: IBlock | null
|
||||
}
|
||||
|
||||
class TableComponent extends React.Component<Props, State> {
|
||||
|
@ -36,7 +38,7 @@ class TableComponent extends React.Component<Props, State> {
|
|||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = { isHoverOnCover: false, isSearching: !!this.props.boardTree?.getSearchText() }
|
||||
this.state = { isHoverOnCover: false, isSearching: !!this.props.boardTree?.getSearchText(), shownCard: null }
|
||||
}
|
||||
|
||||
componentDidUpdate(prevPros: Props, prevState: State) {
|
||||
|
@ -63,6 +65,10 @@ class TableComponent extends React.Component<Props, State> {
|
|||
|
||||
return (
|
||||
<div className="octo-app">
|
||||
{this.state.shownCard &&
|
||||
<RootPortal>
|
||||
<CardDialog boardTree={boardTree} card={this.state.shownCard} mutator={mutator} onClose={() => this.setState({shownCard: null})}/>
|
||||
</RootPortal>}
|
||||
<div className="octo-frame">
|
||||
<div
|
||||
className="octo-hovercontrols"
|
||||
|
@ -167,7 +173,6 @@ class TableComponent extends React.Component<Props, State> {
|
|||
boardTree={boardTree}
|
||||
card={card}
|
||||
focusOnMount={focusOnMount}
|
||||
showCard={(c) => { this.showCard(c) }}
|
||||
onKeyDown={(e) => {
|
||||
if (e.keyCode === 13) {
|
||||
// Enter: Insert new card if on last row
|
||||
|
@ -347,12 +352,6 @@ class TableComponent extends React.Component<Props, State> {
|
|||
Menu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
async showCard(card: IBlock) {
|
||||
console.log(`showCard: ${card.title}`)
|
||||
|
||||
await this.props.showCard(card)
|
||||
}
|
||||
|
||||
focusOnCardTitle(cardId: string) {
|
||||
const tableRowRef = this.cardIdToRowMap.get(cardId)
|
||||
Utils.log(`focusOnCardTitle, ${tableRowRef?.current ?? "undefined"}`)
|
||||
|
@ -368,7 +367,7 @@ class TableComponent extends React.Component<Props, State> {
|
|||
"add card",
|
||||
async () => {
|
||||
if (show) {
|
||||
this.showCard(card)
|
||||
this.setState({shownCard: card})
|
||||
} else {
|
||||
// Focus on this card's title inline on next render
|
||||
this.cardIdToFocusOnRender = card.id
|
||||
|
|
|
@ -4,21 +4,26 @@ import { Mutator } from "../mutator"
|
|||
import { IBlock } from "../octoTypes"
|
||||
import { OctoUtils } from "../octoUtils"
|
||||
import { Editable } from "./editable"
|
||||
import { CardDialog } from "./cardDialog"
|
||||
import RootPortal from "./rootPortal"
|
||||
|
||||
type Props = {
|
||||
mutator: Mutator
|
||||
boardTree: BoardTree
|
||||
card: IBlock
|
||||
focusOnMount: boolean
|
||||
showCard: (card: IBlock) => void
|
||||
onKeyDown: (e: React.KeyboardEvent) => void
|
||||
}
|
||||
|
||||
type State = {
|
||||
showCard: boolean
|
||||
}
|
||||
|
||||
class TableRow extends React.Component<Props, State> {
|
||||
private titleRef = React.createRef<Editable>()
|
||||
state = {
|
||||
showCard: false
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.focusOnMount) {
|
||||
|
@ -27,7 +32,7 @@ class TableRow extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { mutator, boardTree, card, showCard, onKeyDown } = this.props
|
||||
const { mutator, boardTree, card, onKeyDown } = this.props
|
||||
const { board, activeView } = boardTree
|
||||
|
||||
const openButonRef = React.createRef<HTMLDivElement>()
|
||||
|
@ -48,7 +53,11 @@ class TableRow extends React.Component<Props, State> {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div ref={openButonRef} className="octo-hoverbutton" style={{ display: "none" }} onClick={() => { showCard(card) }}>Open</div>
|
||||
<div ref={openButonRef} className="octo-hoverbutton" style={{ display: "none" }} onClick={() => { this.setState({showCard: true}) }}>Open</div>
|
||||
{this.state.showCard &&
|
||||
<RootPortal>
|
||||
<CardDialog boardTree={boardTree} card={card} mutator={mutator} onClose={() => this.setState({showCard: false})}/>
|
||||
</RootPortal>}
|
||||
</div>
|
||||
|
||||
{/* Columns, one per property */}
|
||||
|
|
|
@ -14,7 +14,6 @@ type Props = {
|
|||
boardTree?: BoardTree
|
||||
showBoard: (id: string) => void
|
||||
showView: (id: string) => void
|
||||
showCard: (card: IBlock) => void
|
||||
showFilter: (el: HTMLElement) => void
|
||||
setSearchText: (text: string) => void
|
||||
}
|
||||
|
@ -34,7 +33,7 @@ class WorkspaceComponent extends React.Component<Props> {
|
|||
}
|
||||
|
||||
private mainComponent() {
|
||||
const { mutator, boardTree, showCard, showFilter, setSearchText, showView } = this.props
|
||||
const { mutator, boardTree, showFilter, setSearchText, showView } = this.props
|
||||
const { activeView } = boardTree || {}
|
||||
|
||||
if (!activeView) {
|
||||
|
@ -43,11 +42,11 @@ class WorkspaceComponent extends React.Component<Props> {
|
|||
|
||||
switch (activeView?.viewType) {
|
||||
case "board": {
|
||||
return <BoardComponent mutator={mutator} boardTree={boardTree} showCard={showCard} showFilter={showFilter} setSearchText={setSearchText} showView={showView} />
|
||||
return <BoardComponent mutator={mutator} boardTree={boardTree} showFilter={showFilter} setSearchText={setSearchText} showView={showView} />
|
||||
}
|
||||
|
||||
case "table": {
|
||||
return <TableComponent mutator={mutator} boardTree={boardTree} showCard={showCard} showFilter={showFilter} setSearchText={setSearchText} showView={showView} />
|
||||
return <TableComponent mutator={mutator} boardTree={boardTree} showFilter={showFilter} setSearchText={setSearchText} showView={showView} />
|
||||
}
|
||||
|
||||
default: {
|
||||
|
|
|
@ -17,7 +17,6 @@ interface IBlock {
|
|||
|
||||
// These are methods exposed by the top-level page to components
|
||||
interface IPageController {
|
||||
showCard(card: IBlock): Promise<void>
|
||||
showBoard(boardId: string): void
|
||||
showView(viewId: string): void
|
||||
showFilter(anchorElement?: HTMLElement): void
|
||||
|
|
|
@ -110,22 +110,6 @@ export default class BoardPage extends React.Component<Props, State> {
|
|||
const { board, activeView } = this.state.boardTree || {}
|
||||
const mutator = new Mutator(this.octo)
|
||||
|
||||
// TODO Move all this into the root portal component when that is merged
|
||||
if (this.state.boardTree && this.state.boardTree.board && shownCardTree) {
|
||||
ReactDOM.render(
|
||||
<CardDialog mutator={mutator} boardTree={this.state.boardTree} cardTree={shownCardTree} onClose={() => { this.showCard(undefined) }}></CardDialog>,
|
||||
Utils.getElementById("overlay")
|
||||
)
|
||||
} else {
|
||||
const overlay = document.getElementById("overlay")
|
||||
if (overlay) {
|
||||
ReactDOM.render(
|
||||
<div />,
|
||||
overlay
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (this.filterAnchorElement) {
|
||||
const element = this.filterAnchorElement
|
||||
const bodyRect = document.body.getBoundingClientRect()
|
||||
|
@ -161,7 +145,6 @@ export default class BoardPage extends React.Component<Props, State> {
|
|||
workspaceTree={workspaceTree}
|
||||
boardTree={this.state.boardTree}
|
||||
showView={(id) => { this.showView(id) }}
|
||||
showCard={(card) => { this.showCard(card) }}
|
||||
showBoard={(id) => { this.showBoard(id) }}
|
||||
showFilter={(el) => { this.showFilter(el) }}
|
||||
setSearchText={(text) => { this.setSearchText(text) }} />
|
||||
|
@ -209,25 +192,6 @@ export default class BoardPage extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
// IPageController
|
||||
|
||||
async showCard(card: IBlock) {
|
||||
this.cardListener.close()
|
||||
|
||||
if (card) {
|
||||
const cardTree = new CardTree(this.octo, card.id)
|
||||
await cardTree.sync()
|
||||
this.setState({...this.state, shownCardTree: cardTree})
|
||||
|
||||
this.cardListener = new OctoListener()
|
||||
this.cardListener.open(card.id, async () => {
|
||||
await cardTree.sync()
|
||||
this.forceUpdate()
|
||||
})
|
||||
} else {
|
||||
this.setState({...this.state, shownCardTree: undefined})
|
||||
}
|
||||
}
|
||||
|
||||
showBoard(boardId: string) {
|
||||
const { boardTree } = this.state
|
||||
|
||||
|
|
Loading…
Reference in a new issue