1
0
mirror of https://github.com/mattermost/focalboard.git synced 2025-01-17 18:26:17 +02:00

Cleanup merge of react-router

This commit is contained in:
Chen-I Lim 2020-10-14 11:19:14 -07:00
parent 3c76e099c3
commit 3cfad9d027
5 changed files with 161 additions and 140 deletions

View File

@ -1,40 +1,37 @@
import React from "react"; import React from "react"
import { import {
BrowserRouter as Router, BrowserRouter as Router,
Switch, Switch,
Route, Route,
Link Link
} from "react-router-dom"; } from "react-router-dom"
import LoginPage from './pages/loginPage'; import LoginPage from './pages/loginPage'
import BoardPage from './pages/boardPage'; import BoardPage from './pages/boardPage'
export default function App() { export default function App() {
return ( return (
<Router> <Router>
<div> <div id="frame">
<header id="header"> <div className="page-header">
<a href="/">OCTO</a> <a href="/">OCTO</a>
</header> </div>
<main id="main"> <div id="main">
<Switch> <Switch>
<Route path="/login"> <Route path="/login">
<LoginPage /> <LoginPage />
</Route> </Route>
<Route path="/board"> <Route path="/board">
<BoardPage /> <BoardPage />
</Route> </Route>
</Switch> </Switch>
</main> </div>
<footer id="footer"> <div id="overlay">
</footer> </div>
</div>
<div id="overlay"> </Router>
</div> )
</div>
</Router>
);
} }

View File

@ -9,7 +9,7 @@ import { WorkspaceTree } from "../workspaceTree"
type Props = { type Props = {
mutator: Mutator mutator: Mutator
showBoard: (id: string) => void showBoard: (id: string) => void
workspaceTree: WorkspaceTree, workspaceTree: WorkspaceTree,
boardTree?: BoardTree boardTree?: BoardTree
} }
@ -18,6 +18,10 @@ class Sidebar extends React.Component<Props> {
render() { render() {
const { workspaceTree } = this.props const { workspaceTree } = this.props
if (!workspaceTree) {
return <div></div>
}
const { boards } = workspaceTree const { boards } = workspaceTree
return ( return (

View File

@ -12,17 +12,18 @@ type Props = {
mutator: Mutator, mutator: Mutator,
workspaceTree: WorkspaceTree workspaceTree: WorkspaceTree
boardTree?: BoardTree boardTree?: BoardTree
showBoard: (id: string) => void showBoard: (id: string) => void
showView: (id: string) => void showView: (id: string) => void
showCard: (card: IBlock) => void showCard: (card: IBlock) => void
showFilter: (el: HTMLElement) => void showFilter: (el: HTMLElement) => void
setSearchText: (text: string) => void setSearchText: (text: string) => void
} }
class WorkspaceComponent extends React.Component<Props> { class WorkspaceComponent extends React.Component<Props> {
render() { render() {
const { mutator, boardTree, workspaceTree, showBoard} = this.props const { mutator, boardTree, workspaceTree, showBoard } = this.props
Utils.assert(workspaceTree)
const element = const element =
<div className="octo-workspace"> <div className="octo-workspace">
<Sidebar mutator={mutator} showBoard={showBoard} workspaceTree={workspaceTree} boardTree={boardTree}></Sidebar> <Sidebar mutator={mutator} showBoard={showBoard} workspaceTree={workspaceTree} boardTree={boardTree}></Sidebar>
@ -42,11 +43,11 @@ class WorkspaceComponent extends React.Component<Props> {
switch (activeView?.viewType) { switch (activeView?.viewType) {
case "board": { case "board": {
return <BoardComponent mutator={mutator} boardTree={boardTree} showCard={showCard} showFilter={showFilter} setSearchText={setSearchText} showView={showView}/> return <BoardComponent mutator={mutator} boardTree={boardTree} showCard={showCard} showFilter={showFilter} setSearchText={setSearchText} showView={showView} />
} }
case "table": { case "table": {
return <TableComponent mutator={mutator} boardTree={boardTree} showCard={showCard} showFilter={showFilter} setSearchText={setSearchText} showView={showView}/> return <TableComponent mutator={mutator} boardTree={boardTree} showCard={showCard} showFilter={showFilter} setSearchText={setSearchText} showView={showView} />
} }
default: { default: {

View File

@ -5,13 +5,12 @@ import { BoardView } from "../boardView"
import { CardTree } from "../cardTree" import { CardTree } from "../cardTree"
import { CardDialog } from "../components/cardDialog" import { CardDialog } from "../components/cardDialog"
import { FilterComponent } from "../components/filterComponent" import { FilterComponent } from "../components/filterComponent"
import { PageHeader } from "../components/pageHeader"
import { WorkspaceComponent } from "../components/workspaceComponent" import { WorkspaceComponent } from "../components/workspaceComponent"
import { FlashMessage } from "../flashMessage" import { FlashMessage } from "../flashMessage"
import { Mutator } from "../mutator" import { Mutator } from "../mutator"
import { OctoClient } from "../octoClient" import { OctoClient } from "../octoClient"
import { OctoListener } from "../octoListener" import { OctoListener } from "../octoListener"
import { IBlock, IPageController } from "../octoTypes" import { IBlock } from "../octoTypes"
import { UndoManager } from "../undomanager" import { UndoManager } from "../undomanager"
import { Utils } from "../utils" import { Utils } from "../utils"
import { WorkspaceTree } from "../workspaceTree" import { WorkspaceTree } from "../workspaceTree"
@ -20,109 +19,111 @@ type Props = {
} }
type State = { type State = {
boardId: string boardId: string
viewId: string viewId: string
workspaceTree: WorkspaceTree workspaceTree: WorkspaceTree
boardTree?: BoardTree boardTree?: BoardTree
shownCardTree?: CardTree
} }
export default class BoardPage extends React.Component<Props, State> { export default class BoardPage extends React.Component<Props, State> {
workspaceTree: WorkspaceTree
boardTree?: BoardTree
view: BoardView view: BoardView
updateTitleTimeout: number updateTitleTimeout: number
updatePropertyLabelTimeout: number updatePropertyLabelTimeout: number
shownCardTree: CardTree
private filterAnchorElement?: HTMLElement private filterAnchorElement?: HTMLElement
private octo = new OctoClient() private octo = new OctoClient()
private boardListener = new OctoListener() private boardListener = new OctoListener()
private cardListener = new OctoListener() private cardListener = new OctoListener()
constructor(props: Props) { constructor(props: Props) {
super(props) super(props)
const queryString = new URLSearchParams(window.location.search) const queryString = new URLSearchParams(window.location.search)
const boardId = queryString.get("id") const boardId = queryString.get("id")
const viewId = queryString.get("v") const viewId = queryString.get("v")
this.state = { this.state = {
boardId, boardId,
viewId, viewId,
workspaceTree: new WorkspaceTree(this.octo), workspaceTree: new WorkspaceTree(this.octo),
}
console.log(`BoardPage. boardId: ${boardId}`)
}
componentDidUpdate(prevProps: Props, prevState: State) {
const board = this.state.boardTree.board;
const prevBoard = prevState.boardTree.board;
const activeView = this.state.boardTree.activeView;
const prevActiveView = prevState.boardTree.activeView;
if (board.icon !== prevBoard.icon) {
Utils.setFavicon(board.icon)
}
if (board.title !== prevBoard.title || activeView.title !== prevActiveView.title) {
document.title = `OCTO - ${board.title} | ${activeView.title}`
} }
}
undoRedoHandler = async (e: KeyboardEvent) => { Utils.log(`BoardPage. boardId: ${boardId}`)
if (e.target !== document) { return } }
if (e.keyCode === 90 && !e.shiftKey && (e.ctrlKey || e.metaKey) && !e.altKey) { // Cmd+Z componentDidUpdate(prevProps: Props, prevState: State) {
Utils.log(`Undo`) Utils.log(`componentDidUpdate`)
const description = UndoManager.shared.undoDescription const board = this.state.boardTree?.board
await UndoManager.shared.undo() const prevBoard = prevState.boardTree?.board
if (description) {
FlashMessage.show(`Undo ${description}`)
} else {
FlashMessage.show(`Undo`)
}
} else if (e.keyCode === 90 && e.shiftKey && (e.ctrlKey || e.metaKey) && !e.altKey) { // Shift+Cmd+Z
Utils.log(`Redo`)
const description = UndoManager.shared.redoDescription
await UndoManager.shared.redo()
if (description) {
FlashMessage.show(`Redo ${description}`)
} else {
FlashMessage.show(`Redo`)
}
}
}
componentDidMount() { const activeView = this.state.boardTree?.activeView
const prevActiveView = prevState.boardTree?.activeView
if (board?.icon !== prevBoard?.icon) {
Utils.setFavicon(board?.icon)
}
if (board?.title !== prevBoard?.title || activeView?.title !== prevActiveView?.title) {
document.title = `OCTO - ${board?.title} | ${activeView?.title}`
}
}
undoRedoHandler = async (e: KeyboardEvent) => {
if (e.target !== document.body) { return }
if (e.keyCode === 90 && !e.shiftKey && (e.ctrlKey || e.metaKey) && !e.altKey) { // Cmd+Z
Utils.log(`Undo`)
const description = UndoManager.shared.undoDescription
await UndoManager.shared.undo()
if (description) {
FlashMessage.show(`Undo ${description}`)
} else {
FlashMessage.show(`Undo`)
}
} else if (e.keyCode === 90 && e.shiftKey && (e.ctrlKey || e.metaKey) && !e.altKey) { // Shift+Cmd+Z
Utils.log(`Redo`)
const description = UndoManager.shared.redoDescription
await UndoManager.shared.redo()
if (description) {
FlashMessage.show(`Redo ${description}`)
} else {
FlashMessage.show(`Redo`)
}
}
}
componentDidMount() {
document.addEventListener("keydown", this.undoRedoHandler) document.addEventListener("keydown", this.undoRedoHandler)
if (this.state.boardId) { if (this.state.boardId) {
this.attachToBoard(this.state.boardId, this.state.viewId) this.attachToBoard(this.state.boardId, this.state.viewId)
} else { } else {
this.sync() this.sync()
} }
} }
componentWillUnmount() { componentWillUnmount() {
document.removeEventListener("keydown", this.undoRedoHandler) document.removeEventListener("keydown", this.undoRedoHandler)
} }
render() { render() {
const { workspaceTree, shownCardTree } = this.state
const { board, activeView } = this.state.boardTree || {} const { board, activeView } = this.state.boardTree || {}
const mutator = new Mutator(this.octo) const mutator = new Mutator(this.octo)
// TODO Move all this into the root portal component when that is merged // TODO Move all this into the root portal component when that is merged
if (this.state.boardTree && this.state.boardTree.board && this.shownCardTree) { if (this.state.boardTree && this.state.boardTree.board && shownCardTree) {
ReactDOM.render( ReactDOM.render(
<CardDialog mutator={mutator} boardTree={this.state.boardTree} cardTree={this.shownCardTree} onClose={() => { this.showCard(undefined) }}></CardDialog>, <CardDialog mutator={mutator} boardTree={this.state.boardTree} cardTree={shownCardTree} onClose={() => { this.showCard(undefined) }}></CardDialog>,
Utils.getElementById("overlay") Utils.getElementById("overlay")
) )
} else { } else {
ReactDOM.render( const overlay = document.getElementById("overlay")
<div />, if (overlay) {
Utils.getElementById("overlay") ReactDOM.render(
) <div />,
overlay
)
}
} }
if (this.filterAnchorElement) { if (this.filterAnchorElement) {
@ -146,50 +147,64 @@ export default class BoardPage extends React.Component<Props, State> {
Utils.getElementById("modal") Utils.getElementById("modal")
) )
} else { } else {
ReactDOM.render(<div />, Utils.getElementById("modal")) const modal = document.getElementById("modal")
if (modal) {
ReactDOM.render(<div />, modal)
}
} }
return ( Utils.log(`BoardPage.render ${this.state.boardTree?.board?.title}`)
<div className='BoardPage'> return (
<WorkspaceComponent mutator={mutator} workspaceTree={this.workspaceTree} boardTree={this.state.boardTree} showView={this.showView} showCard={this.showCard} showBoard={this.showBoard} showFilter={this.showFilter} setSearchText={this.setSearchText} />, <div className='BoardPage'>
</div> <WorkspaceComponent
); mutator={mutator}
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) }} />
</div>
)
} }
private attachToBoard(boardId: string, viewId?: string) { private async attachToBoard(boardId: string, viewId?: string) {
const boardTree = new BoardTree(this.octo, boardId) Utils.log(`attachToBoard: ${boardId}`)
this.setState({
boardId,
viewId,
boardTree,
})
this.boardListener.open(boardId, (blockId: string) => { this.boardListener.open(boardId, (blockId: string) => {
console.log(`octoListener.onChanged: ${blockId}`) console.log(`octoListener.onChanged: ${blockId}`)
this.sync() this.sync(boardId)
}) })
this.sync() this.sync(boardId, viewId)
} }
async sync() { async sync(boardId: string = this.state.boardId, viewId: string | undefined = this.state.viewId) {
const { viewId, workspaceTree, boardTree } = this.state const { workspaceTree } = this.state
Utils.log(`sync start: ${boardId}`)
await workspaceTree.sync() await workspaceTree.sync()
if (boardTree) {
if (boardId) {
const boardTree = new BoardTree(this.octo, boardId)
await boardTree.sync() await boardTree.sync()
// Default to first view // Default to first view
if (!viewId) { if (!viewId) {
this.setState({viewId: boardTree.views[0].id}) viewId = boardTree.views[0].id
} }
boardTree.setActiveView(this.state.viewId) boardTree.setActiveView(viewId)
// TODO: Handle error (viewId not found) // TODO: Handle error (viewId not found)
this.setState({ this.setState({
viewId: boardTree.activeView.id ...this.state,
}) boardTree,
console.log(`sync complete... title: ${boardTree.board.title}`) viewId: boardTree.activeView.id
})
Utils.log(`sync complete: ${boardTree.board.id} (${boardTree.board.title})`)
} else {
this.forceUpdate()
} }
} }
@ -201,20 +216,22 @@ export default class BoardPage extends React.Component<Props, State> {
if (card) { if (card) {
const cardTree = new CardTree(this.octo, card.id) const cardTree = new CardTree(this.octo, card.id)
await cardTree.sync() await cardTree.sync()
this.shownCardTree = cardTree this.setState({...this.state, shownCardTree: cardTree})
this.cardListener = new OctoListener() this.cardListener = new OctoListener()
this.cardListener.open(card.id, async () => { this.cardListener.open(card.id, async () => {
await cardTree.sync() await cardTree.sync()
this.render() this.forceUpdate()
}) })
} else { } else {
this.shownCardTree = undefined this.setState({...this.state, shownCardTree: undefined})
} }
} }
showBoard(boardId: string) { showBoard(boardId: string) {
if (this.boardTree?.board?.id === boardId) { return } const { boardTree } = this.state
if (boardTree?.board?.id === boardId) { return }
const newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + `?id=${encodeURIComponent(boardId)}` const newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + `?id=${encodeURIComponent(boardId)}`
window.history.pushState({ path: newUrl }, "", newUrl) window.history.pushState({ path: newUrl }, "", newUrl)
@ -224,7 +241,7 @@ export default class BoardPage extends React.Component<Props, State> {
showView(viewId: string) { showView(viewId: string) {
this.state.boardTree.setActiveView(viewId) this.state.boardTree.setActiveView(viewId)
this.setState({viewId, boardTree: this.state.boardTree}) this.setState({ viewId, boardTree: this.state.boardTree })
const newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + `?id=${encodeURIComponent(this.state.boardId)}&v=${encodeURIComponent(viewId)}` const newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + `?id=${encodeURIComponent(this.state.boardId)}&v=${encodeURIComponent(viewId)}`
window.history.pushState({ path: newUrl }, "", newUrl) window.history.pushState({ path: newUrl }, "", newUrl)
} }
@ -234,6 +251,6 @@ export default class BoardPage extends React.Component<Props, State> {
} }
setSearchText(text?: string) { setSearchText(text?: string) {
this.boardTree.setSearchText(text) this.state.boardTree?.setSearchText(text)
} }
} }

View File

@ -73,7 +73,9 @@ hr {
overflow: auto; overflow: auto;
} }
#octo-tasks-app > #main { #octo-tasks-app #frame,
#octo-tasks-app #main,
#octo-tasks-app .BoardPage {
flex: 1 1 auto; flex: 1 1 auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;