diff --git a/webapp/src/app.tsx b/webapp/src/app.tsx index ac56a4bc8..18165db2b 100644 --- a/webapp/src/app.tsx +++ b/webapp/src/app.tsx @@ -78,7 +78,7 @@ const App = React.memo((): JSX.Element => { - + {loggedIn === false && } {loggedIn === true && } @@ -86,7 +86,7 @@ const App = React.memo((): JSX.Element => { { if (loggedIn === false) { let redirectUrl = '/' + Utils.buildURL(`/workspace/${match.params.workspaceId}/`) @@ -109,7 +109,7 @@ const App = React.memo((): JSX.Element => { > - + {loggedIn === false && } {loggedIn === true && } diff --git a/webapp/src/components/centerPanel.tsx b/webapp/src/components/centerPanel.tsx index 64387e692..5505c0a69 100644 --- a/webapp/src/components/centerPanel.tsx +++ b/webapp/src/components/centerPanel.tsx @@ -37,10 +37,11 @@ type Props = { readonly: boolean addCard: (card: Card) => void addTemplate: (template: Card) => void + shownCardId?: string + showCard: (cardId?: string) => void } type State = { - shownCardId?: string selectedCardIds: string[] cardIdToFocusOnRender: string } @@ -77,10 +78,6 @@ class CenterPanel extends React.Component { } } - componentDidMount(): void { - this.showCardInUrl() - } - constructor(props: Props) { super(props) this.state = { @@ -93,14 +90,6 @@ class CenterPanel extends React.Component { return true } - private showCardInUrl() { - const queryString = new URLSearchParams(window.location.search) - const cardId = queryString.get('c') || undefined - if (cardId !== this.state.shownCardId) { - this.setState({shownCardId: cardId}) - } - } - render(): JSX.Element { const {groupByProperty, activeView, board, views, cards} = this.props const {visible: visibleGroups, hidden: hiddenGroups} = this.getVisibleAndHiddenGroups(cards, activeView.fields.visibleOptionIds, activeView.fields.hiddenOptionIds, groupByProperty) @@ -117,15 +106,15 @@ class CenterPanel extends React.Component { keyName='ctrl+d,del,esc,backspace' onKeyDown={this.keydownHandler} /> - {this.state.shownCardId && + {this.props.shownCardId && this.showCard(undefined)} showCard={(cardId) => this.showCard(cardId)} readonly={this.props.readonly} @@ -316,8 +305,8 @@ class CenterPanel extends React.Component { } private showCard = (cardId?: string) => { - Utils.replaceUrlQueryParam('c', cardId) - this.setState({selectedCardIds: [], shownCardId: cardId}) + this.setState({selectedCardIds: []}) + this.props.showCard(cardId) } private async deleteSelectedCards() { diff --git a/webapp/src/components/workspace.tsx b/webapp/src/components/workspace.tsx index ed4b81f6a..08788002b 100644 --- a/webapp/src/components/workspace.tsx +++ b/webapp/src/components/workspace.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React from 'react' -import {useRouteMatch} from 'react-router-dom' +import React, {useCallback} from 'react' +import {generatePath, useRouteMatch, useHistory} from 'react-router-dom' import {FormattedMessage} from 'react-intl' import {getCurrentBoard} from '../store/boards' @@ -19,12 +19,19 @@ type Props = { } function CenterContent(props: Props) { - const match = useRouteMatch<{boardId: string, viewId: string}>() + const match = useRouteMatch<{boardId: string, viewId: string, cardId?: string}>() const board = useAppSelector(getCurrentBoard) const cards = useAppSelector(getCurrentViewCardsSortedFilteredAndGrouped) const activeView = useAppSelector(getView(match.params.viewId)) const views = useAppSelector(getCurrentBoardViews) const groupByProperty = useAppSelector(getCurrentViewGroupBy) + const history = useHistory() + + const showCard = useCallback((cardId?: string) => { + const params = {...match.params, cardId} + const newPath = generatePath(match.path, params) + history.push(newPath) + }, [match, history]) if (board && activeView) { let property = groupByProperty @@ -36,6 +43,8 @@ function CenterContent(props: Props) { readonly={props.readonly} board={board} cards={cards} + shownCardId={match.params.cardId} + showCard={showCard} activeView={activeView} groupByProperty={property} views={views} diff --git a/webapp/src/pages/boardPage.tsx b/webapp/src/pages/boardPage.tsx index 37cfd6bf6..6622afb0a 100644 --- a/webapp/src/pages/boardPage.tsx +++ b/webapp/src/pages/boardPage.tsx @@ -42,7 +42,7 @@ const BoardPage = (props: Props) => { const dispatch = useAppDispatch() const history = useHistory() - const match = useRouteMatch<{boardId: string, viewId: string, workspaceId?: string}>() + const match = useRouteMatch<{boardId: string, viewId: string, cardId?: string, workspaceId?: string}>() const [websocketClosed, setWebsocketClosed] = useState(false) // TODO: Make this less brittle. This only works because this is the root render function @@ -53,20 +53,37 @@ const BoardPage = (props: Props) => { // Backward compatibility: This can be removed in the future, this is for // transform the old query params into routes useEffect(() => { - const queryString = new URLSearchParams(window.location.search) - const queryBoardId = queryString.get('id') - const queryViewId = queryString.get('v') - if (queryBoardId) { - const params = {...match.params, boardId: queryBoardId} - if (queryViewId) { - params.viewId = queryViewId - } - const newPath = generatePath(match.path, params) - history.replace(newPath) - } }, []) useEffect(() => { + // Backward compatibility: This can be removed in the future, this is for + // transform the old query params into routes + const queryString = new URLSearchParams(history.location.search) + const queryBoardId = queryString.get('id') + const params = {...match.params} + let needsRedirect = false + if (queryBoardId) { + params.boardId = queryBoardId + needsRedirect = true + } + const queryViewId = queryString.get('v') + if (queryViewId) { + params.viewId = queryViewId + needsRedirect = true + } + const queryCardId = queryString.get('c') + if (queryCardId) { + params.cardId = queryCardId + needsRedirect = true + } + if (needsRedirect) { + const newPath = generatePath(match.path, params) + history.replace(newPath) + return + } + + // Backward compatibility end + const boardId = match.params.boardId const viewId = match.params.viewId @@ -96,7 +113,7 @@ const BoardPage = (props: Props) => { UserSettings.lastViewId = viewId || '' dispatch(setCurrentBoard(boardId || '')) dispatch(setCurrentView(viewId || '')) - }, [match.params.boardId, match.params.viewId, history, boardViews]) + }, [match.params.boardId, match.params.viewId, boardViews]) useEffect(() => { Utils.setFavicon(board?.fields.icon) @@ -119,7 +136,7 @@ const BoardPage = (props: Props) => { let token = localStorage.getItem('focalboardSessionId') || '' if (props.readonly) { loadAction = initialReadOnlyLoad - const queryString = new URLSearchParams(window.location.search) + const queryString = new URLSearchParams(history.location.search) token = token || queryString.get('r') || '' } dispatch(loadAction(match.params.boardId))