diff --git a/dist/bundle.es.js b/dist/bundle.es.js index 9474043..c445cdc 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -1934,6 +1934,63 @@ function doDismissError() { }; } +// JSON parser +const parseJson = (data, filters = []) => { + const list = data.map(item => { + const temp = {}; + // Apply filters + Object.entries(item).forEach(([key, value]) => { + if (!filters.includes(key)) temp[key] = value; + }); + return temp; + }); + // Beautify JSON + return JSON.stringify(list, null, '\t'); +}; + +// CSV Parser +// No need for an external module: +// https://gist.github.com/btzr-io/55c3450ea3d709fc57540e762899fb85 +const parseCsv = (data, filters = []) => { + // Get items for header + const getHeaders = item => { + const list = []; + // Apply filters + Object.entries(item).forEach(([key]) => { + if (!filters.includes(key)) list.push(key); + }); + // return headers + return list.join(','); + }; + + // Get rows content + const getData = list => list.map(item => { + const row = []; + // Apply filters + Object.entries(item).forEach(([key, value]) => { + if (!filters.includes(key)) row.push(value); + }); + // return rows + return row.join(','); + }).join('\n'); + + // Return CSV string + return `${getHeaders(data[0])} \n ${getData(data)}`; +}; + +const parseData = (data, format, filters = []) => { + // Check for validation + const valid = data && data[0] && format; + // Pick a format + const formats = { + csv: list => parseCsv(list, filters), + json: list => parseJson(list, filters) + }; + + // Return parsed data: JSON || CSV + return valid && formats[format] ? formats[format](data) : undefined; +}; + const selectState = state => state.wallet || {}; const selectWalletState = selectState; @@ -2085,6 +2142,24 @@ const selectHasTransactions = reselect.createSelector(selectTransactionItems, tr const selectIsFetchingTransactions = reselect.createSelector(selectState, state => state.fetchingTransactions); +/** + * CSV of 'selectTransactionItems'. + */ +const selectTransactionsFile = reselect.createSelector(selectTransactionItems, transactions => { + if (!transactions || transactions.length === 0) { + // No data. + return undefined; + } + + const parsed = parseData(transactions, 'csv'); + if (!parsed) { + // Invalid data, or failed to parse. + return null; + } + + return parsed; +}); + const selectIsSendingSupport = reselect.createSelector(selectState, state => state.sendingSupport); const selectReceiveAddress = reselect.createSelector(selectState, state => state.receiveAddress); @@ -6793,6 +6868,7 @@ exports.selectTotalSupports = selectTotalSupports; exports.selectTransactionItems = selectTransactionItems; exports.selectTransactionListFilter = selectTransactionListFilter; exports.selectTransactionsById = selectTransactionsById; +exports.selectTransactionsFile = selectTransactionsFile; exports.selectTxoItemCount = selectTxoItemCount; exports.selectTxoPage = selectTxoPage; exports.selectTxoPageNumber = selectTxoPageNumber; diff --git a/src/index.js b/src/index.js index 24ec6fb..d412d83 100644 --- a/src/index.js +++ b/src/index.js @@ -285,6 +285,7 @@ export { selectSupportsByOutpoint, selectTotalSupports, selectTransactionItems, + selectTransactionsFile, selectRecentTransactions, selectHasTransactions, selectIsFetchingTransactions, diff --git a/src/redux/selectors/wallet.js b/src/redux/selectors/wallet.js index 89316d7..0eb5316 100644 --- a/src/redux/selectors/wallet.js +++ b/src/redux/selectors/wallet.js @@ -2,6 +2,7 @@ import { createSelector } from 'reselect'; import * as TRANSACTIONS from 'constants/transaction_types'; import { PAGE_SIZE, LATEST_PAGE_SIZE } from 'constants/transaction_list'; import { selectClaimIdsByUri } from 'redux/selectors/claims'; +import parseData from 'util/parse-data'; export const selectState = state => state.wallet || {}; export const selectWalletState = selectState; @@ -267,6 +268,27 @@ export const selectIsFetchingTransactions = createSelector( state => state.fetchingTransactions ); +/** + * CSV of 'selectTransactionItems'. + */ +export const selectTransactionsFile = createSelector( + selectTransactionItems, + transactions => { + if (!transactions || transactions.length === 0) { + // No data. + return undefined; + } + + const parsed = parseData(transactions, 'csv'); + if (!parsed) { + // Invalid data, or failed to parse. + return null; + } + + return parsed; + } +); + export const selectIsSendingSupport = createSelector( selectState, state => state.sendingSupport diff --git a/src/util/parse-data.js b/src/util/parse-data.js new file mode 100644 index 0000000..83f9a1c --- /dev/null +++ b/src/util/parse-data.js @@ -0,0 +1,61 @@ +// JSON parser +const parseJson = (data, filters = []) => { + const list = data.map(item => { + const temp = {}; + // Apply filters + Object.entries(item).forEach(([key, value]) => { + if (!filters.includes(key)) temp[key] = value; + }); + return temp; + }); + // Beautify JSON + return JSON.stringify(list, null, '\t'); +}; + +// CSV Parser +// No need for an external module: +// https://gist.github.com/btzr-io/55c3450ea3d709fc57540e762899fb85 +const parseCsv = (data, filters = []) => { + // Get items for header + const getHeaders = item => { + const list = []; + // Apply filters + Object.entries(item).forEach(([key]) => { + if (!filters.includes(key)) list.push(key); + }); + // return headers + return list.join(','); + }; + + // Get rows content + const getData = list => + list + .map(item => { + const row = []; + // Apply filters + Object.entries(item).forEach(([key, value]) => { + if (!filters.includes(key)) row.push(value); + }); + // return rows + return row.join(','); + }) + .join('\n'); + + // Return CSV string + return `${getHeaders(data[0])} \n ${getData(data)}`; +}; + +const parseData = (data, format, filters = []) => { + // Check for validation + const valid = data && data[0] && format; + // Pick a format + const formats = { + csv: list => parseCsv(list, filters), + json: list => parseJson(list, filters), + }; + + // Return parsed data: JSON || CSV + return valid && formats[format] ? formats[format](data) : undefined; +}; + +export default parseData;