Skip to content

Commit

Permalink
Update upload dialog layout
Browse files Browse the repository at this point in the history
  • Loading branch information
jmccollum-woolpert committed Feb 1, 2024
1 parent da0100d commit cbcc524
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export class AppComponent {
'dropoff',
'edit',
'help',
'help-filled',
'input',
'map',
'maps',
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,95 +3,108 @@ <h1 mat-dialog-title>Upload a scenario or solution</h1>
<div mat-dialog-content>
<mat-divider class="mb-4"></mat-divider>
<h3 class="strong">What file types can I use?</h3>
<h4 class="strong">
<h4 class="strong d-flex">
Load scenario and solution files
<a (click)="openScenarioSolutionHelp()">
<mat-icon fontIcon="help" class="help-icon"></mat-icon>
<a (click)="openScenarioSolutionHelp()" class="ml-1 scenario-solution-help-icon blue-svg-icon">
<mat-icon svgIcon="help-filled"></mat-icon>
</a>
</h4>
<p>
Have an existing vehicle routing problem you want to solve? You can upload a JSON description
of the problem to see the routes that Cloud Fleet Routing recommends, and then download the
generated routes if you wish.
</p>
<p>
You may also upload a zip file containing a scenario and its matching solution. In order to do
this, please adhere to the following requirements:
</p>
<ul>
<li>The zip file contains two files named <i>scenario.json</i> and <i>solution.json</i></li>
<li>The provided solution is for the provided scenario</li>
</ul>
<div class="file-input">
<div class="file-input__form-field">
<mat-form-field>
<input
matInput
[readonly]="true"
[formControl]="fileName"
(click)="selectFile()"
required />
<mat-error
*ngIf="
fileName.errors?.required && (fileName.touched || fileName.dirty) && !validatingUpload
">
{{ (messages$ | async)?.formFileRequired || 'File is required' }}
</mat-error>
<mat-error *ngIf="fileName.errors?.zipContents && (fileName.touched || fileName.dirty)">
{{ 'Invalid zip contents' }}
</mat-error>
<mat-error *ngIf="fileName.errors?.fileFormat && (fileName.touched || fileName.dirty)">
{{ (messages$ | async)?.formInvalidFileFormat || 'Invalid file format' }}
</mat-error>
<mat-error *ngIf="fileName.errors?.requestFormat && (fileName.touched || fileName.dirty)">
{{ (messages$ | async)?.formInvalidRequestFormat || 'Invalid request format' }}
</mat-error>
</mat-form-field>
<button
type="button"
mat-raised-button
cdkFocusInitial
(click)="selectFile()"
[disabled]="validatingUpload">
Choose a File
</button>
</div>
<p *ngIf="validatingUpload" class="mat-small">Validating upload</p>
<!-- resolve place ids -->
<div
*ngIf="scenarioHasPlaceIds && placeIdProgress < placeIdCount"
class="d-flex flex-column mat-small">
<div *ngIf="!resolvingPlaceIds" class="d-flex flex-column align-items-center">
<p>
⚠️ This scenario contains Place ID waypoints. Some features of the application require
lat/lng locations. Click the button below to request the lat/lng location of all Place
IDs in the scenario (it will take a few minutes). You may continue with just the Place
IDs, but some parts of the application may not work properly.
<div class="json-upload-container d-flex flex-column">
<div class="d-flex flex-row justify-content-between w-100 json-description-container">
<div class="d-flex flex-column json-description">
<div class="align-items-center d-flex">
<div class="blue-svg-icon">
<mat-icon svgIcon="zip"></mat-icon>
</div>
<span class="ml-1 mat-body-strong">.json file</span>
</div>
<p class="description-text">
Use this option when you have a .json file that contains a VRP scenario you want to solve.
</p>
<button type="button" mat-stroked-button (click)="resolveWaypointPlaceIds()">
Get Place ID Locations
</div>
<div class="d-flex flex-column json-description">
<div class="align-items-center d-flex">
<div class="blue-svg-icon">
<mat-icon svgIcon="zip"></mat-icon>
</div>
<span class="ml-1 mat-body-strong">.zip file</span>
</div>
<p class="description-text">
Use this option when you have a .zip file that contains both the .json and VRP scenario files. The .zip file must contain the <span class="strong">scenario.json</span> and <span class="strong">solution.json</span>
</p>
</div>
</div>
<div class="file-input">
<div class="file-input__form-field">
<mat-form-field>
<input
matInput
[readonly]="true"
[formControl]="fileName"
(click)="selectFile()"
required />
<mat-error
*ngIf="
fileName.errors?.required && (fileName.touched || fileName.dirty) && !validatingUpload
">
{{ (messages$ | async)?.formFileRequired || 'File is required' }}
</mat-error>
<mat-error *ngIf="fileName.errors?.zipContents && (fileName.touched || fileName.dirty)">
{{ 'Invalid zip contents' }}
</mat-error>
<mat-error *ngIf="fileName.errors?.fileFormat && (fileName.touched || fileName.dirty)">
{{ (messages$ | async)?.formInvalidFileFormat || 'Invalid file format' }}
</mat-error>
<mat-error *ngIf="fileName.errors?.requestFormat && (fileName.touched || fileName.dirty)">
{{ (messages$ | async)?.formInvalidRequestFormat || 'Invalid request format' }}
</mat-error>
</mat-form-field>
<button
type="button"
mat-raised-button
cdkFocusInitial
(click)="selectFile()"
[disabled]="validatingUpload">
Choose a File
</button>
</div>

<div *ngIf="resolvingPlaceIds">
<mat-progress-bar [value]="(placeIdProgress / placeIdCount) * 100"></mat-progress-bar>
<mat-label
>Requesting Place ID locations... ({{ placeIdProgress | number }} of
{{ placeIdCount | number }})</mat-label
>
<p *ngIf="validatingUpload" class="mat-small">Validating upload</p>
<!-- resolve place ids -->
<div
*ngIf="scenarioHasPlaceIds && placeIdProgress < placeIdCount"
class="d-flex flex-column mat-small">
<div *ngIf="!resolvingPlaceIds" class="d-flex flex-column align-items-center">
<p>
⚠️ This scenario contains Place ID waypoints. Some features of the application require
lat/lng locations. Click the button below to request the lat/lng location of all Place
IDs in the scenario (it will take a few minutes). You may continue with just the Place
IDs, but some parts of the application may not work properly.
</p>
<button type="button" mat-stroked-button (click)="resolveWaypointPlaceIds()">
Get Place ID Locations
</button>
</div>

<div *ngIf="resolvingPlaceIds">
<mat-progress-bar [value]="(placeIdProgress / placeIdCount) * 100"></mat-progress-bar>
<mat-label
>Requesting Place ID locations... ({{ placeIdProgress | number }} of
{{ placeIdCount | number }})</mat-label
>
</div>

<mat-error *ngIf="placeIdError">
{{ placeIdError }}
</mat-error>
</div>

<mat-error *ngIf="placeIdError">
{{ placeIdError }}
</mat-error>
<!-- file input browser (not visible) -->
<input
#fileInput
type="file"
accept=".json,.zip"
(click)="fileUploadClicked($event)"
(change)="fileSelected($event)" />
</div>
<!-- file input browser (not visible) -->
<input
#fileInput
type="file"
accept=".json,.zip"
(click)="fileUploadClicked($event)"
(change)="fileSelected($event)" />
</div>
</div>
<div mat-dialog-actions>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@import '../../../../styles/variables.scss';

.file-input__form-field {
display: flex;
align-items: center;
}

.file-input__form-field mat-form-field.mat-form-field {
flex-grow: 1;
width: auto;
}

.file-input__form-field :last-child {
flex-grow: 0;
margin-left: 16px;
}

.file-input input[type='file'] {
opacity: 0;
height: 0;
}

.mat-dialog-content {
overflow-x: hidden;
}

.scenario-solution-help-icon {
display: inline-flex;

mat-icon {
width: 20px;
height: 20px;
}
}

.json-upload-container {
border-radius: 0.625rem;
background: rgba(66, 133, 244, 0.05);

display: flex;
padding: 0.9375rem;
flex-direction: column;
align-items: flex-start;
gap: 1.5625rem;
align-self: stretch;
}

.json-description-container {
gap: 1rem;
}

.json-description {
flex-grow: 1;
width: 0;
}

.description-text {
color: $gray
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { ScenarioSolutionHelpDialogComponent } from 'src/app/core/containers/sce
@Component({
selector: 'app-upload-dialog',
templateUrl: './upload-dialog.component.html',
styleUrls: ['./upload-dialog.component.css'],
styleUrls: ['./upload-dialog.component.scss'],
changeDetection: ChangeDetectionStrategy.Default,
})
export class UploadDialogComponent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
color="primary"
class="entry-point-button"
(click)="upload()">
<mat-icon fontIcon="input"></mat-icon>
<mat-icon svgIcon="input"></mat-icon>
<span class="ml-3">Load...</span>
</button>
<div class="col"></div>
Expand All @@ -39,7 +39,7 @@
color="primary"
class="entry-point-button"
(click)="newScenario()">
<mat-icon fontIcon="add"></mat-icon>
<mat-icon svgIcon="add"></mat-icon>
<span class="ml-2">Create new</span>
</button>
</div>
Expand All @@ -48,7 +48,7 @@
class="col cloud-invisible"
[ngClass]="{ 'cloud-visible': (hasStorageApi$ | async) && (allowUserStorage$ | async) }">
<a class="cloud-button" (click)="loadFromStorage()">
<mat-icon fontIcon="bookmark"></mat-icon>
<mat-icon svgIcon="bookmark"></mat-icon>
Open from a Cloud Project
</a>
</div>
Expand Down
4 changes: 4 additions & 0 deletions application/frontend/src/assets/images/help-filled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion application/frontend/src/assets/images/zip.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions application/frontend/src/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -886,3 +886,7 @@ app-bulk-edit-unset {
.strong {
font-weight: 500 !important;
}

.blue-svg-icon mat-icon svg path {
fill: $blue;
}

0 comments on commit cbcc524

Please sign in to comment.