main

mattermost/focalboard

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

archiver.ts

TLDR

This file, archiver.ts, contains the implementation of the Archiver class along with several methods related to exporting and importing board and full archives. The Archiver class provides methods for exporting a board archive and a full archive, as well as importing a full archive. Additionally, there is a method for checking the validity of a block.

Methods

exportBoardArchive

This method is a static asynchronous function that exports a board archive. It takes a Board object as a parameter and returns a promise that resolves to void.

exportFullArchive

This method is a static asynchronous function that exports a full archive. It takes a teamID (string) as a parameter and returns a promise that resolves to void.

exportArchive

This is a private static function that is responsible for exporting an archive. It takes a promise as a parameter and does not return anything. This function is called by the exportBoardArchive and exportFullArchive methods.

importArchiveFromFile

This is a private static asynchronous function that imports a full archive from a file. It takes a File object as a parameter and returns a promise that resolves to void.

isValidBlock

This is a static function that checks the validity of a Block. It takes a Block object as a parameter and returns a boolean value indicating whether the block is valid or not.

importFullArchive

This is a static function that imports a full archive. It provides an optional onComplete callback function. This method allows the user to select a file for importing the archive.

Classes

Archiver

The Archiver class provides methods for exporting and importing archives. It contains static methods for exporting a board archive and a full archive, as well as importing a full archive. Additionally, it has a static method for checking the validity of a block.

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {IAppWindow} from './types'
import {Block} from './blocks/block'
import {Board} from './blocks/board'
import mutator from './mutator'
import {Utils} from './utils'

declare let window: IAppWindow

class Archiver {
    static async exportBoardArchive(board: Board): Promise<void> {
        this.exportArchive(mutator.exportBoardArchive(board.id))
    }

    static async exportFullArchive(teamID: string): Promise<void> {
        this.exportArchive(mutator.exportFullArchive(teamID))
    }

    private static exportArchive(prom: Promise<Response>): void {
        // TODO:  don't download whole archive before presenting SaveAs dialog.
        prom.then((response) => {
            response.blob().
                then((blob) => {
                    const link = document.createElement('a')
                    link.style.display = 'none'

                    const date = new Date()
                    const filename = `archive-${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}.boardarchive`

                    const file = new Blob([blob], {type: 'application/octet-stream'})
                    link.href = URL.createObjectURL(file)
                    link.download = filename
                    document.body.appendChild(link)		// FireFox support

                    link.click()

                    // TODO: Review if this is needed in the future, this is to fix the problem with linux webview links
                    if (window.openInNewBrowser) {
                        window.openInNewBrowser(link.href)
                    }

                    // TODO: Remove or reuse link and revolkObjectURL to avoid memory leak
                })
        })
    }

    private static async importArchiveFromFile(file: File): Promise<void> {
        const response = await mutator.importFullArchive(file)
        if (response.status !== 200) {
            Utils.log('ERROR importing archive: ' + response.text())
        }
    }

    static isValidBlock(block: Block): boolean {
        if (!block.id || !block.boardId) {
            return false
        }

        return true
    }

    static importFullArchive(onComplete?: () => void): void {
        const input = document.createElement('input')
        input.type = 'file'
        input.accept = '.boardarchive'
        input.onchange = async () => {
            const file = input.files && input.files[0]
            if (file) {
                await Archiver.importArchiveFromFile(file)
            }

            onComplete?.()
        }

        input.style.display = 'none'
        document.body.appendChild(input)
        input.click()

        // TODO: Remove or reuse input
    }
}

export {Archiver}