From 77040024d4992eb6cf0d5d01369feb126e0a17fe Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:17:28 -0400 Subject: [PATCH] chore: fix analytics CSV download (#3489) --- .../analytics_dowload_dialog.dart | 88 ++++++++++++++++--- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/lib/pangea/analytics_downloads/analytics_dowload_dialog.dart b/lib/pangea/analytics_downloads/analytics_dowload_dialog.dart index 8659df623..c17bdab1d 100644 --- a/lib/pangea/analytics_downloads/analytics_dowload_dialog.dart +++ b/lib/pangea/analytics_downloads/analytics_dowload_dialog.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:csv/csv.dart'; import 'package:excel/excel.dart'; +import 'package:intl/intl.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; @@ -81,19 +83,52 @@ class AnalyticsDownloadDialogState extends State { } try { - final content = _getExcelFileContent({ - ConstructTypeEnum.vocab: vocabSummary, - ConstructTypeEnum.morph: morphSummary, - }); + if (_downloadType == DownloadType.csv) { + final vocabContent = _getCSVFileContent( + ConstructTypeEnum.vocab, + vocabSummary, + ); - final fileName = - "analytics_${MatrixState.pangeaController.matrixState.client.userID?.localpart}_${DateTime.now().toIso8601String()}.${_downloadType == DownloadType.xlsx ? 'xlsx' : 'csv'}"; + final morphContent = _getCSVFileContent( + ConstructTypeEnum.morph, + morphSummary, + ); - await downloadFile( - content, - fileName, - _downloadType, - ); + final vocabFileName = + "analytics_vocab_${MatrixState.pangeaController.matrixState.client.userID?.localpart}_${DateFormat('yyyy-MM-dd-hh:mm:ss').format(DateTime.now())}.csv"; + + final morphFileName = + "analytics_morph_${MatrixState.pangeaController.matrixState.client.userID?.localpart}_${DateFormat('yyyy-MM-dd-hh:mm:ss').format(DateTime.now())}.csv"; + + final futures = [ + downloadFile( + vocabContent, + vocabFileName, + _downloadType, + ), + downloadFile( + morphContent, + morphFileName, + _downloadType, + ), + ]; + + await Future.wait(futures); + } else { + final content = _getExcelFileContent({ + ConstructTypeEnum.vocab: vocabSummary, + ConstructTypeEnum.morph: morphSummary, + }); + + final fileName = + "analytics_${MatrixState.pangeaController.matrixState.client.userID?.localpart}_${DateFormat('yyyy-MM-dd-hh:mm:ss').format(DateTime.now())}.xlsx'}"; + + await downloadFile( + content, + fileName, + _downloadType, + ); + } _downloaded = true; } catch (e, s) { ErrorHandler.logError( @@ -312,6 +347,37 @@ class AnalyticsDownloadDialogState extends State { return excel.encode() ?? []; } + String _getCSVFileContent( + ConstructTypeEnum type, + List summaries, + ) { + final values = type == ConstructTypeEnum.vocab + ? AnalyticsSummaryEnum.vocabValues + : AnalyticsSummaryEnum.morphValues; + + final List> rows = []; + final headerRow = []; + for (final key in values) { + headerRow.add(key.header(context)); + } + + rows.add(headerRow); + for (final summary in summaries) { + final List row = []; + for (int i = 0; i < values.length; i++) { + final key = values[i]; + final value = summary.getValue(key); + row.add( + value is List ? value.map((v) => "\"$v\"").join(", ") : value, + ); + } + rows.add(row); + } + + final String fileString = const ListToCsvConverter().convert(rows); + return fileString; + } + List _formatExcelRow( AnalyticsSummaryModel summary, ConstructTypeEnum type,