Spaces:
Sleeping
Sleeping
| // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | |
| // See LICENSE.txt for license information. | |
| import {IntlShape} from 'react-intl' | |
| import {BoardView} from './blocks/boardView' | |
| import {Board, IPropertyTemplate} from './blocks/board' | |
| import {Card} from './blocks/card' | |
| import {Utils} from './utils' | |
| import {IAppWindow} from './types' | |
| import propsRegistry from './properties' | |
| declare let window: IAppWindow | |
| const hashSignToken = '___hash_sign___' | |
| class CsvExporter { | |
| static exportTableCsv(board: Board, activeView: BoardView, cards: Card[], intl: IntlShape, view?: BoardView): void { | |
| const viewToExport = view ?? activeView | |
| if (!viewToExport) { | |
| return | |
| } | |
| const rows = CsvExporter.generateTableArray(board, cards, viewToExport, intl) | |
| let csvContent = 'data:text/csv;charset=utf-8,' | |
| rows.forEach((row) => { | |
| const encodedRow = row.join(',') | |
| csvContent += encodedRow + '\r\n' | |
| }) | |
| const encodedUri = encodeURI(csvContent).replace(hashSignToken, '%23') | |
| const filename = `${Utils.sanitizeFilename(viewToExport.title || 'Untitled')}.csv` | |
| const link = document.createElement('a') | |
| link.style.display = 'none' | |
| link.setAttribute('href', encodedUri) | |
| link.setAttribute('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(encodedUri) | |
| } | |
| // TODO: Remove or reuse link | |
| } | |
| private static encodeText(text: string): string { | |
| return text.replace(/"/g, '""').replace(/#/g, hashSignToken) | |
| } | |
| private static generateTableArray(board: Board, cards: Card[], viewToExport: BoardView, intl: IntlShape): string[][] { | |
| const rows: string[][] = [] | |
| const visibleProperties = board.cardProperties.filter((template: IPropertyTemplate) => viewToExport.fields.visiblePropertyIds.includes(template.id)) | |
| if (viewToExport.fields.viewType === 'calendar' && | |
| viewToExport.fields.dateDisplayPropertyId && | |
| !viewToExport.fields.visiblePropertyIds.includes(viewToExport.fields.dateDisplayPropertyId)) { | |
| const dateDisplay = board.cardProperties.find((template: IPropertyTemplate) => viewToExport.fields.dateDisplayPropertyId === template.id) | |
| if (dateDisplay) { | |
| visibleProperties.push(dateDisplay) | |
| } | |
| } | |
| { | |
| // Header row | |
| const row: string[] = [intl.formatMessage({id: 'TableComponent.name', defaultMessage: 'Name'})] | |
| visibleProperties.forEach((template: IPropertyTemplate) => { | |
| row.push(template.name) | |
| }) | |
| rows.push(row) | |
| } | |
| cards.forEach((card) => { | |
| const row: string[] = [] | |
| row.push(`"${this.encodeText(card.title)}"`) | |
| visibleProperties.forEach((template: IPropertyTemplate) => { | |
| let propertyValue = card.fields.properties[template.id] | |
| const property = propsRegistry.get(template.type) | |
| if (property.type === 'createdBy') { | |
| propertyValue = card.createdBy | |
| } | |
| if (property.type === 'updatedBy') { | |
| propertyValue = card.modifiedBy | |
| } | |
| row.push(property.exportValue(propertyValue, card, template, intl)) | |
| }) | |
| rows.push(row) | |
| }) | |
| return rows | |
| } | |
| } | |
| export {CsvExporter} | |