Update frontend to use update models.
Add delete funtionality to Assets and Devices. Fix bug with switching between views in assets list and devices list Fix bug with editing owner user. Fix bugs with dispatching.
This commit is contained in:
Родитель
23e0b213d5
Коммит
2a7eb9eed2
|
@ -2,24 +2,36 @@
|
|||
Licensed under the MIT License. -->
|
||||
|
||||
<mat-toolbar color="primary">
|
||||
<span>Add asset:</span>
|
||||
<span>{{isEditable ? 'Edit Asset' : 'Add Asset'}}</span>
|
||||
<span class="toolbar-spacer"></span>
|
||||
<a *ngIf="isEditable" [appRoleLimiter]="Roles.Administrator" mat-icon-button mat-tooltip="Delete Asset" (click)="deleteAsset()">
|
||||
<mat-icon>delete_forever</mat-icon>
|
||||
</a>
|
||||
</mat-toolbar>
|
||||
|
||||
<section>
|
||||
<form (submit)="submit()">
|
||||
<mat-input-container>
|
||||
<input matInput placeholder="Asset Name" [(ngModel)]="asset.id" [disabled]="isEditable" name="id" required>
|
||||
<mat-input-container *ngIf="isEditable">
|
||||
<input matInput placeholder="Asset Id" [(ngModel)]="asset.id" disabled name="id">
|
||||
</mat-input-container>
|
||||
|
||||
<mat-input-container>
|
||||
<mat-select *ngIf="!isEditable" placeholder="Asset Type" [(ngModel)]="asset.assetType" name="assetType" required>
|
||||
<input matInput placeholder="Asset Name" [(ngModel)]="asset.name" name="name" required>
|
||||
</mat-input-container>
|
||||
|
||||
<mat-input-container>
|
||||
<mat-select placeholder="Asset Type" [(ngModel)]="asset.assetType" name="assetType" [disabled]="isEditable" required>
|
||||
<mat-option [value]="AssetType.Car">Car</mat-option>
|
||||
<mat-option [value]="AssetType.Truck">Truck</mat-option>
|
||||
</mat-select>
|
||||
</mat-input-container>
|
||||
|
||||
<mat-input-container *ngIf="asset.trackingDeviceId">
|
||||
<input matInput placeholder="Tracking Device" [(ngModel)]="asset.trackingDeviceName" name="trackingDevice" disabled>
|
||||
<mat-input-container>
|
||||
<mat-select placeholder="Linked Device" [(ngModel)]="asset.trackingDeviceId" name="trackingDeviceId">
|
||||
<mat-option *ngFor="let device of devices" [value]="device.id">
|
||||
{{device.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-input-container>
|
||||
|
||||
<div *ngIf="asset.assetType == AssetType.Truck" class="truck-container">
|
||||
|
@ -66,7 +78,7 @@
|
|||
|
||||
<div class="pull-right">
|
||||
<a mat-raised-button [routerLink]="['/assets']">Back</a>
|
||||
<button *ngIf="!isEditable" mat-raised-button class="dispatch-button" type="submit">Submit</button>
|
||||
<button mat-raised-button class="dispatch-button" type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
|
@ -7,8 +7,11 @@ import { Subscription } from 'rxjs/Subscription';
|
|||
import { ToasterService } from 'angular2-toaster';
|
||||
|
||||
import { Asset, AssetType } from '../asset';
|
||||
import { Roles } from '../../shared/role';
|
||||
import { AssetProperties } from '../../shared/asset-properties';
|
||||
import { AssetService } from '../asset.service';
|
||||
import { Device } from '../../devices/device';
|
||||
import { DeviceService } from '../../devices/device.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-asset-editor-dialog',
|
||||
|
@ -18,15 +21,18 @@ import { AssetService } from '../asset.service';
|
|||
|
||||
export class AssetEditorComponent implements OnInit, OnDestroy {
|
||||
asset: Asset;
|
||||
devices: Device[];
|
||||
isEditable: boolean;
|
||||
assetProperties: AssetProperties;
|
||||
AssetType = AssetType;
|
||||
private routerSubscription: Subscription;
|
||||
private assetSubscription: Subscription;
|
||||
Roles = Roles;
|
||||
private isAlive: boolean;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private assetService: AssetService,
|
||||
private deviceService: DeviceService,
|
||||
private toasterService: ToasterService) {
|
||||
this.asset = new Asset();
|
||||
this.asset.assetType = AssetType.Car;
|
||||
|
@ -34,21 +40,30 @@ export class AssetEditorComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.routerSubscription = this.route.params.subscribe(params => {
|
||||
const id = params['id'];
|
||||
if (id) {
|
||||
this.isEditable = true;
|
||||
this.assetSubscription = this.assetService.getAsset(id).subscribe(asset => this.asset = asset);
|
||||
}
|
||||
});
|
||||
this.isAlive = true;
|
||||
|
||||
this.route.params
|
||||
.takeWhile(() => this.isAlive)
|
||||
.subscribe(params => {
|
||||
const id = params['id'];
|
||||
if (id) {
|
||||
this.isEditable = true;
|
||||
this.assetService.getAsset(id)
|
||||
.takeWhile(() => this.isAlive)
|
||||
.subscribe(asset => {
|
||||
this.asset = asset;
|
||||
this.assetProperties = this.asset.assetProperties;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.deviceService.getDevices()
|
||||
.takeWhile(() => this.isAlive)
|
||||
.subscribe(devices => this.devices = devices);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.routerSubscription.unsubscribe();
|
||||
|
||||
if (this.assetSubscription && !this.assetSubscription.closed) {
|
||||
this.assetSubscription.unsubscribe();
|
||||
}
|
||||
this.isAlive = false;
|
||||
}
|
||||
|
||||
submit() {
|
||||
|
@ -56,9 +71,19 @@ export class AssetEditorComponent implements OnInit, OnDestroy {
|
|||
this.asset.assetProperties = this.assetProperties;
|
||||
}
|
||||
|
||||
this.assetService.addAsset(this.asset)
|
||||
.subscribe(() => this.router.navigate(['/assets']), error => {
|
||||
this.toasterService.pop('error', 'Invalid Input', 'Asset ID already exists');
|
||||
});
|
||||
if (this.isEditable) {
|
||||
this.assetService.updateAsset(this.asset)
|
||||
.subscribe(() => this.router.navigate(['/assets']));
|
||||
} else {
|
||||
this.assetService.addAsset(this.asset)
|
||||
.subscribe(() => this.router.navigate(['/assets']), error => {
|
||||
this.toasterService.pop('error', 'Invalid Input', 'Asset ID already exists');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
deleteAsset() {
|
||||
this.assetService.deleteAsset(this.asset)
|
||||
.subscribe(() => this.router.navigate(['/assets']));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
<mat-icon>add_circle</mat-icon>
|
||||
</a>
|
||||
<button mat-icon-button>
|
||||
<mat-icon>info</mat-icon>
|
||||
</button>
|
||||
<mat-icon>info</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
|
||||
<mat-input-container>
|
||||
|
@ -17,18 +17,18 @@
|
|||
</mat-input-container>
|
||||
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let asset of assets | async | filterList:filter" [class.active]="asset == selectedAsset && isAssetListSeleceted()">
|
||||
<h3 mat-line (click)="showAsset(asset)">{{asset.id}}</h3>
|
||||
<span mat-line class="subtle" (click)="showAsset(asset)">device: {{asset.trackingDeviceName}}</span>
|
||||
<mat-list-item *ngFor="let asset of assetsList | filterList:filter" [class.active]="asset == selectedAsset && isAssetListSeleceted()">
|
||||
<h3 mat-line (click)="showAsset(asset)">{{asset.name}}</h3>
|
||||
<span mat-line class="subtle" (click)="showAsset(asset)">device: {{asset.trackingDevice ? asset.trackingDevice.name : ''}}</span>
|
||||
<button mat-icon-button mat-tooltip='Trips' (click)="showTrips(asset)" [class.active]="asset == selectedAsset && isAssetTripsSelected()">
|
||||
<mat-icon>trending_up</mat-icon>
|
||||
</button>
|
||||
<mat-icon>trending_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button mat-tooltip='Points' (click)="showPoints(asset)" [class.active]="asset == selectedAsset && isAssetPointsSelected()">
|
||||
<mat-icon>gps_fixed</mat-icon>
|
||||
</button>
|
||||
<!--<a mat-icon-button [routerLink]="['/assets', asset.id]">
|
||||
<mat-icon>mode_edit</mat-icon>
|
||||
</a>-->
|
||||
<mat-icon>gps_fixed</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button mat-tooltip='Edit' [routerLink]="['/assets', asset.id]">
|
||||
<mat-icon>mode_edit</mat-icon>
|
||||
</button>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/* tslint:disable:no-unused-variable */
|
||||
import { Injectable } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { Asset, AssetType } from '../asset';
|
||||
import { AssetEditorComponent } from '../asset-editor/asset-editor.component';
|
||||
import { AssetListComponent } from './asset-list.component';
|
||||
import { AssetService } from '../asset.service';
|
||||
import { MapsService } from '../../maps/maps.service';
|
||||
|
||||
import 'hammerjs';
|
||||
import 'rxjs/add/observable/of';
|
||||
|
||||
@Injectable()
|
||||
export class MockAssetService {
|
||||
getAssets(): Observable<Asset[]> {
|
||||
return Observable.of([
|
||||
{
|
||||
id: 'bus99',
|
||||
trackingDeviceName: 'cairo phone',
|
||||
assetType: AssetType.Car,
|
||||
assetProperties: {}
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
describe('AssetListComponent', () => {
|
||||
let component: AssetListComponent;
|
||||
let fixture: ComponentFixture<AssetListComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AssetListComponent],
|
||||
providers: [
|
||||
MapsService,
|
||||
{ provide: AssetService, useClass: MockAssetService }
|
||||
],
|
||||
imports: [
|
||||
FormsModule
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AssetListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -29,8 +29,6 @@ enum SelectedAssetState {
|
|||
styleUrls: ['./asset-list.component.css']
|
||||
})
|
||||
export class AssetListComponent implements OnInit, OnDestroy {
|
||||
|
||||
assets: Observable<Asset[]>;
|
||||
points: Point[];
|
||||
trips: Trip[];
|
||||
filter: string;
|
||||
|
@ -54,13 +52,16 @@ export class AssetListComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.assets = this.assetService.getAssets();
|
||||
this.assets
|
||||
this.assetService.getAssets()
|
||||
.takeWhile(() => this.isAlive)
|
||||
.skipWhile(assets => assets.length === 0)
|
||||
.take(1)
|
||||
.subscribe(assets => {
|
||||
this.assetsList = assets;
|
||||
this.assetsList = assets.sort((a, b) => {
|
||||
if (a.name < b.name) { return -1; }
|
||||
if (a.name > b.name) { return 1; }
|
||||
return 0;
|
||||
});
|
||||
this.showAllAssets();
|
||||
});
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ export class AssetListComponent implements OnInit, OnDestroy {
|
|||
} else {
|
||||
this.selectedAsset = asset;
|
||||
this.selectedAssetState = SelectedAssetState.PointsSelected;
|
||||
this.toasterService.pop('info', '', 'Showing latest points of \" ' + this.selectedAsset.id + ' \"');
|
||||
this.toasterService.pop('info', '', 'Showing latest points of \" ' + this.selectedAsset.name + ' \"');
|
||||
this.unsubscribe();
|
||||
this.subscription = this.assetService.getPoints(asset.id, this.selectedDateRange)
|
||||
.subscribe(points => {
|
||||
|
@ -98,7 +99,7 @@ export class AssetListComponent implements OnInit, OnDestroy {
|
|||
this.selectedAsset = asset;
|
||||
this.selectedAssetState = SelectedAssetState.ListSelected;
|
||||
this.showAllAssets();
|
||||
this.toasterService.pop('info', '', 'Following asset ' + this.selectedAsset.id);
|
||||
this.toasterService.pop('info', '', 'Following asset ' + this.selectedAsset.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,10 +109,10 @@ export class AssetListComponent implements OnInit, OnDestroy {
|
|||
.subscribe(points => {
|
||||
this.mapsService.showAssetsPositions(points);
|
||||
|
||||
if (this.selectedAsset && !points[this.selectedAsset.id]) {
|
||||
this.toasterService.pop('error', '', 'Can\'t find position of ' + this.selectedAsset.id);
|
||||
if (this.selectedAsset && !points[this.selectedAsset.name]) {
|
||||
this.toasterService.pop('error', '', 'Can\'t find position of ' + this.selectedAsset.name);
|
||||
} else if (this.selectedAsset) {
|
||||
this.mapsService.showAsset([this.selectedAsset, points[this.selectedAsset.id]]);
|
||||
this.mapsService.showAsset([this.selectedAsset, points[this.selectedAsset.name]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -126,7 +127,7 @@ export class AssetListComponent implements OnInit, OnDestroy {
|
|||
} else {
|
||||
this.selectedAsset = asset;
|
||||
this.selectedAssetState = SelectedAssetState.TripsSelected;
|
||||
this.toasterService.pop('info', '', 'Showing latest trips of ' + this.selectedAsset.id);
|
||||
this.toasterService.pop('info', '', 'Showing latest trips of ' + this.selectedAsset.name);
|
||||
this.unsubscribe();
|
||||
this.subscription = this.assetService.getTrips(asset.id, this.selectedDateRange)
|
||||
.subscribe(trips => {
|
||||
|
|
|
@ -21,6 +21,14 @@ export class AssetService {
|
|||
return this.dataService.post<Asset>('assets', asset);
|
||||
}
|
||||
|
||||
updateAsset(asset: Asset): Observable<void> {
|
||||
return this.dataService.put<Asset>('assets', asset.id, asset, true);
|
||||
}
|
||||
|
||||
deleteAsset(asset: Asset): Observable<void> {
|
||||
return this.dataService.delete<Asset>('assets', asset.id);
|
||||
}
|
||||
|
||||
getAssets(): Observable<Asset[]> {
|
||||
return this.dataService.get<Asset>('assets');
|
||||
}
|
||||
|
@ -57,7 +65,7 @@ export class AssetService {
|
|||
}
|
||||
|
||||
return trips.filter(t => {
|
||||
return t.startTimeStampUtc >= +dateRange.from && t.startTimeStampUtc <= +dateRange.to;
|
||||
return Date.parse(t.startTimeUtc) >= +dateRange.from && Date.parse(t.startTimeUtc) <= +dateRange.to;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
Licensed under the MIT License. -->
|
||||
|
||||
<mat-toolbar color="primary">
|
||||
<span *ngIf="!isEditing">Add device</span>
|
||||
<span *ngIf="isEditing">Edit Device</span>
|
||||
<span>{{isEditing ? 'Edit Device' : 'Add Device'}}</span>
|
||||
<span class="toolbar-spacer"></span>
|
||||
<a *ngIf="isEditing" [appRoleLimiter]="Roles.Administrator" mat-icon-button mat-tooltip="Delete Asset" (click)="deleteDevice()">
|
||||
<mat-icon>delete_forever</mat-icon>
|
||||
</a>
|
||||
</mat-toolbar>
|
||||
|
||||
<section>
|
||||
|
@ -39,7 +42,7 @@
|
|||
<mat-input-container>
|
||||
<mat-select placeholder="Linked Asset" [(ngModel)]="device.assetId" name="assetId">
|
||||
<mat-option *ngFor="let asset of assets" [value]="asset.id">
|
||||
{{asset.id}}
|
||||
{{asset.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-input-container>
|
||||
|
|
|
@ -9,6 +9,7 @@ import { ToasterService } from 'angular2-toaster';
|
|||
import { HubConnection } from '@aspnet/signalr-client';
|
||||
import { UUID } from 'angular2-uuid';
|
||||
|
||||
import { Roles } from '../../shared/role';
|
||||
import { Asset } from '../../assets/asset';
|
||||
import { AssetService } from '../../assets/asset.service';
|
||||
import { Device } from '../device';
|
||||
|
@ -26,6 +27,7 @@ export class DeviceEditorComponent implements OnInit, OnDestroy {
|
|||
isEditing: boolean;
|
||||
assets: Asset[];
|
||||
deviceToken = '';
|
||||
Roles = Roles;
|
||||
|
||||
private routerSubscription: Subscription;
|
||||
private assetsSubscription: Subscription;
|
||||
|
@ -111,4 +113,9 @@ export class DeviceEditorComponent implements OnInit, OnDestroy {
|
|||
data: this.deviceService.getProvisioningQrCodeUrl(this.nonce)
|
||||
});
|
||||
}
|
||||
|
||||
deleteDevice() {
|
||||
this.deviceService.deleteDevice(this.device)
|
||||
.subscribe(() => this.router.navigate(['/devices']));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
<mat-list>
|
||||
<mat-list-item *ngFor="let device of devices | async | filterList:filter" [class.active]="device == selectedDevice && isDeviceListSelected()">
|
||||
<h3 mat-line (click)="showDevice(device)">{{device.name}}</h3>
|
||||
<span mat-line class="subtle" (click)="showDevice(device)">asset: {{device.assetId}}</span>
|
||||
<span mat-line class="subtle" (click)="showDevice(device)">asset: {{device.asset ? device.asset.name : ''}}</span>
|
||||
<button mat-icon-button mat-tooltip='Points' (click)="showPoints(device)" [class.active]="device == selectedDevice && isDevicePointSelected()">
|
||||
<mat-icon>gps_fixed</mat-icon>
|
||||
</button>
|
||||
<a [appRoleLimiter]="Roles.Administrator" mat-icon-button mat-tooltip="Edit" [routerLink]="['/devices', device.id]">
|
||||
<mat-icon>mode_edit</mat-icon>
|
||||
</a>
|
||||
<button mat-icon-button mat-tooltip='Points' (click)="showPoints(device)" [class.active]="device == selectedDevice && isDevicePointSelected()">
|
||||
<mat-icon>gps_fixed</mat-icon>
|
||||
</button>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/* tslint:disable:no-unused-variable */
|
||||
import { Injectable } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { Device } from '../device';
|
||||
import { DeviceEditorComponent } from '../device-editor/device-editor.component';
|
||||
import { DeviceListComponent } from './device-list.component';
|
||||
import { DeviceService } from '../device.service';
|
||||
import { MapsService } from '../../maps/maps.service';
|
||||
|
||||
import 'hammerjs';
|
||||
import 'rxjs/add/observable/of';
|
||||
|
||||
@Injectable()
|
||||
export class MockDeviceService {
|
||||
getDevices(): Observable<Device[]> {
|
||||
return Observable.of([
|
||||
{
|
||||
id: 'cairo phone',
|
||||
assetId: 'bus66'
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
describe('DeviceListComponent', () => {
|
||||
let component: DeviceListComponent;
|
||||
let fixture: ComponentFixture<DeviceListComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [DeviceListComponent, DeviceEditorComponent],
|
||||
providers: [
|
||||
MapsService,
|
||||
{ provide: DeviceService, useClass: MockDeviceService }
|
||||
],
|
||||
imports: [
|
||||
FormsModule
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DeviceListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -57,6 +57,10 @@ export class DeviceService {
|
|||
return this.dataService.put<Device>('devices', device.id, device, true);
|
||||
}
|
||||
|
||||
deleteDevice(device: Device): Observable<void> {
|
||||
return this.dataService.delete<Device>('devices', device.id);
|
||||
}
|
||||
|
||||
getProvisioningQrCodeUrl(nonce: String): string {
|
||||
return `${this.envSettingsService.getEnvironmentVariable(EnvironmentSettings.backendUrl)}/devices/qrcode?nonce=${nonce}`;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<mat-input-container>
|
||||
<mat-select placeholder="Asset" [(ngModel)]="selectedAsset" name="assetId" required="true">
|
||||
<mat-option *ngFor="let asset of assets" [value]="asset" (click)="checkSelected(asset)">
|
||||
{{asset.id}}
|
||||
{{asset.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-input-container>
|
||||
|
|
|
@ -134,7 +134,6 @@ export class DispatchingEditorComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
showRoute() {
|
||||
|
||||
if (this.pinsAdded.length < 2 || this.pinsAdded.length > 20) {
|
||||
this.toasterService.pop('error', 'Invalid Input', 'Number of Points per route has to be between 2 and 20');
|
||||
return;
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<h3>Available Assets:</h3>
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let asset of assets">
|
||||
<mat-checkbox (change)="onAssetCheckChanged($event)" [checked]="asset.checked" [name]="asset.id">{{asset.id}}</mat-checkbox>
|
||||
<mat-checkbox (change)="onAssetCheckChanged($event)" [checked]="asset.checked" [name]="asset.id">{{asset.name}}</mat-checkbox>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
<input matInput placeholder="Location Pin" [(ngModel)]="locationString" name="locationPin" disabled required>
|
||||
</mat-input-container>
|
||||
|
||||
<mat-input-container *ngIf="isEditable">
|
||||
<input matInput placeholder="Location Type" [(ngModel)]="locationTypeString" name="interestLevel" disabled>
|
||||
</mat-input-container>
|
||||
|
||||
<div class="pull-right">
|
||||
<a mat-raised-button [routerLink]="['/locations']">Back</a>
|
||||
<button mat-raised-button class="dispatch-button " type="submit">Submit</button>
|
||||
|
|
|
@ -49,7 +49,6 @@ export class LocationEditorComponent implements OnInit, OnDestroy {
|
|||
if (location) {
|
||||
this.location = location;
|
||||
this.setlocationString();
|
||||
this.setLocationTypeString();
|
||||
this.mapService.showLocationsPositions([this.location]);
|
||||
}
|
||||
});
|
||||
|
@ -97,13 +96,9 @@ export class LocationEditorComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
if (this.isEditable) {
|
||||
if (this.didLocationChange) {
|
||||
this.location.interestLevel = InterestLevel.Manual;
|
||||
}
|
||||
this.locationService.updateLocation(this.location)
|
||||
.subscribe(() => this.router.navigate(['/locations']));
|
||||
} else {
|
||||
this.location.interestLevel = InterestLevel.Manual;
|
||||
this.locationService.addLocation(this.location)
|
||||
.subscribe(() => this.router.navigate(['/locations']));
|
||||
}
|
||||
|
@ -112,12 +107,4 @@ export class LocationEditorComponent implements OnInit, OnDestroy {
|
|||
private setlocationString() {
|
||||
this.locationString = '(' + this.location.latitude + ' , ' + this.location.longitude + ' )';
|
||||
}
|
||||
|
||||
private setLocationTypeString() {
|
||||
if (this.location.interestLevel === InterestLevel.Manual) {
|
||||
this.locationTypeString = 'Created/Edited Manually';
|
||||
} else {
|
||||
this.locationTypeString = 'Automatically Generated';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -433,7 +433,7 @@ export class BingMapsService {
|
|||
strokeThickness: 2
|
||||
});
|
||||
|
||||
this.map.entities.push(polyline);
|
||||
this.locationsLayer.add(polyline);
|
||||
this.centerMap(points[0]);
|
||||
}
|
||||
});
|
||||
|
@ -441,13 +441,7 @@ export class BingMapsService {
|
|||
|
||||
showDispatchingRoutePins(locations: Location[]) {
|
||||
this.load().then(() => {
|
||||
this.resetMap();
|
||||
this.locationsLayer.setVisible(true);
|
||||
this.locationsLayer.clear();
|
||||
|
||||
let index = 1;
|
||||
locations.forEach(location => {
|
||||
location.name = this.getNormalizedLocationName(location) + ' (' + index++ + ')';
|
||||
this.showLocation(location);
|
||||
});
|
||||
});
|
||||
|
@ -534,9 +528,9 @@ export class BingMapsService {
|
|||
/* END POINT FUNCTIONS */
|
||||
|
||||
/* ASSET FUNCTIONS */
|
||||
showAssets(positions: [Asset, TrackingPoint][], centerMap: boolean): void {
|
||||
showAssets(positions: [Asset, TrackingPoint][], centerMap: boolean, clearMap: boolean): void {
|
||||
this.load().then(() => {
|
||||
if (centerMap) {
|
||||
if (clearMap) {
|
||||
this.resetMap();
|
||||
this.assetsLayer.setVisible(true);
|
||||
}
|
||||
|
@ -551,7 +545,7 @@ export class BingMapsService {
|
|||
points.push(p);
|
||||
const location = new Microsoft.Maps.Location(p.latitude, p.longitude);
|
||||
const pushpin = new Microsoft.Maps.Pushpin(location, {
|
||||
title: position[0].id,
|
||||
title: position[0].name,
|
||||
subTitle: this.timeConverter(p.time),
|
||||
icon:
|
||||
(position[0].assetType === AssetType.Car
|
||||
|
@ -570,9 +564,9 @@ export class BingMapsService {
|
|||
/* END ASSET FUNCTIONS */
|
||||
|
||||
/* DEVICE FUNCTIONS */
|
||||
showDevices(positions: Map<string, TrackingPoint>, centerMap: boolean): void {
|
||||
showDevices(positions: Map<string, TrackingPoint>, centerMap: boolean, clearMap: boolean): void {
|
||||
this.load().then(() => {
|
||||
if (centerMap) {
|
||||
if (clearMap) {
|
||||
this.resetMap();
|
||||
this.devicesLayer.setVisible(true);
|
||||
}
|
||||
|
@ -666,7 +660,7 @@ export class BingMapsService {
|
|||
const tripLegLocations = [];
|
||||
|
||||
// Show the starting stop in a leg if its different from the ending stop of the last
|
||||
if (!previousTripLeg || previousTripLeg.endLocationId !== leg.startLocationId) {
|
||||
if (!previousTripLeg || previousTripLeg.endLocation.id !== leg.startLocation.id) {
|
||||
this.showTripLocation(leg.startLocation);
|
||||
tripLegLocations.push(new Microsoft.Maps.Location(
|
||||
leg.startLocation.latitude,
|
||||
|
@ -699,7 +693,7 @@ export class BingMapsService {
|
|||
previousTripLeg = leg;
|
||||
|
||||
// Draw a dotted line between trip leg stop locations, if they are not the same.
|
||||
if (previousTripLeg && previousTripLeg.endLocationId !== leg.startLocationId) {
|
||||
if (previousTripLeg && previousTripLeg.endLocation.id !== leg.startLocation.id) {
|
||||
const startPoint = new Microsoft.Maps.Location(
|
||||
leg.startLocation.latitude,
|
||||
leg.startLocation.longitude
|
||||
|
@ -747,7 +741,7 @@ export class BingMapsService {
|
|||
}
|
||||
|
||||
// Draw a dotted line between trip leg stop locations, if they are not the same.
|
||||
if (previousTripLeg && previousTripLeg.endLocationId !== leg.startLocationId) {
|
||||
if (previousTripLeg && previousTripLeg.endLocation.id !== leg.startLocation.id) {
|
||||
const startPoint = new Microsoft.Maps.Location(
|
||||
leg.startLocation.latitude,
|
||||
leg.startLocation.longitude
|
||||
|
|
|
@ -5,6 +5,7 @@ import { Local } from 'protractor/built/driverProviders';
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { ReplaySubject } from 'rxjs/ReplaySubject';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
import { Point } from '../shared/point';
|
||||
|
@ -18,33 +19,33 @@ import { Asset } from '../assets/asset';
|
|||
@Injectable()
|
||||
export class MapsService {
|
||||
|
||||
private points = new Subject<Point[]>();
|
||||
private trips = new Subject<Trip[]>();
|
||||
private trip = new Subject<Trip>();
|
||||
private geofence = new Subject<Geofence>();
|
||||
private geofences = new Subject<Geofence[]>();
|
||||
private currentDrawEnd = new Subject();
|
||||
private geofenceCircularRadiusChange = new Subject<number>();
|
||||
private geofenceCircularDraw = new Subject<[Point, number]>();
|
||||
private points = new ReplaySubject<Point[]>();
|
||||
private trips = new ReplaySubject<Trip[]>();
|
||||
private trip = new ReplaySubject<Trip>();
|
||||
private geofence = new ReplaySubject<Geofence>();
|
||||
private geofences = new ReplaySubject<Geofence[]>();
|
||||
private currentDrawEnd = new ReplaySubject();
|
||||
private geofenceCircularRadiusChange = new ReplaySubject<number>();
|
||||
private geofenceCircularDraw = new ReplaySubject<[Point, number]>();
|
||||
private geofenceCircularDrawResult = new BehaviorSubject<Point>(null);
|
||||
private geofencePolygonDraw = new Subject<Point[]>();
|
||||
private geofencePolygonDraw = new ReplaySubject<Point[]>();
|
||||
private geofencePolygonDrawResult = new BehaviorSubject<Point[]>(new Array<Point>());
|
||||
private assetsPositions = new Subject<[{ [key: string]: TrackingPoint }, boolean]>();
|
||||
private assetPosition = new Subject<[Asset, TrackingPoint]>();
|
||||
private devicesPositions = new Subject<Map<string, TrackingPoint>>();
|
||||
private devicePosition = new Subject<[string, TrackingPoint]>();
|
||||
private dispatchingPinsDraw = new Subject<Location[]>();
|
||||
private assetsPositions = new ReplaySubject<[{ [key: string]: TrackingPoint }, boolean]>();
|
||||
private assetPosition = new ReplaySubject<[Asset, TrackingPoint]>();
|
||||
private devicesPositions = new ReplaySubject<[Map<string, TrackingPoint>, boolean]>();
|
||||
private devicePosition = new ReplaySubject<[string, TrackingPoint]>();
|
||||
private dispatchingPinsDraw = new ReplaySubject<Location[]>();
|
||||
private dispatchingPinsDrawResult = new BehaviorSubject<Location[]>(new Array<Location>());
|
||||
private dispatchingPoints = new Subject<Point[]>();
|
||||
private dispatchingAlternativePoints = new Subject<Point[]>();
|
||||
private dispatchingPins = new Subject<Location[]>();
|
||||
private locationsPositions = new Subject<Location[]>();
|
||||
private locationPosition = new Subject<Location>();
|
||||
private locationPinDraw = new Subject<Location>();
|
||||
private locationPinResult = new Subject<Location>();
|
||||
private itineraryPoint = new Subject<Point>();
|
||||
private locationSearchQuery = new Subject<string>();
|
||||
private locationSearchResult = new Subject<Point>();
|
||||
private dispatchingPoints = new ReplaySubject<Point[]>();
|
||||
private dispatchingAlternativePoints = new ReplaySubject<Point[]>();
|
||||
private dispatchingPins = new ReplaySubject<Location[]>();
|
||||
private locationsPositions = new ReplaySubject<Location[]>();
|
||||
private locationPosition = new ReplaySubject<Location>();
|
||||
private locationPinDraw = new ReplaySubject<Location>();
|
||||
private locationPinResult = new ReplaySubject<Location>();
|
||||
private itineraryPoint = new ReplaySubject<Point>();
|
||||
private locationSearchQuery = new ReplaySubject<string>();
|
||||
private locationSearchResult = new ReplaySubject<Point>();
|
||||
|
||||
private routeColor: number;
|
||||
|
||||
|
@ -90,8 +91,8 @@ export class MapsService {
|
|||
this.assetPosition.next(position);
|
||||
}
|
||||
|
||||
showDevicesPositions(positions: Map<string, TrackingPoint>) {
|
||||
this.devicesPositions.next(positions);
|
||||
showDevicesPositions(positions: Map<string, TrackingPoint>, inBackground = false) {
|
||||
this.devicesPositions.next([positions, inBackground]);
|
||||
}
|
||||
|
||||
showDevice(position: [string, TrackingPoint]) {
|
||||
|
@ -107,11 +108,11 @@ export class MapsService {
|
|||
}
|
||||
|
||||
startLocationPinDraw() {
|
||||
this.locationPinDraw.next();
|
||||
this.locationPinDraw.next(null);
|
||||
}
|
||||
|
||||
endCurrentDraw() {
|
||||
this.currentDrawEnd.next();
|
||||
this.currentDrawEnd.next(null);
|
||||
}
|
||||
|
||||
showTrips(trips: Trip[]) {
|
||||
|
@ -156,7 +157,7 @@ export class MapsService {
|
|||
return this.assetPosition.asObservable();
|
||||
}
|
||||
|
||||
getDevicesPositions(): Observable<Map<string, TrackingPoint>> {
|
||||
getDevicesPositions(): Observable<[Map<string, TrackingPoint>, boolean]> {
|
||||
return this.devicesPositions.asObservable();
|
||||
}
|
||||
|
||||
|
|
|
@ -147,24 +147,29 @@ export class MapsComponent implements OnInit {
|
|||
const mappedAssets = new Array<[Asset, TrackingPoint]>();
|
||||
for (const k of Object.keys(positions)) {
|
||||
const value = positions[k];
|
||||
const asset = assets.find(val => val.id === k);
|
||||
mappedAssets.push([asset, value]);
|
||||
const asset = assets.find(val => val.name === k);
|
||||
if (asset) {
|
||||
mappedAssets.push([asset, value]);
|
||||
}
|
||||
}
|
||||
|
||||
this.bingMapsService.showAssets(
|
||||
mappedAssets,
|
||||
!data[1] && lastPositionCall !== 'assets'
|
||||
!data[1] && lastPositionCall !== 'assets',
|
||||
!data[1]
|
||||
);
|
||||
|
||||
lastPositionCall = 'assets';
|
||||
});
|
||||
|
||||
this.mapsService.getDevicesPositions().subscribe(positions => {
|
||||
this.mapsService.getDevicesPositions().subscribe(data => {
|
||||
this.bingMapsService.showDevices(
|
||||
positions,
|
||||
lastPositionCall !== 'devcies'
|
||||
data[0],
|
||||
!data[1] && lastPositionCall !== 'devices',
|
||||
!data[1]
|
||||
);
|
||||
lastPositionCall = 'devcies';
|
||||
|
||||
lastPositionCall = 'devices';
|
||||
});
|
||||
|
||||
this.mapsService.getLocationsPositions().subscribe(positions => {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<a class="partial-button" (click)="regenerateToken()">Regenerate</a>
|
||||
</mat-input-container>
|
||||
|
||||
<mat-input-container [hidden]="user.role.name === 'Owner'">
|
||||
<mat-input-container *ngIf="user.role.name !== 'Owner'">
|
||||
<mat-select placeholder="Role" [(ngModel)]="user.role.name" name="role" [required]="isAddingNew">
|
||||
<mat-option *ngFor="let role of roles" [value]="role.name">
|
||||
{{role.name}}
|
||||
|
|
Загрузка…
Ссылка в новой задаче