Commit 632c4ac2ffc20e2b051533b741377e5cc2b35dca

Authored by lsagona
1 parent c666d6db69
Exists in master

import vessels

Showing 53 changed files with 842 additions and 251 deletions Side-by-side Diff

angular.json View file @ 632c4ac
... ... @@ -31,7 +31,10 @@
31 31 "node_modules/bootstrap/dist/css/bootstrap.css",
32 32 "src/styles.scss"
33 33 ],
34   - "scripts": []
  34 + "scripts": [
  35 + "node_modules/jquery/dist/jquery.min.js",
  36 + "node_modules/bootstrap/dist/js/bootstrap.min.js"
  37 + ]
35 38 },
36 39 "configurations": {
37 40 "production": {
package-lock.json View file @ 632c4ac
... ... @@ -6674,6 +6674,11 @@
6674 6674 }
6675 6675 }
6676 6676 },
  6677 + "jquery": {
  6678 + "version": "3.5.1",
  6679 + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
  6680 + "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
  6681 + },
6677 6682 "js-tokens": {
6678 6683 "version": "4.0.0",
6679 6684 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
... ... @@ -7830,6 +7835,29 @@
7830 7835 "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
7831 7836 "dev": true
7832 7837 },
  7838 + "ngx-bootstrap-icons": {
  7839 + "version": "1.2.0",
  7840 + "resolved": "https://registry.npmjs.org/ngx-bootstrap-icons/-/ngx-bootstrap-icons-1.2.0.tgz",
  7841 + "integrity": "sha512-e6AT33wrhZfUEahZoZoVji2Nk2twj0GlPeusf6sW2Ebds9eeN3tBoSCE4kqLEZHS1B/6eOw8jDdOhKYhRPSgLw==",
  7842 + "requires": {
  7843 + "tslib": "^2.0.0"
  7844 + }
  7845 + },
  7846 + "ngx-dropzone": {
  7847 + "version": "2.2.2",
  7848 + "resolved": "https://registry.npmjs.org/ngx-dropzone/-/ngx-dropzone-2.2.2.tgz",
  7849 + "integrity": "sha512-REuBcPNTY33OtcZD6dw8Fq/jFqwviiYydYaCn74yig8TvDDYhtJ/BPjtvbw7uEgF4BJr/UEHbKMvkdZIyCgsww==",
  7850 + "requires": {
  7851 + "tslib": "^1.9.0"
  7852 + },
  7853 + "dependencies": {
  7854 + "tslib": {
  7855 + "version": "1.14.1",
  7856 + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
  7857 + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
  7858 + }
  7859 + }
  7860 + },
7833 7861 "nice-try": {
7834 7862 "version": "1.0.5",
7835 7863 "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
... ... @@ -8865,6 +8893,11 @@
8865 8893 "requires": {
8866 8894 "ts-pnp": "^1.1.6"
8867 8895 }
  8896 + },
  8897 + "popper.js": {
  8898 + "version": "1.16.1",
  8899 + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
  8900 + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
8868 8901 },
8869 8902 "portfinder": {
8870 8903 "version": "1.0.28",
package.json View file @ 632c4ac
... ... @@ -20,6 +20,10 @@
20 20 "@angular/platform-browser-dynamic": "~10.2.0",
21 21 "@angular/router": "~10.2.0",
22 22 "bootstrap": "^4.5.3",
  23 + "jquery": "^3.5.1",
  24 + "ngx-bootstrap-icons": "^1.2.0",
  25 + "ngx-dropzone": "^2.2.2",
  26 + "popper.js": "^1.16.1",
23 27 "rxjs": "^6.6.3",
24 28 "tslib": "^2.0.0",
25 29 "zone.js": "~0.10.2"
src/app/app-routing.module.ts View file @ 632c4ac
1   -import { NgModule } from '@angular/core';
2   -import { Routes, RouterModule } from '@angular/router';
3   -
4   -const routes: Routes = [];
5   -
6   -@NgModule({
7   - imports: [RouterModule.forRoot(routes)],
8   - exports: [RouterModule]
9   -})
10   -export class AppRoutingModule { }
src/app/app.component.html View file @ 632c4ac
1   -
2   -
3   -
4   -<router-outlet></router-outlet>
src/app/app.component.spec.ts View file @ 632c4ac
1   -import { TestBed } from '@angular/core/testing';
2   -import { RouterTestingModule } from '@angular/router/testing';
3   -import { AppComponent } from './app.component';
4   -
5   -describe('AppComponent', () => {
6   - beforeEach(async () => {
7   - await TestBed.configureTestingModule({
8   - imports: [
9   - RouterTestingModule
10   - ],
11   - declarations: [
12   - AppComponent
13   - ],
14   - }).compileComponents();
15   - });
16   -
17   - it('should create the app', () => {
18   - const fixture = TestBed.createComponent(AppComponent);
19   - const app = fixture.componentInstance;
20   - expect(app).toBeTruthy();
21   - });
22   -
23   - it(`should have as title 'fdit-visualisation'`, () => {
24   - const fixture = TestBed.createComponent(AppComponent);
25   - const app = fixture.componentInstance;
26   - expect(app.title).toEqual('fdit-visualisation');
27   - });
28   -
29   - it('should render title', () => {
30   - const fixture = TestBed.createComponent(AppComponent);
31   - fixture.detectChanges();
32   - const compiled = fixture.nativeElement;
33   - expect(compiled.querySelector('.content span').textContent).toContain('fdit-visualisation app is running!');
34   - });
35   -});
src/app/app.component.ts View file @ 632c4ac
1   -import { Component } from '@angular/core';
2   -
3   -@Component({
4   - selector: 'app-root',
5   - templateUrl: './app.component.html',
6   - styleUrls: ['./app.component.scss']
7   -})
8   -export class AppComponent {
9   - title = 'fdit-visualisation';
10   -}
src/app/app.module.ts View file @ 632c4ac
1   -import { BrowserModule } from '@angular/platform-browser';
2   -import { NgModule } from '@angular/core';
3   -
4   -import { AppRoutingModule } from './app-routing.module';
5   -import { AppComponent } from './app.component';
6   -import { NavBarComponent } from './nav-bar/nav-bar.component';
7   -import { BoatListComponent } from './boat-list/boat-list.component';
8   -import { MapComponent } from './map/map.component';
9   -import { GraphComponent } from './graph/graph.component';
10   -
11   -@NgModule({
12   - declarations: [
13   - AppComponent,
14   - NavBarComponent,
15   - BoatListComponent,
16   - MapComponent,
17   - GraphComponent
18   - ],
19   - imports: [
20   - BrowserModule,
21   - AppRoutingModule
22   - ],
23   - providers: [],
24   - bootstrap: [AppComponent]
25   -})
26   -export class AppModule { }
src/app/boat-list/boat-list.component.html View file @ 632c4ac
1   -<p>boat-list works!</p>
src/app/boat-list/boat-list.component.spec.ts View file @ 632c4ac
1   -import { ComponentFixture, TestBed } from '@angular/core/testing';
2   -
3   -import { BoatListComponent } from './boat-list.component';
4   -
5   -describe('BoatListComponent', () => {
6   - let component: BoatListComponent;
7   - let fixture: ComponentFixture<BoatListComponent>;
8   -
9   - beforeEach(async () => {
10   - await TestBed.configureTestingModule({
11   - declarations: [ BoatListComponent ]
12   - })
13   - .compileComponents();
14   - });
15   -
16   - beforeEach(() => {
17   - fixture = TestBed.createComponent(BoatListComponent);
18   - component = fixture.componentInstance;
19   - fixture.detectChanges();
20   - });
21   -
22   - it('should create', () => {
23   - expect(component).toBeTruthy();
24   - });
25   -});
src/app/boat-list/boat-list.component.ts View file @ 632c4ac
1   -import { Component, OnInit } from '@angular/core';
2   -
3   -@Component({
4   - selector: 'app-boat-list',
5   - templateUrl: './boat-list.component.html',
6   - styleUrls: ['./boat-list.component.scss']
7   -})
8   -export class BoatListComponent implements OnInit {
9   -
10   - constructor() { }
11   -
12   - ngOnInit(): void {
13   - }
14   -
15   -}
src/app/component/app-routing.module.ts View file @ 632c4ac
  1 +import { NgModule } from '@angular/core';
  2 +import { Routes, RouterModule } from '@angular/router';
  3 +
  4 +const routes: Routes = [];
  5 +
  6 +@NgModule({
  7 + imports: [RouterModule.forRoot(routes)],
  8 + exports: [RouterModule]
  9 +})
  10 +export class AppRoutingModule { }
src/app/component/app.component.html View file @ 632c4ac
  1 +<app-nav-bar></app-nav-bar>
  2 +<router-outlet></router-outlet>
src/app/component/app.component.spec.ts View file @ 632c4ac
  1 +import { TestBed } from '@angular/core/testing';
  2 +import { RouterTestingModule } from '@angular/router/testing';
  3 +import { AppComponent } from './app.component';
  4 +
  5 +describe('AppComponent', () => {
  6 + beforeEach(async () => {
  7 + await TestBed.configureTestingModule({
  8 + imports: [
  9 + RouterTestingModule
  10 + ],
  11 + declarations: [
  12 + AppComponent
  13 + ],
  14 + }).compileComponents();
  15 + });
  16 +
  17 + it('should create the app', () => {
  18 + const fixture = TestBed.createComponent(AppComponent);
  19 + const app = fixture.componentInstance;
  20 + expect(app).toBeTruthy();
  21 + });
  22 +
  23 + it(`should have as title 'fdit-visualisation'`, () => {
  24 + const fixture = TestBed.createComponent(AppComponent);
  25 + const app = fixture.componentInstance;
  26 + expect(app.title).toEqual('fdit-visualisation');
  27 + });
  28 +
  29 + it('should render title', () => {
  30 + const fixture = TestBed.createComponent(AppComponent);
  31 + fixture.detectChanges();
  32 + const compiled = fixture.nativeElement;
  33 + expect(compiled.querySelector('.content span').textContent).toContain('fdit-visualisation app is running!');
  34 + });
  35 +});
src/app/component/app.component.ts View file @ 632c4ac
  1 +import { Component } from '@angular/core';
  2 +
  3 +@Component({
  4 + selector: 'app-root',
  5 + templateUrl: './app.component.html',
  6 + styleUrls: ['./app.component.scss']
  7 +})
  8 +export class AppComponent {
  9 + title = 'fdit-visualisation';
  10 +}
src/app/component/app.module.ts View file @ 632c4ac
  1 +import { BrowserModule } from '@angular/platform-browser';
  2 +import { NgModule } from '@angular/core';
  3 +import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons';
  4 +
  5 +import { AppRoutingModule } from './app-routing.module';
  6 +import { AppComponent } from './app.component';
  7 +import { NavBarComponent } from './nav-bar/nav-bar.component';
  8 +import { MapComponent } from './map/map.component';
  9 +import { GraphComponent } from './graph/graph.component';
  10 +import { ProgressComponent } from './import-vessels/progress/progress.component';
  11 +import { ImportVesselsComponent } from './import-vessels/import-vessels.component';
  12 +import { ImportVesselsDirective } from './import-vessels/import-vessels.directive';
  13 +import { ListVesselComponent } from './list-vessel/list-vessel.component';
  14 +
  15 +@NgModule({
  16 + declarations: [
  17 + AppComponent,
  18 + NavBarComponent,
  19 + MapComponent,
  20 + GraphComponent,
  21 + ProgressComponent,
  22 + ImportVesselsComponent,
  23 + ImportVesselsDirective,
  24 + ListVesselComponent
  25 + ],
  26 + imports: [
  27 + BrowserModule,
  28 + AppRoutingModule,
  29 + NgxBootstrapIconsModule.pick(allIcons)
  30 + ],
  31 + providers: [],
  32 + bootstrap: [AppComponent]
  33 +})
  34 +export class AppModule { }
src/app/component/graph/graph.component.spec.ts View file @ 632c4ac
  1 +import { ComponentFixture, TestBed } from '@angular/core/testing';
  2 +
  3 +import { GraphComponent } from './graph.component';
  4 +
  5 +describe('GraphComponent', () => {
  6 + let component: GraphComponent;
  7 + let fixture: ComponentFixture<GraphComponent>;
  8 +
  9 + beforeEach(async () => {
  10 + await TestBed.configureTestingModule({
  11 + declarations: [ GraphComponent ]
  12 + })
  13 + .compileComponents();
  14 + });
  15 +
  16 + beforeEach(() => {
  17 + fixture = TestBed.createComponent(GraphComponent);
  18 + component = fixture.componentInstance;
  19 + fixture.detectChanges();
  20 + });
  21 +
  22 + it('should create', () => {
  23 + expect(component).toBeTruthy();
  24 + });
  25 +});
src/app/component/graph/graph.component.ts View file @ 632c4ac
  1 +import { Component, OnInit } from '@angular/core';
  2 +
  3 +@Component({
  4 + selector: 'app-graph',
  5 + templateUrl: './graph.component.html',
  6 + styleUrls: ['./graph.component.scss']
  7 +})
  8 +export class GraphComponent implements OnInit {
  9 +
  10 + constructor() { }
  11 +
  12 + ngOnInit(): void {
  13 + }
  14 +
  15 +}
src/app/component/import-vessels/import-vessels.component.html View file @ 632c4ac
  1 +<div class="container" appImportVessels (fileDropped)="onFileDropped($event)">
  2 + <input type="file" #fileDropRef id="fileDropRef" multiple (change)="fileBrowseHandler($event.target.files)" />
  3 + <img src="../../../assets/ic-upload-file.svg" alt="">
  4 + <h3>Drag and drop file here</h3>
  5 + <h3>or</h3>
  6 + <label for="fileDropRef">Browse for file</label>
  7 +</div>
  8 +<div class="files-list">
  9 + <div class="single-file" *ngFor="let file of files; let i = index">
  10 + <img src="../../../assets/ic-file.svg" width="45px" alt="file">
  11 + <div class="info">
  12 + <h4 class="name">
  13 + {{ file?.name }}
  14 + </h4>
  15 + <p class="size">
  16 + {{ formatBytes(file?.size) }}
  17 + </p>
  18 + <app-progress [progress]="file?.progress"></app-progress>
  19 + </div>
  20 + <img src="../../../assets/ic-delete-file.svg" class="delete" width="20px" alt="file" (click)="deleteFile(i)">
  21 + </div>
  22 +</div>
src/app/component/import-vessels/import-vessels.component.scss View file @ 632c4ac
  1 +
  2 +.container {
  3 + width: 450px;
  4 + height: 200px;
  5 + padding: 2rem;
  6 + text-align: center;
  7 + //border: dashed 1px #979797;
  8 + position: relative;
  9 + margin: 0 auto;
  10 +
  11 + input {
  12 + opacity: 0;
  13 + position: absolute;
  14 + z-index: 2;
  15 + width: 100%;
  16 + height: 100%;
  17 + top: 0;
  18 + left: 0;
  19 + }
  20 +
  21 + label {
  22 + color: white;
  23 + width: 183px;
  24 + height: 44px;
  25 + border-radius: 21.5px;
  26 + background-color: #db202f;
  27 + padding: 8px 16px;
  28 + }
  29 +
  30 + h3 {
  31 + font-size: 20px;
  32 + font-weight: 600;
  33 + color: #38424c;
  34 + }
  35 +}
  36 +
  37 +.fileover {
  38 + animation: shake 1s;
  39 + animation-iteration-count: infinite;
  40 +}
  41 +
  42 +.files-list {
  43 + margin-top: 1.5rem;
  44 +
  45 + .single-file {
  46 + display: flex;
  47 + padding: 0.5rem;
  48 + justify-content: space-between;
  49 + align-items: center;
  50 + border: dashed 1px #979797;
  51 + margin-bottom: 1rem;
  52 +
  53 + img.delete {
  54 + margin-left: 0.5rem;
  55 + cursor: pointer;
  56 + align-self: flex-end;
  57 + }
  58 +
  59 + flex-grow: 1;
  60 +
  61 + .name {
  62 + font-size: 14px;
  63 + font-weight: 500;
  64 + color: #353f4a;
  65 + margin: 0;
  66 + }
  67 +
  68 + .size {
  69 + font-size: 12px;
  70 + font-weight: 500;
  71 + color: #a4a4a4;
  72 + margin: 0 0 0.25rem;
  73 + }
  74 +
  75 + .info {
  76 + width: 100%
  77 + }
  78 + }
  79 +}
  80 +
  81 +/* Shake animation */
  82 +@keyframes shake {
  83 + 0% {
  84 + transform: translate(1px, 1px) rotate(0deg);
  85 + }
  86 +
  87 + 10% {
  88 + transform: translate(-1px, -2px) rotate(-1deg);
  89 + }
  90 +
  91 + 20% {
  92 + transform: translate(-3px, 0px) rotate(1deg);
  93 + }
  94 +
  95 + 30% {
  96 + transform: translate(3px, 2px) rotate(0deg);
  97 + }
  98 +
  99 + 40% {
  100 + transform: translate(1px, -1px) rotate(1deg);
  101 + }
  102 +
  103 + 50% {
  104 + transform: translate(-1px, 2px) rotate(-1deg);
  105 + }
  106 +
  107 + 60% {
  108 + transform: translate(-3px, 1px) rotate(0deg);
  109 + }
  110 +
  111 + 70% {
  112 + transform: translate(3px, 1px) rotate(-1deg);
  113 + }
  114 +
  115 + 80% {
  116 + transform: translate(-1px, -1px) rotate(1deg);
  117 + }
  118 +
  119 + 90% {
  120 + transform: translate(1px, 2px) rotate(0deg);
  121 + }
  122 +
  123 + 100% {
  124 + transform: translate(1px, -2px) rotate(-1deg);
  125 + }
  126 +}
src/app/component/import-vessels/import-vessels.component.spec.ts View file @ 632c4ac
  1 +import { ComponentFixture, TestBed } from '@angular/core/testing';
  2 +
  3 +import { ImportVesselsComponent } from './import-vessels.component';
  4 +
  5 +describe('ImportVesselsComponent', () => {
  6 + let component: ImportVesselsComponent;
  7 + let fixture: ComponentFixture<ImportVesselsComponent>;
  8 +
  9 + beforeEach(async () => {
  10 + await TestBed.configureTestingModule({
  11 + declarations: [ ImportVesselsComponent ]
  12 + })
  13 + .compileComponents();
  14 + });
  15 +
  16 + beforeEach(() => {
  17 + fixture = TestBed.createComponent(ImportVesselsComponent);
  18 + component = fixture.componentInstance;
  19 + fixture.detectChanges();
  20 + });
  21 +
  22 + it('should create', () => {
  23 + expect(component).toBeTruthy();
  24 + });
  25 +});
src/app/component/import-vessels/import-vessels.component.ts View file @ 632c4ac
  1 +import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
  2 +import {VesselsService} from '../../service/vessels.service';
  3 +import {Vessel} from '../../model/vessel';
  4 +
  5 +@Component({
  6 + selector: 'app-import-vessels',
  7 + templateUrl: './import-vessels.component.html',
  8 + styleUrls: ['./import-vessels.component.scss']
  9 +})
  10 +export class ImportVesselsComponent implements OnInit {
  11 + vessels: Map<number, Vessel>;
  12 +
  13 +
  14 + constructor(private vesselsService: VesselsService) {
  15 + }
  16 +
  17 + @ViewChild('fileDropRef', {static: false}) fileDropEl: ElementRef;
  18 + files: any[] = [];
  19 +
  20 + ngOnInit(): void {
  21 + this.vesselsService.currentVessels.subscribe(vessels => this.vessels = vessels);
  22 + }
  23 +
  24 + /**
  25 + * on file drop handler
  26 + */
  27 + onFileDropped($event): void {
  28 + this.prepareFilesList($event);
  29 + }
  30 +
  31 + /**
  32 + * handle file from browsing
  33 + */
  34 + fileBrowseHandler(files): void {
  35 + this.prepareFilesList(files);
  36 + }
  37 +
  38 + /**
  39 + * Delete file from files list
  40 + * @param index (File index)
  41 + */
  42 + deleteFile(index: number): void {
  43 + if (this.files[index].progress < 100) {
  44 + return;
  45 + }
  46 + this.files.splice(index, 1);
  47 + }
  48 +
  49 +
  50 + uploadFilesSimulator(index: number): void {
  51 + const fileReader = new FileReader();
  52 + let nbLine: number;
  53 +
  54 + fileReader.onload = (e) => {
  55 + const lines: string[] = (fileReader.result as string).split('\n');
  56 + nbLine = lines.length;
  57 + for (const line of lines) {
  58 + const splitLine = line.split(',');
  59 + const newVessel = new Vessel(splitLine);
  60 + this.vessels.set(Number(newVessel.mmsi), newVessel);
  61 + }
  62 + };
  63 +
  64 + fileReader.onprogress = (e ) => {
  65 + if (e.lengthComputable) {
  66 + this.files[index].progress = Math.round(((e.loaded / e.total) * 100));
  67 + }
  68 + };
  69 +
  70 + fileReader.readAsText(this.files[index]);
  71 + }
  72 +
  73 + prepareFilesList(files: Array<any>): void {
  74 + for (const item of files) {
  75 + item.progress = 0;
  76 + this.files.push(item);
  77 + }
  78 + this.fileDropEl.nativeElement.value = '';
  79 + this.uploadFilesSimulator(0);
  80 + }
  81 +
  82 + formatBytes(bytes, decimals = 2): string {
  83 + if (bytes === 0) {
  84 + return '0 Bytes';
  85 + }
  86 + const k = 1024;
  87 + const dm = decimals <= 0 ? 0 : decimals;
  88 + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  89 + const i = Math.floor(Math.log(bytes) / Math.log(k));
  90 + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
  91 + }
  92 +}
src/app/component/import-vessels/import-vessels.directive.spec.ts View file @ 632c4ac
  1 +import { ImportVesselsDirective } from './import-vessels.directive';
  2 +
  3 +describe('ImportVesselsDirective', () => {
  4 + it('should create an instance', () => {
  5 + const directive = new ImportVesselsDirective();
  6 + expect(directive).toBeTruthy();
  7 + });
  8 +});
src/app/component/import-vessels/import-vessels.directive.ts View file @ 632c4ac
  1 +import {Directive, EventEmitter, HostBinding, HostListener, Output} from '@angular/core';
  2 +
  3 +@Directive({
  4 + selector: '[appImportVessels]'
  5 +})
  6 +export class ImportVesselsDirective {
  7 +
  8 + @HostBinding('class.fileover') fileOver: boolean;
  9 + @Output() fileDropped = new EventEmitter<any>();
  10 +
  11 + @HostListener('dragover', ['$event'])
  12 + onDragOver(evt): void {
  13 + evt.preventDefault();
  14 + evt.stopPropagation();
  15 + this.fileOver = true;
  16 + }
  17 +
  18 + @HostListener('dragleave', ['$event'])
  19 + public onDragLeave(evt): void {
  20 + evt.preventDefault();
  21 + evt.stopPropagation();
  22 + this.fileOver = false;
  23 + }
  24 +
  25 + @HostListener('drop', ['$event'])
  26 + public ondrop(evt): void {
  27 + evt.preventDefault();
  28 + evt.stopPropagation();
  29 + this.fileOver = false;
  30 + const files = evt.dataTransfer.files;
  31 + if (files.length > 0) {
  32 + this.fileDropped.emit(files);
  33 + }
  34 + }
  35 +}
src/app/component/import-vessels/progress/progress.component.html View file @ 632c4ac
  1 +<div class="progress-cont">
  2 + <div class="progress" [style.width]="progress + '%'">
  3 + </div>
  4 +</div>
src/app/component/import-vessels/progress/progress.component.scss View file @ 632c4ac
  1 +.progress-cont {
  2 + height: 7px;
  3 + width: 100%;
  4 + border-radius: 4px;
  5 + background-color: #d0d0d0;
  6 + position: relative;
  7 +
  8 + .progress {
  9 + width: 0;
  10 + height: 100%;
  11 + position: absolute;
  12 + z-index: 1;
  13 + top: 0;
  14 + left: 0;
  15 + border-radius: 4px;
  16 + background-color: #4c97cb;
  17 + transition: 0.5s all;
  18 + }
  19 +}
src/app/component/import-vessels/progress/progress.component.spec.ts View file @ 632c4ac
  1 +import { ComponentFixture, TestBed } from '@angular/core/testing';
  2 +
  3 +import { ProgressComponent } from './progress.component';
  4 +
  5 +describe('ProgressComponent', () => {
  6 + let component: ProgressComponent;
  7 + let fixture: ComponentFixture<ProgressComponent>;
  8 +
  9 + beforeEach(async () => {
  10 + await TestBed.configureTestingModule({
  11 + declarations: [ ProgressComponent ]
  12 + })
  13 + .compileComponents();
  14 + });
  15 +
  16 + beforeEach(() => {
  17 + fixture = TestBed.createComponent(ProgressComponent);
  18 + component = fixture.componentInstance;
  19 + fixture.detectChanges();
  20 + });
  21 +
  22 + it('should create', () => {
  23 + expect(component).toBeTruthy();
  24 + });
  25 +});
src/app/component/import-vessels/progress/progress.component.ts View file @ 632c4ac
  1 +import {Component, Input, OnInit} from '@angular/core';
  2 +
  3 +@Component({
  4 + selector: 'app-progress',
  5 + templateUrl: './progress.component.html',
  6 + styleUrls: ['./progress.component.scss']
  7 +})
  8 +export class ProgressComponent implements OnInit {
  9 + @Input() progress = 0;
  10 + constructor() { }
  11 +
  12 + ngOnInit(): void {
  13 + }
  14 +
  15 +}
src/app/component/list-vessel/list-vessel.component.spec.ts View file @ 632c4ac
  1 +import { ComponentFixture, TestBed } from '@angular/core/testing';
  2 +
  3 +import { ListVesselComponent } from './list-vessel.component';
  4 +
  5 +describe('ListVesselComponent', () => {
  6 + let component: ListVesselComponent;
  7 + let fixture: ComponentFixture<ListVesselComponent>;
  8 +
  9 + beforeEach(async () => {
  10 + await TestBed.configureTestingModule({
  11 + declarations: [ ListVesselComponent ]
  12 + })
  13 + .compileComponents();
  14 + });
  15 +
  16 + beforeEach(() => {
  17 + fixture = TestBed.createComponent(ListVesselComponent);
  18 + component = fixture.componentInstance;
  19 + fixture.detectChanges();
  20 + });
  21 +
  22 + it('should create', () => {
  23 + expect(component).toBeTruthy();
  24 + });
  25 +});
src/app/component/list-vessel/list-vessel.component.ts View file @ 632c4ac
  1 +import { Component, OnInit } from '@angular/core';
  2 +
  3 +@Component({
  4 + selector: 'app-list-vessel',
  5 + templateUrl: './list-vessel.component.html',
  6 + styleUrls: ['./list-vessel.component.scss']
  7 +})
  8 +export class ListVesselComponent implements OnInit {
  9 +
  10 + constructor() { }
  11 +
  12 + ngOnInit(): void {
  13 + }
  14 +
  15 +}
src/app/component/map/map.component.html View file @ 632c4ac
  1 +<p>map works!</p>
src/app/component/map/map.component.spec.ts View file @ 632c4ac
  1 +import { ComponentFixture, TestBed } from '@angular/core/testing';
  2 +
  3 +import { MapComponent } from './map.component';
  4 +
  5 +describe('MapComponent', () => {
  6 + let component: MapComponent;
  7 + let fixture: ComponentFixture<MapComponent>;
  8 +
  9 + beforeEach(async () => {
  10 + await TestBed.configureTestingModule({
  11 + declarations: [ MapComponent ]
  12 + })
  13 + .compileComponents();
  14 + });
  15 +
  16 + beforeEach(() => {
  17 + fixture = TestBed.createComponent(MapComponent);
  18 + component = fixture.componentInstance;
  19 + fixture.detectChanges();
  20 + });
  21 +
  22 + it('should create', () => {
  23 + expect(component).toBeTruthy();
  24 + });
  25 +});
src/app/component/map/map.component.ts View file @ 632c4ac
  1 +import { Component, OnInit } from '@angular/core';
  2 +
  3 +@Component({
  4 + selector: 'app-map',
  5 + templateUrl: './map.component.html',
  6 + styleUrls: ['./map.component.scss']
  7 +})
  8 +export class MapComponent implements OnInit {
  9 +
  10 + constructor() { }
  11 +
  12 + ngOnInit(): void {
  13 + }
  14 +
  15 +}
src/app/component/nav-bar/nav-bar.component.html View file @ 632c4ac
  1 +<nav class="navbar navbar-expand-lg navbar-light bg-light">
  2 + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
  3 + <span class="navbar-toggler-icon"></span>
  4 + </button>
  5 + <div class="collapse navbar-collapse" id="navbarNavDropdown">
  6 + <ul class="navbar-nav">
  7 +
  8 + <li class="nav-item">
  9 + <a class="nav-link" data-toggle="modal" data-target="#exampleModal" >Import</a>
  10 + </li>
  11 +
  12 + <li class="nav-item dropdown">
  13 + <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
  14 + Dropdown menu
  15 + </a>
  16 + <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
  17 + <a class="dropdown-item" href="#">Action</a>
  18 + <a class="dropdown-item" href="#">Another action</a>
  19 + <a class="dropdown-item" href="#">Something else here</a>
  20 + </div>
  21 + </li>
  22 + </ul>
  23 + </div>
  24 +</nav>
  25 +
  26 +<!-- Modal -->
  27 +<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
  28 + <div class="modal-dialog" role="document">
  29 + <div class="modal-content">
  30 + <div class="modal-header">
  31 + <h5 class="modal-title" id="exampleModalLabel">Import Vessels</h5>
  32 + <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  33 + <span aria-hidden="true">&times;</span>
  34 + </button>
  35 + </div>
  36 + <div class="modal-body">
  37 + <app-import-vessels></app-import-vessels>
  38 + </div>
  39 + <div class="modal-footer">
  40 + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
  41 + </div>
  42 + </div>
  43 + </div>
  44 +</div>
src/app/component/nav-bar/nav-bar.component.spec.ts View file @ 632c4ac
  1 +import { ComponentFixture, TestBed } from '@angular/core/testing';
  2 +
  3 +import { NavBarComponent } from './nav-bar.component';
  4 +
  5 +describe('NavBarComponent', () => {
  6 + let component: NavBarComponent;
  7 + let fixture: ComponentFixture<NavBarComponent>;
  8 +
  9 + beforeEach(async () => {
  10 + await TestBed.configureTestingModule({
  11 + declarations: [ NavBarComponent ]
  12 + })
  13 + .compileComponents();
  14 + });
  15 +
  16 + beforeEach(() => {
  17 + fixture = TestBed.createComponent(NavBarComponent);
  18 + component = fixture.componentInstance;
  19 + fixture.detectChanges();
  20 + });
  21 +
  22 + it('should create', () => {
  23 + expect(component).toBeTruthy();
  24 + });
  25 +});
src/app/component/nav-bar/nav-bar.component.ts View file @ 632c4ac
  1 +import {Component, OnInit} from '@angular/core';
  2 +
  3 +@Component({
  4 + selector: 'app-nav-bar',
  5 + templateUrl: './nav-bar.component.html',
  6 + styleUrls: ['./nav-bar.component.scss']
  7 +})
  8 +export class NavBarComponent implements OnInit {
  9 +
  10 + constructor() { }
  11 +
  12 + ngOnInit(): void {
  13 + }
  14 +
  15 +}
src/app/graph/graph.component.html View file @ 632c4ac
1   -<p>graph works!</p>
src/app/graph/graph.component.spec.ts View file @ 632c4ac
1   -import { ComponentFixture, TestBed } from '@angular/core/testing';
2   -
3   -import { GraphComponent } from './graph.component';
4   -
5   -describe('GraphComponent', () => {
6   - let component: GraphComponent;
7   - let fixture: ComponentFixture<GraphComponent>;
8   -
9   - beforeEach(async () => {
10   - await TestBed.configureTestingModule({
11   - declarations: [ GraphComponent ]
12   - })
13   - .compileComponents();
14   - });
15   -
16   - beforeEach(() => {
17   - fixture = TestBed.createComponent(GraphComponent);
18   - component = fixture.componentInstance;
19   - fixture.detectChanges();
20   - });
21   -
22   - it('should create', () => {
23   - expect(component).toBeTruthy();
24   - });
25   -});
src/app/graph/graph.component.ts View file @ 632c4ac
1   -import { Component, OnInit } from '@angular/core';
2   -
3   -@Component({
4   - selector: 'app-graph',
5   - templateUrl: './graph.component.html',
6   - styleUrls: ['./graph.component.scss']
7   -})
8   -export class GraphComponent implements OnInit {
9   -
10   - constructor() { }
11   -
12   - ngOnInit(): void {
13   - }
14   -
15   -}
src/app/map/map.component.html View file @ 632c4ac
1   -<p>map works!</p>
src/app/map/map.component.spec.ts View file @ 632c4ac
1   -import { ComponentFixture, TestBed } from '@angular/core/testing';
2   -
3   -import { MapComponent } from './map.component';
4   -
5   -describe('MapComponent', () => {
6   - let component: MapComponent;
7   - let fixture: ComponentFixture<MapComponent>;
8   -
9   - beforeEach(async () => {
10   - await TestBed.configureTestingModule({
11   - declarations: [ MapComponent ]
12   - })
13   - .compileComponents();
14   - });
15   -
16   - beforeEach(() => {
17   - fixture = TestBed.createComponent(MapComponent);
18   - component = fixture.componentInstance;
19   - fixture.detectChanges();
20   - });
21   -
22   - it('should create', () => {
23   - expect(component).toBeTruthy();
24   - });
25   -});
src/app/map/map.component.ts View file @ 632c4ac
1   -import { Component, OnInit } from '@angular/core';
2   -
3   -@Component({
4   - selector: 'app-map',
5   - templateUrl: './map.component.html',
6   - styleUrls: ['./map.component.scss']
7   -})
8   -export class MapComponent implements OnInit {
9   -
10   - constructor() { }
11   -
12   - ngOnInit(): void {
13   - }
14   -
15   -}
src/app/model/vessel.spec.ts View file @ 632c4ac
  1 +import { Vessel } from './vessel';
  2 +
  3 +describe('Vessel', () => {
  4 + // it('should create an instance', () => {
  5 + // expect(new Vessel()).toBeTruthy();
  6 + // });
  7 +});
src/app/model/vessel.ts View file @ 632c4ac
  1 +export class Vessel {
  2 + mmsi: string;
  3 + time: string;
  4 + latitude: string;
  5 + longitude: string;
  6 + speedOverGround: string;
  7 + courseOverGround: string;
  8 + heading: string;
  9 + vesselName: string;
  10 + imo: string;
  11 + callSign: string;
  12 + vesselType: string;
  13 + status: string;
  14 + length: string;
  15 + width: string;
  16 + draft: string;
  17 + cargo: string;
  18 +
  19 +
  20 + constructor(splitLine: string[]) {
  21 + this.mmsi = splitLine[0];
  22 + this.time = splitLine[1];
  23 + this.latitude = splitLine[2];
  24 + this.longitude = splitLine[3];
  25 + this.speedOverGround = splitLine[4];
  26 + this.courseOverGround = splitLine[5];
  27 + this.heading = splitLine[6];
  28 + this.vesselName = splitLine[7];
  29 + this.imo = splitLine[8];
  30 + this.callSign = splitLine[9];
  31 + this.vesselType = splitLine[10];
  32 + this.status = splitLine[11];
  33 + this.length = splitLine[12];
  34 + this.width = splitLine[13];
  35 + this.draft = splitLine[14];
  36 + this.cargo = splitLine[15];
  37 + }
  38 +}
src/app/nav-bar/nav-bar.component.html View file @ 632c4ac
1   -<p>nav-bar works!</p>
src/app/nav-bar/nav-bar.component.spec.ts View file @ 632c4ac
1   -import { ComponentFixture, TestBed } from '@angular/core/testing';
2   -
3   -import { NavBarComponent } from './nav-bar.component';
4   -
5   -describe('NavBarComponent', () => {
6   - let component: NavBarComponent;
7   - let fixture: ComponentFixture<NavBarComponent>;
8   -
9   - beforeEach(async () => {
10   - await TestBed.configureTestingModule({
11   - declarations: [ NavBarComponent ]
12   - })
13   - .compileComponents();
14   - });
15   -
16   - beforeEach(() => {
17   - fixture = TestBed.createComponent(NavBarComponent);
18   - component = fixture.componentInstance;
19   - fixture.detectChanges();
20   - });
21   -
22   - it('should create', () => {
23   - expect(component).toBeTruthy();
24   - });
25   -});
src/app/nav-bar/nav-bar.component.ts View file @ 632c4ac
1   -import { Component, OnInit } from '@angular/core';
2   -
3   -@Component({
4   - selector: 'app-nav-bar',
5   - templateUrl: './nav-bar.component.html',
6   - styleUrls: ['./nav-bar.component.scss']
7   -})
8   -export class NavBarComponent implements OnInit {
9   -
10   - constructor() { }
11   -
12   - ngOnInit(): void {
13   - }
14   -
15   -}
src/app/service/vessels.service.spec.ts View file @ 632c4ac
  1 +import { TestBed } from '@angular/core/testing';
  2 +
  3 +import { VesselsService } from './vessels.service';
  4 +
  5 +describe('VesselsService', () => {
  6 + let service: VesselsService;
  7 +
  8 + beforeEach(() => {
  9 + TestBed.configureTestingModule({});
  10 + service = TestBed.inject(VesselsService);
  11 + });
  12 +
  13 + it('should be created', () => {
  14 + expect(service).toBeTruthy();
  15 + });
  16 +});
src/app/service/vessels.service.ts View file @ 632c4ac
  1 +import {Injectable} from '@angular/core';
  2 +import {BehaviorSubject, Observable} from 'rxjs';
  3 +import {Vessel} from '../model/vessel';
  4 +
  5 +@Injectable({
  6 + providedIn: 'root'
  7 +})
  8 +export class VesselsService {
  9 + private vessels = new BehaviorSubject(new Map());
  10 + currentVessels = this.vessels.asObservable();
  11 +
  12 + constructor() {
  13 + }
  14 +
  15 + changeVesselsSet(newVessels: Map<number, Vessel>): void {
  16 + this.vessels.next(newVessels);
  17 + }
  18 +}
src/assets/ic-delete-file.svg View file @ 632c4ac
  1 +<svg xmlns="http://www.w3.org/2000/svg" width="14" height="18" viewBox="0 0 14 18">
  2 + <path fill="#B1B1B1" fill-rule="nonzero" d="M1 16c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2H3c-1.1 0-2 .9-2 2v10zm3.17-7.83a.996.996 0 0 1 1.41 0L7 9.59l1.42-1.42a.996.996 0 1 1 1.41 1.41L8.41 11l1.42 1.42a.996.996 0 1 1-1.41 1.41L7 12.41l-1.42 1.42a.996.996 0 1 1-1.41-1.41L5.59 11 4.17 9.58a.996.996 0 0 1 0-1.41zM10.5 1L9.79.29C9.61.11 9.35 0 9.09 0H4.91c-.26 0-.52.11-.7.29L3.5 1H1c-.55 0-1 .45-1 1s.45 1 1 1h12c.55 0 1-.45 1-1s-.45-1-1-1h-2.5z"/>
  3 +</svg>
src/assets/ic-file.svg View file @ 632c4ac
  1 +<?xml version="1.0" encoding="windows-1252"?>
  2 +<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
  3 +<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
  4 +<polygon style="fill:#EDEADA;" points="51.5,14 37.5,0 6.5,0 6.5,58 51.5,58 "/>
  5 +<g>
  6 + <path style="fill:#CEC9AE;" d="M16.5,23h25c0.552,0,1-0.447,1-1s-0.448-1-1-1h-25c-0.552,0-1,0.447-1,1S15.948,23,16.5,23z"/>
  7 + <path style="fill:#CEC9AE;" d="M16.5,15h10c0.552,0,1-0.447,1-1s-0.448-1-1-1h-10c-0.552,0-1,0.447-1,1S15.948,15,16.5,15z"/>
  8 + <path style="fill:#CEC9AE;" d="M41.5,29h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S42.052,29,41.5,29z"/>
  9 + <path style="fill:#CEC9AE;" d="M41.5,37h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S42.052,37,41.5,37z"/>
  10 + <path style="fill:#CEC9AE;" d="M41.5,45h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S42.052,45,41.5,45z"/>
  11 +</g>
  12 +<polygon style="fill:#CEC9AE;" points="37.5,0 37.5,14 51.5,14 "/>
  13 +<g>
  14 +</g>
  15 +<g>
  16 +</g>
  17 +<g>
  18 +</g>
  19 +<g>
  20 +</g>
  21 +<g>
  22 +</g>
  23 +<g>
  24 +</g>
  25 +<g>
  26 +</g>
  27 +<g>
  28 +</g>
  29 +<g>
  30 +</g>
  31 +<g>
  32 +</g>
  33 +<g>
  34 +</g>
  35 +<g>
  36 +</g>
  37 +<g>
  38 +</g>
  39 +<g>
  40 +</g>
  41 +<g>
  42 +</g>
  43 +</svg>
src/assets/ic-upload-file.svg View file @ 632c4ac
  1 +<svg xmlns="http://www.w3.org/2000/svg" width="63" height="64" viewBox="0 0 63 64">
  2 + <g fill="#3B454F" fill-rule="nonzero">
  3 + <path d="M42.656 15.135a1.953 1.953 0 0 1-1.391-.578L31.5 4.795l-9.765 9.762a1.97 1.97 0 1 1-2.785-2.785L30.106.616a1.97 1.97 0 0 1 2.785 0l11.157 11.156a1.97 1.97 0 0 1-1.392 3.363z"/>
  4 + <path d="M31.5 36.791a1.97 1.97 0 0 1-1.969-1.969V2.01a1.97 1.97 0 0 1 3.938 0v32.812a1.97 1.97 0 0 1-1.969 1.969z"/>
  5 + <path d="M55.781 63.041H7.22A7.225 7.225 0 0 1 0 55.822V41.385a4.599 4.599 0 0 1 4.594-4.594h7.234a4.567 4.567 0 0 1 4.402 3.276l2.814 9.382a.658.658 0 0 0 .628.467h23.656a.658.658 0 0 0 .628-.467l2.814-9.385a4.572 4.572 0 0 1 4.402-3.273h7.234A4.599 4.599 0 0 1 63 41.385v14.437a7.225 7.225 0 0 1-7.219 7.219zM4.594 40.729a.656.656 0 0 0-.657.656v14.437a3.286 3.286 0 0 0 3.282 3.282H55.78a3.286 3.286 0 0 0 3.282-3.282V41.385a.656.656 0 0 0-.657-.656h-7.234a.65.65 0 0 0-.628.467L47.73 50.58a4.628 4.628 0 0 1-4.402 3.274H19.672a4.567 4.567 0 0 1-4.402-3.276l-2.814-9.382a.65.65 0 0 0-.628-.467H4.594z"/>
  6 + </g>
  7 +</svg>
1 1 import { enableProdMode } from '@angular/core';
2 2 import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 3  
4   -import { AppModule } from './app/app.module';
  4 +import { AppModule } from './app/component/app.module';
5 5 import { environment } from './environments/environment';
6 6  
7 7 if (environment.production) {