Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/components/ECharts/AreaChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import * as echarts from 'echarts/core'
import { CSVDownloadButton } from '~/components/ButtonStyled/CsvButton'
import { SelectWithCombobox } from '~/components/SelectWithCombobox'
import { useDarkModeManager } from '~/contexts/LocalStorage'
import { download, slug, toNiceCsvDate } from '~/utils'
import { slug, toNiceCsvDate } from '~/utils'
import { useCSVDownload } from '~/hooks/useCSVDownload'
import type { IChartProps } from '../types'
import { useDefaults } from '../useDefaults'
import { stringToColour } from '../utils'
Expand Down Expand Up @@ -34,6 +35,7 @@ export default function AreaChart({
...props
}: IChartProps) {
const id = useId()
const { downloadCSV: downloadCSVFromHook, isLoading: isCSVLoading } = useCSVDownload()

const [legendOptions, setLegendOptions] = useState(customLegendOptions)

Expand Down Expand Up @@ -337,26 +339,32 @@ export default function AreaChart({
<CSVDownloadButton
onClick={() => {
try {
let rows = []
let headers: string[]
let rows: any[][]

if (!chartsStack || chartsStack.length === 0) {
rows = [['Timestamp', 'Date', 'Value']]
headers = ['Timestamp', 'Date', 'Value']
rows = []
for (const [date, value] of chartData ?? []) {
rows.push([date, toNiceCsvDate(date), value])
}
} else {
rows = [['Timestamp', 'Date', ...chartsStack]]
headers = ['Timestamp', 'Date', ...chartsStack]
rows = []
for (const item of chartData ?? []) {
const { date, ...rest } = item
rows.push([date, toNiceCsvDate(date), ...chartsStack.map((stack) => rest[stack] ?? '')])
}
}

const Mytitle = title ? slug(title) : 'data'
const filename = `area-chart-${Mytitle}-${new Date().toISOString().split('T')[0]}.csv`
download(filename, rows.map((r) => r.join(',')).join('\n'))
downloadCSVFromHook(filename, [headers, ...rows])
} catch (error) {
console.error('Error generating CSV:', error)
}
}}
isLoading={isCSVLoading}
smol
/>
)}
Expand Down
18 changes: 13 additions & 5 deletions src/components/ECharts/BarChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import * as echarts from 'echarts/core'
import { CSVDownloadButton } from '~/components/ButtonStyled/CsvButton'
import { SelectWithCombobox } from '~/components/SelectWithCombobox'
import { useDarkModeManager } from '~/contexts/LocalStorage'
import { download, slug, toNiceCsvDate } from '~/utils'
import { slug, toNiceCsvDate } from '~/utils'
import { useCSVDownload } from '~/hooks/useCSVDownload'
import type { IBarChartProps } from '../types'
import { useDefaults } from '../useDefaults'
import { stringToColour } from '../utils'
Expand All @@ -28,6 +29,7 @@ export default function BarChart({
customComponents
}: IBarChartProps) {
const id = useId()
const { downloadCSV: downloadCSVFromHook, isLoading: isCSVLoading } = useCSVDownload()

const [legendOptions, setLegendOptions] = useState(customLegendOptions ? [...customLegendOptions] : [])

Expand Down Expand Up @@ -236,26 +238,32 @@ export default function BarChart({
<CSVDownloadButton
onClick={() => {
try {
let rows = []
let headers: string[]
let rows: any[][]

if (!stackKeys || stackKeys.length === 0) {
rows = [['Timestamp', 'Date', 'Value']]
headers = ['Timestamp', 'Date', 'Value']
rows = []
for (const [date, value] of chartData ?? []) {
rows.push([date, toNiceCsvDate(date), value])
}
} else {
rows = [['Timestamp', 'Date', ...selectedStacks]]
headers = ['Timestamp', 'Date', ...selectedStacks]
rows = []
for (const item of chartData ?? []) {
const { date, ...rest } = item
rows.push([date, toNiceCsvDate(date), ...selectedStacks.map((stack) => rest[stack] ?? '')])
}
}

const Mytitle = title ? slug(title) : 'data'
const filename = `bar-chart-${Mytitle}-${new Date().toISOString().split('T')[0]}.csv`
download(filename, rows.map((r) => r.join(',')).join('\n'))
downloadCSVFromHook(filename, [headers, ...rows])
} catch (error) {
console.error('Error generating CSV:', error)
}
}}
isLoading={isCSVLoading}
smol
/>
)}
Expand Down
71 changes: 47 additions & 24 deletions src/components/ECharts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,32 +106,55 @@ export const formatLineChart = ({
}
}

export function downloadChart(data: Record<string, Array<[string | number, number]>>, filename: string) {
let rows = []
const charts = []
const dateStore = {}
for (const chartName in data) {
charts.push(chartName)
for (const [date, value] of data[chartName]) {
if (!dateStore[date]) {
dateStore[date] = {}
export function downloadChart(
data: Record<string, Array<[string | number, number]>>,
filename: string,
options: {
onLoadingStart?: () => void;
onLoadingEnd?: () => void;
onError?: (error: Error) => void;
} = {}
) {
const { onLoadingStart, onLoadingEnd, onError } = options

if (onLoadingStart) onLoadingStart()

try {
const rows = []
const charts = []
const dateStore = {}

for (const chartName in data) {
charts.push(chartName)
for (const [date, value] of data[chartName]) {
if (!dateStore[date]) {
dateStore[date] = {}
}
dateStore[date][chartName] = value
}
dateStore[date][chartName] = value
}
}
rows.push(['Timestamp', 'Date', ...charts])
for (const date in dateStore) {
const values = []
for (const chartName in data) {
values.push(dateStore[date]?.[chartName] ?? '')

rows.push(['Timestamp', 'Date', ...charts])
for (const date in dateStore) {
const values = []
for (const chartName in data) {
values.push(dateStore[date]?.[chartName] ?? '')
}
rows.push([date, toNiceCsvDate(+date / 1000), ...values])
}
rows.push([date, toNiceCsvDate(+date / 1000), ...values])

download(
filename,
rows
.sort((a, b) => a[0] - b[0])
.map((r) => r.join(','))
.join('\n')
)

if (onLoadingEnd) onLoadingEnd()
} catch (error) {
if (onError) onError(error as Error)
else if (onLoadingEnd) onLoadingEnd()
throw error
}
download(
filename,
rows
.sort((a, b) => a[0] - b[0])
.map((r) => r.join(','))
.join('\n')
)
}
7 changes: 5 additions & 2 deletions src/containers/BridgedTVL/BridgedTVLChainsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import { RowLinksWithDropdown } from '~/components/RowLinksWithDropdown'
import { TableWithSearch } from '~/components/Table/TableWithSearch'
import { TokenLogo } from '~/components/TokenLogo'
import { chainIconUrl, download, formattedNum, slug } from '~/utils'
import { useCSVDownload } from '~/hooks/useCSVDownload'

export function BridgedTVLChainsList({ assets, chains, flows1d }) {
const { downloadCSV, isLoading: isDownloadLoading } = useCSVDownload()

const data = Object.keys(assets)
.map((name) => {
const chainAssets = assets?.[name]
Expand Down Expand Up @@ -39,7 +42,7 @@ export function BridgedTVLChainsList({ assets, chains, flows1d }) {
.concat(csvData.map((row) => headers.map((header) => row[header]).join(',')))
.join('\n')

download('bridged-chains.csv', csv)
downloadCSV('bridged-chains.csv', csv)
}

return (
Expand All @@ -52,7 +55,7 @@ export function BridgedTVLChainsList({ assets, chains, flows1d }) {
columnToSearch={['name']}
customFilters={
<>
<CSVDownloadButton onClick={onCSVDownload} smol />
<CSVDownloadButton onClick={onCSVDownload} isLoading={isDownloadLoading} smol />
</>
}
/>
Expand Down
11 changes: 7 additions & 4 deletions src/containers/Bridges/BridgesOverviewByChain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { TxsTableSwitch } from '~/containers/Bridges/TableSwitch'
import { useBuildBridgeChartData } from '~/containers/Bridges/utils'
import { BRIDGES_SHOWING_TXS, useLocalStorageSettingsManager } from '~/contexts/LocalStorage'
import { download, formattedNum, getPrevVolumeFromChart, toNiceCsvDate } from '~/utils'
import { useCSVDownload } from '~/hooks/useCSVDownload'

const BarChart = React.lazy(() => import('~/components/ECharts/BarChart')) as React.FC<IBarChartProps>

Expand All @@ -34,6 +35,8 @@ export function BridgesOverviewByChain({
const [chartType, setChartType] = React.useState(selectedChain === 'All' ? 'Volumes' : 'Bridge Volume')
const [chartView, setChartView] = React.useState<'default' | 'netflow' | 'volume'>('netflow')
const [activeTab, setActiveTab] = React.useState<'bridges' | 'messaging'>('bridges')
const { downloadCSV: downloadMainCSV, isLoading: isMainDownloadLoading } = useCSVDownload()
const { downloadCSV: downloadChartCSV, isLoading: isChartDownloadLoading } = useCSVDownload()

useEffect(() => {
setChartView('netflow')
Expand Down Expand Up @@ -135,7 +138,7 @@ export function BridgesOverviewByChain({
}, 0)
])
})
download(fileName, rows.map((r) => r.join(',')).join('\n'))
downloadMainCSV(fileName, rows.map((r) => r.join(',')).join('\n'))
}

const downloadChartCsv = () => {
Expand Down Expand Up @@ -184,7 +187,7 @@ export function BridgesOverviewByChain({
if (rows.length === 0) {
alert('Not supported for this chart type')
} else {
download(fileName, rows.map((r) => r.join(',')).join('\n'))
downloadChartCSV(fileName, rows.map((r) => r.join(',')).join('\n'))
}
}

Expand Down Expand Up @@ -234,7 +237,7 @@ export function BridgesOverviewByChain({
<span className="font-jetbrains text-2xl font-semibold">{formattedNum(monthTotalVolume, true)}</span>
</p>

<CSVDownloadButton onClick={downloadCsv} smol className="mt-auto mr-auto" />
<CSVDownloadButton onClick={downloadCsv} isLoading={isMainDownloadLoading} smol className="mt-auto mr-auto" />
</div>
<div className="col-span-2 flex flex-col rounded-md border border-(--cards-border) bg-(--cards-bg)">
{selectedChain === 'All' ? (
Expand Down Expand Up @@ -329,7 +332,7 @@ export function BridgesOverviewByChain({
</>
)}
<div className="flex items-center justify-end p-3">
<CSVDownloadButton onClick={downloadChartCsv} smol />
<CSVDownloadButton onClick={downloadChartCsv} isLoading={isChartDownloadLoading} smol />
</div>
</div>
</div>
Expand Down
12 changes: 7 additions & 5 deletions src/containers/ChainOverview/Stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import dayjs from 'dayjs'
import toast from 'react-hot-toast'
import { Bookmark } from '~/components/Bookmark'
import { CSVDownloadButton } from '~/components/ButtonStyled/CsvButton'
import { downloadChart } from '~/components/ECharts/utils'
import { EmbedChart } from '~/components/EmbedChart'
import { Icon } from '~/components/Icon'
import { TokenLogo } from '~/components/TokenLogo'
Expand All @@ -14,7 +13,8 @@ import { chainCoingeckoIdsForGasNotMcap } from '~/constants/chainTokens'
import { formatRaisedAmount } from '~/containers/ProtocolOverview/utils'
import { useDarkModeManager, useLocalStorageSettingsManager } from '~/contexts/LocalStorage'
import { useAuthContext } from '~/containers/Subscribtion/auth'
import { capitalizeFirstLetter, chainIconUrl, downloadCSV, formattedNum, slug } from '~/utils'
import { useCSVDownload } from '~/hooks/useCSVDownload'
import { capitalizeFirstLetter, chainIconUrl, formattedNum, slug } from '~/utils'
import { BAR_CHARTS, ChainChartLabels, chainCharts, chainOverviewChartColors } from './constants'
import { IChainOverviewData } from './types'
import { useFetchChainChartData } from './useFetchChainChartData'
Expand Down Expand Up @@ -46,7 +46,8 @@ export const Stats = memo(function Stats(props: IStatsProps) {

const [tvlSettings] = useLocalStorageSettingsManager('tvl')

const { isAuthenticated } = useAuthContext()
const { authorizedFetch, isAuthenticated } = useAuthContext()
const { downloadCSV, downloadChart, isLoading: isDownloadLoading } = useCSVDownload()

const { toggledCharts, DENOMINATIONS, chainGeckoId, hasAtleasOneBarChart, groupBy, denomination } = useMemo(() => {
const queryParams = JSON.parse(queryParamsString)
Expand Down Expand Up @@ -650,7 +651,7 @@ export const Stats = memo(function Stats(props: IStatsProps) {
.map((t) => `${t[0]}=true`)
.join('&')}`.replaceAll(' ', '%20')

const response = await fetch(url)
const response = await authorizedFetch(url)

if (!response || !response.ok) {
toast.error('Failed to download CSV data')
Expand All @@ -659,13 +660,13 @@ export const Stats = memo(function Stats(props: IStatsProps) {

const csvData = await response.text()


downloadCSV(`${props.metadata.name}.csv`, csvData)
} catch (error) {
console.error('CSV download error:', error)
toast.error('Failed to download CSV data')
}
}}
isLoading={isDownloadLoading}
smol
className="ml-auto"
/>
Expand Down Expand Up @@ -818,6 +819,7 @@ export const Stats = memo(function Stats(props: IStatsProps) {
console.error('Error generating CSV:', error)
}
}}
isLoading={isDownloadLoading}
smol
/>
</div>
Expand Down
10 changes: 6 additions & 4 deletions src/containers/ChainOverview/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import { Tooltip } from '~/components/Tooltip'
import { ICONS_CDN, removedCategoriesFromChainTvl } from '~/constants'
import { subscribeToLocalStorage, useCustomColumns, useLocalStorageSettingsManager } from '~/contexts/LocalStorage'
import { formatProtocolsList2 } from '~/hooks/data/defi'
import { chainIconUrl, download, formattedNum, formattedPercent, slug } from '~/utils'
import { chainIconUrl, formattedNum, formattedPercent, slug } from '~/utils'
import { useCSVDownload } from '~/hooks/useCSVDownload'
import { formatValue } from '../../utils'
import { CustomColumnModal } from './CustomColumnModal'
import { replaceAliases, sampleProtocol } from './customColumnsUtils'
Expand All @@ -49,6 +50,7 @@ export const ChainProtocolsTable = ({
sampleRow?: any
}) => {
const { customColumns, setCustomColumns } = useCustomColumns()
const { downloadCSV: downloadCSVFromHook, isLoading: isCSVLoading } = useCSVDownload()

const router = useRouter()
const [extraTvlsEnabled] = useLocalStorageSettingsManager('tvl')
Expand Down Expand Up @@ -407,9 +409,9 @@ export const ChainProtocolsTable = ({
})
})

const csvContent = [headers, ...rows].map((row) => row.join(',')).join('\n')
const chainName = router.query.chain || 'all'
download(`defillama-${chainName}-protocols.csv`, csvContent)
const filename = `defillama-${chainName}-protocols.csv`
downloadCSVFromHook(filename, [headers, ...rows])
}

return (
Expand Down Expand Up @@ -461,7 +463,7 @@ export const ChainProtocolsTable = ({
onDeleteCustomColumn={handleDeleteCustomColumn}
/>
<TVLRange triggerClassName="w-full sm:w-auto" />
<CSVDownloadButton onClick={handleDownloadCsv} />
<CSVDownloadButton onClick={handleDownloadCsv} isLoading={isCSVLoading} />
</div>
</div>
</div>
Expand Down
Loading