Skip to content

Commit

Permalink
Use scenario name in downloads
Browse files Browse the repository at this point in the history
  • Loading branch information
jmccollum-woolpert committed Mar 27, 2024
1 parent baf41a8 commit 9b9c6c0
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
display: inline-block;
position: relative;
max-width: 50vw;
min-width: 14em;
min-width: 10em;
min-height: 3em;
}

Expand All @@ -16,6 +16,7 @@
}

.scenario-input {
padding-left: 0.25em;
position: absolute;
top: 0;
left: 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export class DownloadPdfDialogComponent implements OnInit, OnDestroy {
renderedMaps: any[] = [];
report: Blob;

scenarioName: string;

csvData: Partial<CsvData>[] = [];
routes: DeckGLRoute[];
vehicles: Vehicle[];
Expand Down Expand Up @@ -207,7 +209,8 @@ export class DownloadPdfDialogComponent implements OnInit, OnDestroy {
}

downloadReport(): void {
this.fileService.download('routes.pdf', [this.report], 'application/pdf');
const filename = this.scenarioName.length ? this.scenarioName : 'routes';
this.fileService.download(`${filename}.pdf`, [this.report], 'application/pdf');
}

cancel(): void {
Expand Down
39 changes: 37 additions & 2 deletions application/frontend/src/app/core/effects/download.effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { FileService, MessageService } from '../services';
import { DownloadEffects } from './download.effects';
import { MatSnackBar } from '@angular/material/snack-bar';
import * as fromUI from '../selectors/ui.selectors';
import { selectScenarioName } from '../selectors/dispatcher.selectors';

describe('DownloadEffects', () => {
let actions$: Observable<any>;
Expand Down Expand Up @@ -53,6 +54,7 @@ describe('DownloadEffects', () => {
selectors: [
{ selector: fromDownload.selectDownload, value: null },
{ selector: fromUI.selectModal, value: null },
{ selector: selectScenarioName, value: '' },
],
}),
provideMockActions(() => actions$),
Expand All @@ -75,7 +77,25 @@ describe('DownloadEffects', () => {
scenario: {},
solution: { routes: [] },
});
const name = jasmine.stringMatching(/^dispatcher_\d{14}$/);
const name = jasmine.stringMatching(/^gmpro_\d{14}$/);
const blob = {};
(fileService.zip as jasmine.Spy).and.callFake(() => of(blob));
(fileService.download as jasmine.Spy).and.callFake(() => null);
actions$ = hot('-a---', { a: download() });

const expected = hot('-b---', { b: downloadSuccess({ name, blob } as any) });
expect(effects.startDownload$).toBeObservable(expected);
expect(fileService.zip).toHaveBeenCalledTimes(1);
expect(fileService.download).toHaveBeenCalledTimes(1);
});

it('should dispatch success with scenario, solution, and custom name', () => {
store.overrideSelector(fromDownload.selectDownload, {
scenario: {},
solution: { routes: [] },
});
store.overrideSelector(selectScenarioName, 'custom scenario');
const name = jasmine.stringMatching('custom scenario');
const blob = {};
(fileService.zip as jasmine.Spy).and.callFake(() => of(blob));
(fileService.download as jasmine.Spy).and.callFake(() => null);
Expand All @@ -89,7 +109,22 @@ describe('DownloadEffects', () => {

it('should dispatch success without solution', () => {
store.overrideSelector(fromDownload.selectDownload, { scenario: {} });
const name = jasmine.stringMatching(/^dispatcher_\d{14}$/);
const name = jasmine.stringMatching(/^gmpro_\d{14}$/);
const blob = {};
(fileService.zip as jasmine.Spy).and.callFake(() => of(blob));
(fileService.download as jasmine.Spy).and.callFake(() => null);
actions$ = hot('-a---', { a: download() });

const expected = hot('-b---', { b: downloadSuccess({ name, blob } as any) });
expect(effects.startDownload$).toBeObservable(expected);
expect(fileService.zip).toHaveBeenCalledTimes(1);
expect(fileService.download).toHaveBeenCalledTimes(1);
});

it('should dispatch success without solution and custom name', () => {
store.overrideSelector(fromDownload.selectDownload, { scenario: {} });
store.overrideSelector(selectScenarioName, 'custom scenario');
const name = jasmine.stringMatching('custom scenario');
const blob = {};
(fileService.zip as jasmine.Spy).and.callFake(() => of(blob));
(fileService.download as jasmine.Spy).and.callFake(() => null);
Expand Down
36 changes: 25 additions & 11 deletions application/frontend/src/app/core/effects/download.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
exhaustMap,
mergeMap,
} from 'rxjs/operators';
import { of, defer, throwError } from 'rxjs';
import { of, defer, throwError, zip } from 'rxjs';
import {
CsvData,
CSV_COLUMN_ORDER,
Expand All @@ -56,6 +56,7 @@ import { MatDialog } from '@angular/material/dialog';
import { DownloadPdfDialogComponent } from '../containers/download-pdf-dialog/download-pdf-dialog.component';
import protobuf from 'protobufjs';
import { ExtendedConversionOptions } from 'src/app/util/canonical-protobuf';
import { selectScenarioName } from '../selectors/dispatcher.selectors';

@Injectable()
export class DownloadEffects {
Expand All @@ -66,8 +67,13 @@ export class DownloadEffects {
filter(
(modal) => modal === Modal.DownloadPDF && !this.dialog.getDialogById(Modal.DownloadPDF)
),
switchMap(() => this.store.select(fromDownload.selectDownload).pipe(first())),
exhaustMap((data) => {
switchMap(() =>
zip(
this.store.select(fromDownload.selectDownload).pipe(first()),
this.store.select(selectScenarioName).pipe(first())
)
),
exhaustMap(([data, scenarioName]) => {
const csvData = this.getCsvDataForSolution(data, false);
const dialog = this.dialog.open(DownloadPdfDialogComponent, {
id: Modal.DownloadPDF,
Expand All @@ -76,6 +82,7 @@ export class DownloadEffects {
disableClose: true,
});
dialog.componentInstance.csvData = this.csvDataToLabeledCsvData(csvData, true);
dialog.componentInstance.scenarioName = scenarioName;
return dialog.afterClosed();
}),
mergeMap((_) => {
Expand Down Expand Up @@ -105,12 +112,16 @@ export class DownloadEffects {
)
.map((key: string) => this.getColumnLabel(key));

return of(unparse({ fields: csvColumns, data: labeledCsvData }));
return zip(
of(unparse({ fields: csvColumns, data: labeledCsvData })),
this.store.select(selectScenarioName).pipe(first())
);
}).pipe(
map((csvData) => {
map(([csvData, scenarioName]) => {
const blob = new Blob([csvData], { type: 'text/csv' });
const name =
'routes_' + formatDate(new Date(), 'yyyyMMddHHmmss', this.locale, 'UTC') + '.csv';
const name = scenarioName.length
? scenarioName
: 'routes_' + formatDate(new Date(), 'yyyyMMddHHmmss', this.locale, 'UTC') + '.csv';
this.fileService.download(name, [csvData], 'text/csv');
return downloadSuccess({ name, blob });
}),
Expand Down Expand Up @@ -152,10 +163,13 @@ export class DownloadEffects {
} as ExtendedConversionOptions;
return of(files);
}).pipe(
switchMap((files) => this.fileService.zip(files)),
map((blob) => {
const name =
'dispatcher_' + formatDate(new Date(), 'yyyyMMddHHmmss', this.locale, 'UTC');
switchMap((files) =>
zip(this.fileService.zip(files), this.store.select(selectScenarioName).pipe(first()))
),
map(([blob, scenarioName]) => {
const name = scenarioName.length
? scenarioName
: 'gmpro_' + formatDate(new Date(), 'yyyyMMddHHmmss', this.locale, 'UTC');
this.fileService.download(name, [blob], 'application/zip');
return downloadSuccess({ name, blob });
}),
Expand Down

0 comments on commit 9b9c6c0

Please sign in to comment.