Skip to content

Commit

Permalink
feat: refresh all rainfall summaries
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismclarke committed Oct 14, 2024
1 parent f528c20 commit 311ad74
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 35 deletions.
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"java.configuration.updateBuildConfiguration": "automatic",
"cSpell.enabled": false,
"eslint.runtime": "node",
// Deno configuration for supabase functions
// NOTE - could be refactored to separate code-workspace
// https://supabase.com/docs/guides/functions/local-development#setting-up-your-environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,27 @@
<h2>Admin</h2>
<div style="display: flex; align-items: center; gap: 2em">
<p style="flex: 1">(WiP) dashboard to allow quick download of Rainfall Summaries to include in the app</p>
<button mat-stroked-button color="primary" (click)="downloadAllStationsCSV()">Download All</button>
<!-- Data Refresh -->
<button mat-stroked-button color="primary" (click)="refreshAllStations()" [disabled]="refreshCount() > -1">
<mat-icon>refresh</mat-icon>
<span>
@if(refreshCount() > -1){
{{ refreshCount() }} / {{ tableData().length }} } @else { Refresh All}
</span>
</button>
<!-- Data Download -->
<button mat-stroked-button color="primary" (click)="downloadAllStationsCSV()">
<mat-icon>download</mat-icon>Download All
</button>
</div>
<picsa-data-table
style="margin-top: 1em"
[data]="tableData()"
[options]="tableOptions"
[valueTemplates]="{ csv: csvTemplate }"
>
<ng-template #csvTemplate let-row="row">
<button mat-button (click)="downloadStationCSV(row)"><mat-icon>download</mat-icon></button>
<ng-template #csvTemplate let-row="row" let-value="value">
<button mat-button (click)="downloadStationCSV(row)" [disabled]="!value"><mat-icon>download</mat-icon></button>
</ng-template>
</picsa-data-table>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { IDataTableOptions, PicsaDataTableComponent } from '@picsa/shared/features';
import { SupabaseService } from '@picsa/shared/services/core/supabase';
import { arrayToHashmapArray } from '@picsa/utils';
import { _wait, arrayToHashmapArray } from '@picsa/utils';
import download from 'downloadjs';
import JSZip from 'jszip';
import { unparse } from 'papaparse';
Expand All @@ -14,6 +14,17 @@ import { ClimateService } from '../../climate.service';
import type { IAnnualRainfallSummariesData, IClimateProductRow, IStationRow } from '../../types';
import { hackConvertAPIDataToLegacyFormat } from '../station-details/components/rainfall-summary/rainfall-summary.utils';

interface IStationAdminSummary {
station_id: string;
row: IStationRow;
updated_at: string;
rainfall_summary?: IClimateProductRow;
start_year?: number;
end_year?: number;
}

const DISPLAY_COLUMNS: (keyof IStationAdminSummary)[] = ['station_id', 'updated_at', 'start_year', 'end_year'];

/**
* TODOs - See #333
*/
Expand All @@ -32,8 +43,9 @@ export class ClimateAdminPageComponent {
return this.generateTableSummaryData(stations, products);
});
public tableOptions: IDataTableOptions = {
displayColumns: ['station_id', 'type', 'updated_at', 'start_year', 'end_year', 'csv'],
displayColumns: DISPLAY_COLUMNS,
};
public refreshCount = signal(-1);

private climateProducts = signal<IClimateProductRow[]>([]);

Expand Down Expand Up @@ -61,23 +73,38 @@ export class ClimateAdminPageComponent {
for (const summary of this.tableData()) {
const csvData = this.generateStationCSVDownload(summary);
if (csvData) {
zip.file(`${summary.station_id}.csv`, csvData);
zip.file(`${summary.row.station_id}.csv`, csvData);
}
}
const blob = await zip.generateAsync({ type: 'blob' });
const country_code = this.deploymentService.activeDeployment()?.country_code;
download(blob, `${country_code}_rainfall_summaries.zip`);
}

public downloadStationCSV(summary) {
const csv = this.generateStationCSVDownload(summary);
public downloadStationCSV(station: IStationAdminSummary) {
const csv = this.generateStationCSVDownload(station);
if (csv) {
download(csv, summary.station_id, 'text/csv');
download(csv, station.row.station_id, 'text/csv');
}
}
private generateStationCSVDownload(summary) {
if (summary.data && summary.data.length > 0) {
const csvData = hackConvertAPIDataToLegacyFormat(summary.data);

public async refreshAllStations() {
this.refreshCount.set(0);
const promises = this.tableData().map(async (station, i) => {
// hack - instead of queueing apply small offset between requests to reduce blocking
await _wait(200 * i);
await this.service.loadFromAPI.rainfallSummaries(station.row);
this.refreshCount.update((v) => v + 1);
});
await Promise.all(promises);
await this.loadRainfallSummaries(this.deploymentService.activeDeployment()?.country_code as string);
}

private generateStationCSVDownload(summary: IStationAdminSummary) {
const { rainfall_summary } = summary;
if (rainfall_summary && rainfall_summary.data) {
const data = rainfall_summary.data['data'] as any[];
const csvData = hackConvertAPIDataToLegacyFormat(data);
const columns = Object.keys(csvData[0]);
const csv = unparse(csvData, { columns });
return csv;
Expand All @@ -86,25 +113,21 @@ export class ClimateAdminPageComponent {
}

private generateTableSummaryData(stations: IStationRow[], products: IClimateProductRow[]) {
if (stations.length > 0 && products.length > 0) {
// NOTE - only single entry for rainfallSummary (not hashmapArray)
const productsHashmap = arrayToHashmapArray(products, 'station_id');
const summary = stations.map((station) => {
const { station_id } = station;
const rainfallSummary = productsHashmap[station_id]?.find((p) => p.type === 'rainfallSummary');
if (rainfallSummary) {
const { data, station_id, type } = rainfallSummary;
const entries: IAnnualRainfallSummariesData[] = data?.['data'] || [];
const start_year = entries[0]?.year;
const end_year = entries[entries.length - 1]?.year;
return { station_id, type, updated_at: '', start_year, end_year, csv: '', data: data?.['data'] };
} else {
return { station_id };
}
});
// NOTE - only single entry for rainfallSummary (not hashmapArray)
const productsHashmap = arrayToHashmapArray(products, 'station_id');
return stations.map((row) => {
const { station_id } = row;
const summary: IStationAdminSummary = { station_id, row, updated_at: '' };
const rainfallSummary = productsHashmap[station_id]?.find((p) => p.type === 'rainfallSummary');
if (rainfallSummary) {
summary.rainfall_summary = rainfallSummary;
const { data } = rainfallSummary;
const entries: IAnnualRainfallSummariesData[] = data?.['data'] || [];
summary.start_year = entries[0]?.year;
summary.end_year = entries[entries.length - 1]?.year;
}
return summary;
}
return [];
});
}

private async loadRainfallSummaries(country_code: string) {
Expand Down
8 changes: 4 additions & 4 deletions apps/picsa-server/supabase/data/deployments_rows.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ id,country_code,label,configuration,variant,access_key_md5,public,icon_path
demo_dev,demo,Extension,{},extension,,false,global/images/tutorial.svg
global_extension,global,Extension,{},extension,,false,global/images/flags/global.svg
global_farmer,global,Farmer,{},farmer,,false,global/images/flags/global.svg
mw_extension,mw,Extension,{},extension,,false,global/images/flags/mw.svg
mw_farmer,mw,Farmer,{},farmer,,false,global/images/flags/mw.svg
mw_workshop,mw,Malawi Workshop,"{""climate_country_code"":""mw_workshops""}",extension,,true,global/images/flags/mw.svg
zm_extension,zm,Extension,{},extension,,false,global/images/flags/zm.svg
zm_farmer,zm,Farmer,{},farmer,,false,global/images/flags/zm.svg
zm_workshop,zm,Zambia Workshop,"{""climate_country_code"":""zm_workshops""}",extension,,true,global/images/flags/zm.svg
mw_extension,mw,Malawi,{},extension,,true,global/images/flags/mw.svg
mw_workshop,mw,Malawi Workshop,"{""climate_country_code"":""mw_workshops""}",extension,,false,global/images/flags/mw.svg
zm_extension,zm,Zambia,{},extension,,true,global/images/flags/zm.svg
zm_workshop,zm,Zambia Workshop,"{""climate_country_code"":""zm_workshops""}",extension,,false,global/images/flags/zm.svg

0 comments on commit 311ad74

Please sign in to comment.