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:
parent
3c76e099c3
commit
3cfad9d027
@ -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>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -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 (
|
||||||
|
@ -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: {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user