1
0
mirror of https://github.com/mattermost/focalboard.git synced 2025-03-11 14:09:34 +02:00

Fixing some things

This commit is contained in:
Jesús Espino 2023-01-24 19:57:04 +01:00
parent dd82913e39
commit dbfde1a238
2 changed files with 116 additions and 98 deletions

View File

@ -1,14 +1,17 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useEffect} from 'react'
import React, {useEffect, useCallback} from 'react'
import {Provider as ReduxProvider} from 'react-redux'
import {IntlProvider} from 'react-intl'
import {IntlProvider, useIntl} from 'react-intl'
import {DndProvider} from 'react-dnd'
import {HTML5Backend} from 'react-dnd-html5-backend'
import {TouchBackend} from 'react-dnd-touch-backend'
import store from '../../../webapp/src/store'
import {updateCards, getRHSCardID, getRHSCard, getRHSBoardID} from '../../../webapp/src/store/cards'
import {getRHSCard, getRHSBoardID} from '../../../webapp/src/store/cards'
import {getCardAttachments} from '../../../webapp/src/store/attachments'
import mutator from '../../../webapp/src/mutator'
import {getBoard} from '../../../webapp/src/store/boards'
import {Block} from '../../../webapp/src/blocks/block'
import {fetchMe, getMe} from '../../../webapp/src/store/users'
@ -20,11 +23,10 @@ import {loadBoardData} from '../../../webapp/src/store/initialLoad'
import {useAppSelector} from '../../../webapp/src/store/hooks'
import {getMessages} from '../../../webapp/src/i18n'
import CardDetail from '../../../webapp/src/components/cardDetail/cardDetail'
import {sendFlashMessage} from '../../../webapp/src/components/flashMessages'
import useConnectToBoard from '../../../webapp/src/hooks/connectToBoard'
import {Utils} from '../../../webapp/src/utils'
import octoClient from '../../../webapp/src/octoClient'
import '../../../webapp/src/styles/variables.scss'
import '../../../webapp/src/styles/main.scss'
import '../../../webapp/src/styles/labels.scss'
@ -40,8 +42,9 @@ const RHSCardContent = () => {
const views = useAppSelector(getViewsByBoard)
const comments = useAppSelector(getCardComments(card?.id))
const contents = useAppSelector(getCardContents(card?.id))
const language = useAppSelector<string>(getLanguage)
const activeView = views[boardID] && views[boardID][0]
const attachments = useAppSelector(getCardAttachments(card.id))
const intl = useIntl()
useEffect(() => {
if (boardID) {
@ -51,34 +54,63 @@ const RHSCardContent = () => {
}
}, [boardID])
const deleteBlock = useCallback(async (block: Block) => {
if (!card) {
return
}
const description = intl.formatMessage({id: 'AttachmentBlock.DeleteAction', defaultMessage: 'delete'})
await mutator.deleteBlock(block, description)
sendFlashMessage({content: intl.formatMessage({id: 'AttachmentBlock.delete', defaultMessage: 'Attachment Deleted Successfully.'}), severity: 'normal'})
}, [card?.boardId, card?.id, card?.fields.contentOrder])
// TODO: Check the permissions here
const readonly = false
useConnectToBoard(store.dispatch, '', me?.id || '', boardID || '', Boolean(readonly), boardID || '')
useConnectToBoard(store.dispatch, me?.id || '', boardID || '', Boolean(readonly), boardID || '')
if (!board || !card || !activeView) {
return null
}
return (
<CardDetail
board={board}
activeView={activeView}
views={views[boardID]}
cards={[]}
card={card}
comments={comments}
contents={contents}
readonly={readonly}
attachments={attachments}
onDelete={deleteBlock}
addAttachment={() => {}}
onClose={() => {}}
/>
)
}
const RHSCardWithIntl = () => {
const language = useAppSelector<string>(getLanguage)
return (
<IntlProvider
locale={language.split(/[_]/)[0]}
messages={getMessages(language)}
>
<CardDetail
board={board}
activeView={activeView}
views={views[boardID]}
cards={[]}
card={card}
comments={comments}
contents={contents}
readonly={readonly}
attachments={[]}
onDelete={() => {}}
onClose={() => {}}
addAttachment={() => {}}
/>
<div
className='focalboard-body RHSCard'
onKeyDown={(e: React.KeyboardEvent) => e.stopPropagation()}
onKeyPress={(e: React.KeyboardEvent) => e.stopPropagation()}
onKeyUp={(e: React.KeyboardEvent) => e.stopPropagation()}
>
{/* TODO: Remove this hack to avoid the capture of the cursor by the create post component */}
<div
className='channel-switch-modal'
style={{display: 'none'}}
/>
<RHSCardContent/>
</div>
</IntlProvider>
)
}
@ -87,19 +119,7 @@ const RHSCard = () => {
return (
<ReduxProvider store={store}>
<DndProvider backend={Utils.isMobile() ? TouchBackend : HTML5Backend}>
<div
className='focalboard-body RHSCard'
onKeyDown={(e: React.KeyboardEvent) => e.stopPropagation()}
onKeyPress={(e: React.KeyboardEvent) => e.stopPropagation()}
onKeyUp={(e: React.KeyboardEvent) => e.stopPropagation()}
>
{/* TODO: Remove this hack to avoid the capture of the cursor by the create post component */}
<div
className='channel-switch-modal'
style={{display: 'none'}}
/>
<RHSCardContent/>
</div>
<RHSCardWithIntl/>
</DndProvider>
</ReduxProvider>
)

View File

@ -1,87 +1,89 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {useEffect, useState} from 'react'
import {useMemo} from 'react'
import {batch} from 'react-redux'
import {Block} from '../blocks/block'
import {ContentBlock} from '../blocks/contentBlock'
import {AttachmentBlock} from '../blocks/attachmentBlock'
import {Utils} from '../utils'
import {CommentBlock} from '../blocks/commentBlock'
import {Board} from '../blocks/board'
import {Board, BoardMember} from '../blocks/board'
import {Card} from '../blocks/card'
import {BoardView} from '../blocks/boardView'
import wsClient, {Subscription, WSClient} from '../wsclient'
import {updateBoards} from '../store/boards'
import {Subscription, WSClient} from '../wsclient'
import {
updateBoards,
updateMembersEnsuringBoardsAndUsers,
fetchBoardMembers,
addMyBoardMemberships,
} from '../store/boards'
import {updateViews} from '../store/views'
import {updateCards} from '../store/cards'
import {updateContents} from '../store/contents'
import {updateComments} from '../store/comments'
import {updateAttachments} from '../store/attachments'
import {followBlock, unfollowBlock} from '../store/users'
import {initialLoad, initialReadOnlyLoad} from '../store/initialLoad'
import {Constants} from '../constants'
const websocketTimeoutForBanner = 5000
import {useWebsockets} from './websockets'
export default function useConnectToBoard(dispatch: any, readToken: string, myID: string, teamId: string|undefined, readonly: boolean, boardId: string): void {
const [websocketClosed, setWebsocketClosed] = useState(false)
useEffect(() => {
let loadAction: any = initialLoad /* eslint-disable-line @typescript-eslint/no-explicit-any */
let token = localStorage.getItem('focalboardSessionId') || ''
export default function useConnectToBoard(dispatch: any, myID: string, teamId: string, readonly: boolean, boardId: string): void {
const loadAction: (boardId: string) => any = useMemo(() => {
if (readonly) {
loadAction = initialReadOnlyLoad
token = token || readToken || ''
return initialReadOnlyLoad
}
return initialLoad
}, [readonly])
dispatch(loadAction(boardId))
useWebsockets(teamId, (wsClient: WSClient) =>{
const incrementalBlockUpdate = (_: WSClient, blocks: Block[]) => {
const teamBlocks = blocks
let subscribedToTeam = false
if (wsClient.state === 'open') {
wsClient.authenticate(token)
wsClient.subscribeToTeam(teamId || '0')
subscribedToTeam = true
}
const incrementalUpdateBoard = (_: WSClient, boards: Board[]) => {
// only takes into account the boards that belong to the team
const teamBoards = boards.filter((b: Board) => b.teamId === '0' || b.teamId === teamId)
dispatch(updateBoards(teamBoards.filter((b: Board) => b.deleteAt !== 0)))
}
const incrementalUpdateBlock = (_: WSClient, blocks: Block[]) => {
batch(() => {
dispatch(updateViews(blocks.filter((b: Block) => b.type === 'view' || b.deleteAt !== 0) as BoardView[]))
dispatch(updateCards(blocks.filter((b: Block) => b.type === 'card' || b.deleteAt !== 0) as Card[]))
dispatch(updateComments(blocks.filter((b: Block) => b.type === 'comment' || b.deleteAt !== 0) as CommentBlock[]))
dispatch(updateContents(blocks.filter((b: Block) => b.type !== 'card' && b.type !== 'view' && b.type !== 'board' && b.type !== 'comment') as ContentBlock[]))
dispatch(updateViews(teamBlocks.filter((b: Block) => b.type === 'view' || b.deleteAt !== 0) as BoardView[]))
dispatch(updateCards(teamBlocks.filter((b: Block) => b.type === 'card' || b.deleteAt !== 0) as Card[]))
dispatch(updateComments(teamBlocks.filter((b: Block) => b.type === 'comment' || b.deleteAt !== 0) as CommentBlock[]))
dispatch(updateAttachments(teamBlocks.filter((b: Block) => b.type === 'attachment' || b.deleteAt !== 0) as AttachmentBlock[]))
dispatch(updateContents(teamBlocks.filter((b: Block) => b.type !== 'card' && b.type !== 'view' && b.type !== 'board' && b.type !== 'comment' && b.type !== 'attachment') as ContentBlock[]))
})
}
let timeout: ReturnType<typeof setTimeout>
const updateWebsocketState = (_: WSClient, newState: 'init'|'open'|'close'): void => {
if (newState === 'open') {
const newToken = localStorage.getItem('focalboardSessionId') || ''
wsClient.authenticate(newToken)
wsClient.subscribeToTeam(teamId || '0')
subscribedToTeam = true
}
const incrementalBoardUpdate = (_: WSClient, boards: Board[]) => {
// only takes into account the entities that belong to the team or the user boards
const teamBoards = boards.filter((b: Board) => b.teamId === Constants.globalTeamId || b.teamId === teamId)
const activeBoard = teamBoards.find((b: Board) => b.id === boardId)
dispatch(updateBoards(teamBoards))
if (timeout) {
clearTimeout(timeout)
}
if (newState === 'close') {
timeout = setTimeout(() => {
setWebsocketClosed(true)
subscribedToTeam = false
}, websocketTimeoutForBanner)
} else {
setWebsocketClosed(false)
if (activeBoard) {
dispatch(fetchBoardMembers({
teamId,
boardId: boardId,
}))
}
}
wsClient.addOnChange(incrementalUpdateBoard, 'board')
wsClient.addOnChange(incrementalUpdateBlock, 'block')
wsClient.addOnReconnect(() => dispatch(loadAction(boardId)))
wsClient.addOnStateChange(updateWebsocketState)
const incrementalBoardMemberUpdate = (_: WSClient, members: BoardMember[]) => {
dispatch(updateMembersEnsuringBoardsAndUsers(members))
if (myID) {
const myBoardMemberships = members.filter((boardMember) => boardMember.userId === myID)
dispatch(addMyBoardMemberships(myBoardMemberships))
}
}
const dispatchLoadAction = () => {
dispatch(loadAction(boardId))
}
Utils.log('useWEbsocket adding onChange handler')
wsClient.addOnChange(incrementalBlockUpdate, 'block')
wsClient.addOnChange(incrementalBoardUpdate, 'board')
wsClient.addOnChange(incrementalBoardMemberUpdate, 'boardMembers')
wsClient.addOnReconnect(dispatchLoadAction)
wsClient.setOnFollowBlock((_: WSClient, subscription: Subscription): void => {
if (subscription.subscriberId === myID) {
dispatch(followBlock(subscription))
@ -92,17 +94,13 @@ export default function useConnectToBoard(dispatch: any, readToken: string, myID
dispatch(unfollowBlock(subscription))
}
})
return () => {
if (timeout) {
clearTimeout(timeout)
}
if (subscribedToTeam) {
wsClient.unsubscribeToTeam(teamId || '0')
}
wsClient.removeOnChange(incrementalUpdateBlock, 'block')
wsClient.removeOnChange(incrementalUpdateBoard, 'board')
wsClient.removeOnReconnect(() => dispatch(loadAction(boardId)))
wsClient.removeOnStateChange(updateWebsocketState)
Utils.log('useWebsocket cleanup')
wsClient.removeOnChange(incrementalBlockUpdate, 'block')
wsClient.removeOnChange(incrementalBoardUpdate, 'board')
wsClient.removeOnChange(incrementalBoardMemberUpdate, 'boardMembers')
wsClient.removeOnReconnect(dispatchLoadAction)
}
}, [teamId, readonly, boardId, myID])
}