main

mattermost/focalboard

Last updated at: 29/12/2023 09:46

cardDetailContext.tsx

TLDR

The cardDetailContext.tsx file in the Demo Projects project is a TypeScript file that contains the implementation of a context provider and hooks for managing the details of a card.

Methods

useCardDetailContext

This method is a custom hook that allows components to access the card detail context. It returns the current card detail context value. If the context is not available, it throws an error.

addBlock

This method is responsible for adding a new block to the card details. It takes parameters for the content handler, index, and auto addition flag. It creates a new block using the content handler, updates its parent and board IDs, and performs the necessary mutations using the mutator module. It also updates the last added block state.

deleteBlock

This method is responsible for deleting a block from the card details. It takes parameters for the block and index. It removes the block from the content order of the card and performs the necessary mutations using the mutator module.

Classes

None

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {createContext, ReactElement, ReactNode, useContext, useMemo, useState, useCallback} from 'react'

import {useIntl} from 'react-intl'

import {Block} from '../../blocks/block'
import {Card} from '../../blocks/card'
import {ContentHandler} from '../content/contentRegistry'
import octoClient from '../../octoClient'
import mutator from '../../mutator'

export type AddedBlock = {
    id: string
    autoAdded: boolean
}

export type CardDetailContextType = {
    card: Card
    lastAddedBlock: AddedBlock
    addBlock: (handler: ContentHandler, index: number, auto: boolean) => void
    deleteBlock: (block: Block, index: number) => void
}

export const CardDetailContext = createContext<CardDetailContextType | null>(null)

export function useCardDetailContext(): CardDetailContextType {
    const cardDetailContext = useContext(CardDetailContext)
    if (!cardDetailContext) {
        throw new Error('CardDetailContext is not available!')
    }
    return cardDetailContext
}

type CardDetailProps = {
    card: Card
    children: ReactNode
}

export const CardDetailProvider = (props: CardDetailProps): ReactElement => {
    const intl = useIntl()
    const [lastAddedBlock, setLastAddedBlock] = useState<AddedBlock>({
        id: '',
        autoAdded: false,
    })
    const {card} = props
    const addBlock = useCallback(async (handler: ContentHandler, index: number, auto: boolean) => {
        const block = await handler.createBlock(card.boardId, intl)
        block.parentId = card.id
        block.boardId = card.boardId
        const typeName = handler.getDisplayText(intl)
        const description = intl.formatMessage({id: 'ContentBlock.addElement', defaultMessage: 'add {type}'}, {type: typeName})
        await mutator.performAsUndoGroup(async () => {
            const afterRedo = async (newBlock: Block) => {
                const contentOrder = card.fields.contentOrder.slice()
                contentOrder.splice(index, 0, newBlock.id)
                await octoClient.patchBlock(card.boardId, card.id, {updatedFields: {contentOrder}})
            }

            const beforeUndo = async () => {
                const contentOrder = card.fields.contentOrder.slice()
                await octoClient.patchBlock(card.boardId, card.id, {updatedFields: {contentOrder}})
            }

            const insertedBlock = await mutator.insertBlock(block.boardId, block, description, afterRedo, beforeUndo)
            setLastAddedBlock({id: insertedBlock.id, autoAdded: auto})
        })
    }, [card.boardId, card.id, card.fields.contentOrder])

    const deleteBlock = useCallback(async (block: Block, index: number) => {
        const contentOrder = card.fields.contentOrder.slice()
        contentOrder.splice(index, 1)
        const description = intl.formatMessage({id: 'ContentBlock.DeleteAction', defaultMessage: 'delete'})
        await mutator.performAsUndoGroup(async () => {
            await mutator.deleteBlock(block, description)
            await mutator.changeCardContentOrder(card.boardId, card.id, card.fields.contentOrder, contentOrder, description)
        })
    }, [card.boardId, card.id, card.fields.contentOrder])

    const contextValue = useMemo(() => ({
        card,
        lastAddedBlock,
        addBlock,
        deleteBlock,
    }), [card, lastAddedBlock, addBlock, deleteBlock])

    return (
        <CardDetailContext.Provider value={contextValue}>
            {props.children}
        </CardDetailContext.Provider>
    )
}