Skip to content

Commit f047910

Browse files
committed
export using cache
1 parent ef8397e commit f047910

File tree

8 files changed

+57
-40
lines changed

8 files changed

+57
-40
lines changed

src/@seed/api/inventory/inventory.service.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -352,19 +352,9 @@ export class InventoryService {
352352
)
353353
}
354354

355-
startInventoryExport(orgId: number): Observable<ProgressResponse> {
355+
startInventoryExport(orgId: number, data: InventoryExportData): Observable<ProgressResponse> {
356356
const url = `/api/v3/tax_lot_properties/start_export/?organization_id=${orgId}`
357-
return this._httpClient.get<ProgressResponse>(url).pipe(
358-
take(1),
359-
catchError((error: HttpErrorResponse) => {
360-
return this._errorService.handleError(error, 'Error starting export')
361-
}),
362-
)
363-
}
364-
365-
exportInventory(orgId: number, type: InventoryType, data: InventoryExportData): Observable<Blob> {
366-
const url = `/api/v3/tax_lot_properties/export/?inventory_type=${type}&organization_id=${orgId}`
367-
return this._httpClient.post(url, data, { responseType: 'blob' }).pipe(
357+
return this._httpClient.post<ProgressResponse>(url, data).pipe(
368358
take(1),
369359
catchError((error: HttpErrorResponse) => {
370360
return this._errorService.handleError(error, 'Error starting export')

src/@seed/services/uploader/uploader.service.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { ProgressResponse } from '@seed/api'
77
import { ErrorService } from '../error'
88
import type {
99
CheckProgressLoopParams,
10+
ExportDataType,
1011
GreenButtonMeterPreview,
1112
MeterPreviewResponse,
1213
ProgressBarObj,
@@ -176,6 +177,26 @@ export class UploaderService {
176177
)
177178
}
178179

180+
stringToBlob(data: string, exportType: ExportDataType) {
181+
const base64ToBlob = (base64: string): Blob => {
182+
const binary = atob(base64)
183+
const bytes = new Uint8Array(binary.length)
184+
for (let i = 0; i < binary.length; i++) {
185+
bytes[i] = binary.charCodeAt(i)
186+
}
187+
188+
return new Blob([bytes], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
189+
}
190+
191+
const blobMap: Record<ExportDataType, () => Blob> = {
192+
csv: () => new Blob([data], { type: 'text/csv' }),
193+
xlsx: () => base64ToBlob(data),
194+
geojson: () => new Blob([JSON.stringify(data, null, '\t')], { type: 'application/geo+json' }),
195+
}
196+
197+
return blobMap[exportType]()
198+
}
199+
179200
/*
180201
* Updates the progress bar object with incoming progress data.
181202
*/

src/@seed/services/uploader/uploader.types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,5 @@ export type MeterPreviewResponse = {
6868
unlinkable_pm_ids: number[];
6969
validated_type_units: ValidatedTypeUnit[];
7070
}
71+
72+
export type ExportDataType = 'csv' | 'xlsx' | 'geojson'

src/app/modules/datasets/data-mappings/data-mapping.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ export class DataMappingComponent implements OnDestroy, OnInit {
223223
this.mappingResultsResponse = response as MappingResultsResponse
224224
this.nextStep(2)
225225
}),
226+
take(1),
226227
)
227228
.subscribe()
228229
}

src/app/modules/inventory-detail/ubids/modal/form-modal.component.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ export class FormModalComponent implements OnInit {
6363
.update(this.data.orgId, this.data.viewId, this.data.ubid.id, ubidDetails, this.data.type)
6464
.pipe(
6565
tap((response) => {
66-
console.log('response', response)
6766
this.close(preferred)
6867
}),
6968
)
@@ -75,7 +74,6 @@ export class FormModalComponent implements OnInit {
7574
.create(this.data.orgId, this.data.viewId, ubidDetails, this.data.type)
7675
.pipe(
7776
tap((response) => {
78-
console.log('response', response)
7977
this.close(preferred)
8078
}),
8179
)

src/app/modules/inventory/actions/export-modal.component.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
<mat-button-toggle class="flex-1" value="geojson">GeoJSON</mat-button-toggle>
1717
</mat-button-toggle-group>
1818

19+
<mat-checkbox formControlName="include_notes">Include Notes</mat-checkbox>
1920
@if (form.value.export_type === 'geojson') {
2021
<mat-checkbox formControlName="include_meter_readings"
2122
>Include Meter Readings <span class="text-secondary"> (Only recommended for small exports)</span>
2223
</mat-checkbox>
23-
} @else if (form.value.export_type === 'csv') {
24-
<mat-checkbox formControlName="include_meter_readings"> Include Label Header</mat-checkbox>
2524
} @else {
2625
<div class="h-10"></div>
2726
}

src/app/modules/inventory/actions/export-modal.component.ts

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { Component, inject, ViewChild } from '@angular/core'
33
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'
44
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'
55
import type { MatStepper } from '@angular/material/stepper'
6-
import { catchError, combineLatest, EMPTY, finalize, Subject, switchMap, takeUntil, tap } from 'rxjs'
7-
import { InventoryService } from '@seed/api'
6+
import { catchError, EMPTY, Subject, switchMap, take, takeUntil, tap } from 'rxjs'
7+
import { CacheService, InventoryService, ProgressResponse } from '@seed/api'
88
import { ModalHeaderComponent, ProgressBarComponent } from '@seed/components'
99
import { MaterialImports } from '@seed/materials'
1010
import { UploaderService } from '@seed/services'
@@ -18,6 +18,7 @@ import type { InventoryExportData, InventoryType } from '../inventory.types'
1818
})
1919
export class ExportModalComponent implements OnDestroy {
2020
@ViewChild('stepper') stepper!: MatStepper
21+
private _cacheService = inject(CacheService)
2122
private _dialogRef = inject(MatDialogRef<ExportModalComponent>)
2223
private _inventoryService = inject(InventoryService)
2324
private _snackBar = inject(SnackBarService)
@@ -36,41 +37,48 @@ export class ExportModalComponent implements OnDestroy {
3637
}
3738

3839
form = new FormGroup({
39-
name: new FormControl<string>(null, Validators.required),
40-
include_notes: new FormControl(true),
4140
export_type: new FormControl<'csv' | 'xlsx' | 'geojson'>('csv', Validators.required),
42-
include_label_header: new FormControl(false),
41+
include_notes: new FormControl(false),
4342
include_meter_readings: new FormControl(false),
43+
name: new FormControl<string>(null, Validators.required),
4444
})
4545

4646
export() {
47-
this._inventoryService.startInventoryExport(this.data.orgId)
47+
const successFn = ({ unique_id }: ProgressResponse) => {
48+
this._cacheService.getCacheEntry(this.data.orgId, unique_id).pipe(
49+
tap((response: { data: string }) => {
50+
const blob = this.getBlob(response.data)
51+
this.downloadData(blob)
52+
this.close()
53+
}),
54+
take(1),
55+
).subscribe()
56+
}
57+
58+
this.initExport()
59+
this._inventoryService.startInventoryExport(this.data.orgId, this.exportData)
4860
.pipe(
49-
tap(({ progress_key }) => { this.initExport(progress_key) }),
50-
switchMap(() => this.pollExport()),
51-
tap((response) => { this.downloadData(response[0]) }),
61+
switchMap(({ progress_key }) => this._uploaderService.checkProgressLoop({
62+
progressKey: progress_key,
63+
successFn,
64+
failureFn: () => { this.close() },
65+
progressBarObj: this.progressBarObj,
66+
})),
5267
takeUntil(this._unsubscribeAll$),
5368
catchError(() => { return EMPTY }),
54-
finalize(() => { this.close() }),
5569
)
5670
.subscribe()
5771
}
5872

59-
initExport(progress_key: string) {
73+
initExport() {
6074
this.stepper.next()
6175
this.formatFilename()
62-
this.formatExportData(this.filename, progress_key)
76+
this.formatExportData(this.filename)
6377
}
6478

65-
pollExport() {
66-
const { orgId, type } = this.data
67-
return combineLatest([
68-
this._inventoryService.exportInventory(orgId, type, this.exportData),
69-
this._uploaderService.checkProgressLoop({
70-
progressKey: this.exportData.progress_key,
71-
progressBarObj: this.progressBarObj,
72-
}),
73-
])
79+
getBlob(data: string): Blob {
80+
const exportType = this.form.value.export_type
81+
return this._uploaderService.stringToBlob(data, exportType)
7482
}
7583

7684
downloadData(data: Blob) {
@@ -91,15 +99,14 @@ export class ExportModalComponent implements OnDestroy {
9199
}
92100
}
93101

94-
formatExportData(filename: string, progress_key: string) {
102+
formatExportData(filename: string) {
95103
this.exportData = {
96104
export_type: this.form.value.export_type,
97105
filename,
98106
ids: this.data.viewIds,
99107
include_meter_readings: this.form.value.include_meter_readings,
100108
include_notes: this.form.value.include_notes,
101109
profile_id: this.data.profileId,
102-
progress_key,
103110
}
104111
}
105112

src/app/modules/inventory/inventory.types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,5 +263,4 @@ export type InventoryExportData = {
263263
include_meter_readings: boolean;
264264
include_notes: boolean;
265265
profile_id: number;
266-
progress_key: string;
267266
}

0 commit comments

Comments
 (0)