/** * A mixin that can be used to copy and paste row values. */ import { getRichClipboard, setRichClipboard, LOCAL_STORAGE_CLIPBOARD_KEY, } from '@baserow/modules/database/utils/clipboard' const PAPA_CONFIG = { delimiter: '\t', } export default { methods: { prepareSelectionForCopy(fields, rows) { const textData = [] const jsonData = [] for (const row of rows) { const text = fields.map((field) => this.$registry .get('field', field.type) .prepareValueForCopy(field, row['field_' + field.id]) ) const json = fields.map((field) => this.$registry .get('field', field.type) .prepareRichValueForCopy(field, row['field_' + field.id]) ) textData.push(text) jsonData.push(json) } const text = this.$papa.unparse(textData, PAPA_CONFIG) try { localStorage.setItem( LOCAL_STORAGE_CLIPBOARD_KEY, JSON.stringify({ text, json: jsonData }) ) return text } catch (e) { // If the local storage is full then we just ignore it. // @TODO: Should we warn the user? return '' } }, async copySelectionToClipboard(selectionPromise) { // Firefox does not have the ClipboardItem type enabled by default, so we // need to check if it is available. Safari instead, needs the // ClipboardItem type to save async data to the clipboard. if (typeof ClipboardItem !== 'undefined') { navigator.clipboard.write([ new ClipboardItem({ 'text/plain': selectionPromise.then( ([fields, rows]) => new Blob([this.prepareSelectionForCopy(fields, rows)], { type: 'text/plain', }) ), }), ]) } else { const text = await selectionPromise.then(([fields, rows]) => this.prepareSelectionForCopy(fields, rows) ) if (typeof navigator.clipboard?.writeText !== 'undefined') { navigator.clipboard.writeText(text) } else { setRichClipboard({ 'text/plain': text }) } } }, async extractClipboardData(event) { const { textRawData, jsonRawData } = await getRichClipboard(event) const { data: textData } = await this.$papa.parsePromise( textRawData, PAPA_CONFIG ) let jsonData = null if (jsonRawData != null) { // Check if we have an array of arrays with At least one row with at least // one row with a value Otherwise the paste is empty if ( Array.isArray(jsonRawData) && jsonRawData.length === textData.length && jsonRawData.every((row) => Array.isArray(row)) && jsonRawData.some((row) => row.length > 0) ) { jsonData = jsonRawData } } return [textData, jsonData] }, }, }