commit 5d07234ebb3b637e9e8e964f25a761b1cdbc1b6b
parent 80fdd5ff69ad856fefa6e7196edb947e62f00dd2
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date: Sun, 18 Aug 2024 13:17:24 +0200
feat(heats): export to csv
Diffstat:
3 files changed, 55 insertions(+), 16 deletions(-)
diff --git a/src/Heats.jsx b/src/Heats.jsx
@@ -1,6 +1,7 @@
import { lazy, useEffect, useState } from 'react'
import { generatePath, Link } from 'react-router-dom'
import { supabase } from './supabaseClient'
+import { exportHeatsToCSV } from './utils'
const Auth = lazy(() => import('./Auth'))
@@ -41,6 +42,17 @@ async function deleteHeat(e, heatId, heatName) {
}
}
+// export heats
+function ExportForm({heats}) {
+ return (
+ <div className='exportForm'>
+ <form method='post' onSubmit={e => exportHeatsToCSV(e)}>
+ <button type='submit'>▿ export</button>
+ </form>
+ </div>
+ )
+}
+
function HeatForm({session}) {
const [loading, setLoading] = useState(false)
const [heats, setHeats] = useState([])
@@ -99,6 +111,7 @@ function HeatForm({session}) {
</tbody>
</table>
</form>
+ <ExportForm />
</div>
)
}
diff --git a/src/Leaderboard.jsx b/src/Leaderboard.jsx
@@ -1,5 +1,5 @@
import { supabase } from './supabaseClient'
-import { exportCSV, rankByHeat, getScores } from './utils'
+import { exportLeaderboardToCSV, rankByHeat, getScores } from './utils'
import { Fragment, useEffect, useState, useRef } from 'react'
import Select from 'react-select'
@@ -112,7 +112,7 @@ async function newHeatFromLeaderboard(e, {leaderboard, rankingComp, selectHeatRe
function ExportForm({leaderboard, heatSelection, rankingComp}) {
return (
<div className='exportForm'>
- <form method='post' onSubmit={e => exportCSV(
+ <form method='post' onSubmit={e => exportLeaderboardToCSV(
e,
leaderboard,
heatSelection,
diff --git a/src/utils.js b/src/utils.js
@@ -1,4 +1,25 @@
-export const exportCSV = async function(e, leaderboard, heatSelection, rankingComp) {
+import { supabase } from './supabaseClient'
+
+export const exportHeatsToCSV = async function(e) {
+ e.preventDefault()
+
+ const { data, error } = await supabase
+ .from('heats')
+ .select('created_at,name,location,planned_start')
+ .csv()
+
+ if (error !== null) {
+ alert(error.message)
+ return
+ } else if (data.length === 0) {
+ alert('No heats yet, nothing to export')
+ return
+ }
+
+ exportCSV(data, "heats")
+}
+
+export const exportLeaderboardToCSV = async function(e, leaderboard, heatSelection, rankingComp) {
e.preventDefault()
if (leaderboard.length === 0) {
@@ -32,19 +53,7 @@ export const exportCSV = async function(e, leaderboard, heatSelection, rankingCo
+ leaderboard[i].bestHeat + "," + leaderboard[i].worstHeat + "," + leaderboard[i].sum + "\n"
}
- // create blob from csv
- const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
-
- // download blob
- const url = URL.createObjectURL(blob)
- const link = document.createElement('a')
- link.href = url
- link.download = "scores-" + new Date().toISOString() + ".csv"
- document.body.appendChild(link)
- link.click()
- document.body.removeChild(link)
- // let browser know not to keep the reference to the file
- URL.revokeObjectURL(url)
+ exportCSV(csv, "scores")
}
// define the ranking logic
@@ -84,3 +93,20 @@ export const getScores = function(i, h) {
const scores = i.heats.find(heat => heat.heatId === h.value)?.scores?.map(s => s.score).join(" + ")
return scores === "" ? 0 : scores
}
+
+// export CSV as blob
+const exportCSV = function(csv, fileSlug) {
+ // create blob from csv
+ const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
+
+ // download blob
+ const url = URL.createObjectURL(blob)
+ const link = document.createElement('a')
+ link.href = url
+ link.download = fileSlug + "-" + new Date().toISOString() + ".csv"
+ document.body.appendChild(link)
+ link.click()
+ document.body.removeChild(link)
+ // let browser know not to keep the reference to the file
+ URL.revokeObjectURL(url)
+}