diff --git a/frontend/app/app.component.ts b/frontend/app/app.component.ts index 522f4bce..7260eedf 100644 --- a/frontend/app/app.component.ts +++ b/frontend/app/app.component.ts @@ -3,6 +3,7 @@ import {AuthenticationService} from "./model/network/authentication.service"; import {UserDTO} from "../../common/entities/UserDTO"; import {Router} from "@angular/router"; + @Component({ selector: 'pi-gallery2-app', template: ``, @@ -31,4 +32,6 @@ export class AppComponent implements OnInit { } + + } diff --git a/frontend/app/app.module.ts b/frontend/app/app.module.ts index b696f439..89a8be6b 100644 --- a/frontend/app/app.module.ts +++ b/frontend/app/app.module.ts @@ -32,6 +32,7 @@ import {ThumbnailManagerService} from "./gallery/thumnailManager.service"; import {OverlayService} from "./gallery/overlay.service"; import {Config} from "../../common/config/public/Config"; import {LAZY_MAPS_API_CONFIG} from "@agm/core/services"; +import {SlimLoadingBarModule} from "ng2-slim-loading-bar"; @Injectable() @@ -49,7 +50,8 @@ export class GoogleMapsConfig { FormsModule, HttpModule, appRoutes, - AgmCoreModule.forRoot() + AgmCoreModule.forRoot(), + SlimLoadingBarModule.forRoot() ], declarations: [AppComponent, LoginComponent, diff --git a/frontend/app/frame/frame.component.css b/frontend/app/frame/frame.component.css new file mode 100644 index 00000000..d55eeacf --- /dev/null +++ b/frontend/app/frame/frame.component.css @@ -0,0 +1,9 @@ +.navbar { + margin-bottom: 0px; +} + +ng2-slim-loading-bar { + margin-bottom: 20px; + display: block; +} + diff --git a/frontend/app/frame/frame.component.html b/frontend/app/frame/frame.component.html index f985843c..acf8459a 100644 --- a/frontend/app/frame/frame.component.html +++ b/frontend/app/frame/frame.component.html @@ -1,32 +1,34 @@ + diff --git a/frontend/app/frame/frame.component.ts b/frontend/app/frame/frame.component.ts index 3ddf0155..ea596929 100644 --- a/frontend/app/frame/frame.component.ts +++ b/frontend/app/frame/frame.component.ts @@ -7,6 +7,7 @@ import {Config} from "../../../common/config/public/Config"; @Component({ selector: 'app-frame', templateUrl: './frame.component.html', + styleUrls: ['./frame.component.css'], providers: [RouterLink], encapsulation: ViewEncapsulation.Emulated }) diff --git a/frontend/app/gallery/grid/photo/photo.grid.gallery.component.ts b/frontend/app/gallery/grid/photo/photo.grid.gallery.component.ts index 99cd5fb1..2aae2461 100644 --- a/frontend/app/gallery/grid/photo/photo.grid.gallery.component.ts +++ b/frontend/app/gallery/grid/photo/photo.grid.gallery.component.ts @@ -48,60 +48,12 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { ngOnInit() { this.thumbnail = this.thumbnailService.getThumbnail(this.gridPhoto); - /* this.loading.show = true; - //set up before adding task to thumbnail generator - if (this.gridPhoto.isThumbnailAvailable()) { - this.image.src = this.gridPhoto.getThumbnailPath(); - this.image.show = true; - } else if (this.gridPhoto.isReplacementThumbnailAvailable()) { - this.image.src = this.gridPhoto.getReplacementThumbnailPath(); - this.image.show = true; - }*/ } - /* - ngAfterViewInit() { - //schedule change after Angular checks the model - if (!this.gridPhoto.isThumbnailAvailable()) { - set Timeout(() => { - - let listener: ThumbnailLoadingListener = { - onStartedLoading: () => { //onLoadStarted - this.loading.animate = true; - }, - onLoad: () => {//onLoaded - this.image.src = this.gridPhoto.getThumbnailPath(); - this.image.show = true; - this.loading.show = false; - this.thumbnailTask = null; - }, - onError: (error) => {//onError - this.thumbnailTask = null; - //TODO: handle error - //TODO: not an error if its from cache - console.error("something bad happened"); - console.error(error); - } - }; - if (this.gridPhoto.isReplacementThumbnailAvailable()) { - this.thumbnailTask = this.thumbnailService.loadImage(this.gridPhoto, ThumbnailLoadingPriority.medium, listener); - } else { - this.thumbnailTask = this.thumbnailService.loadImage(this.gridPhoto, ThumbnailLoadingPriority.high, listener); - } - - - }); - } - }*/ ngOnDestroy() { this.thumbnail.destroy(); - /* - if (this.thumbnailTask != null) { - this.thumbnailService.removeTask(this.thumbnailTask); - this.thumbnailTask = null; - }*/ } @@ -112,6 +64,9 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { onScroll() { + if (this.thumbnail.Available == true) { + return; + } let isInView = this.isInView(); if (this.wasInView != isInView) { this.wasInView = isInView; diff --git a/frontend/app/gallery/map/map.gallery.component.ts b/frontend/app/gallery/map/map.gallery.component.ts index 9ca16f94..e28f2418 100644 --- a/frontend/app/gallery/map/map.gallery.component.ts +++ b/frontend/app/gallery/map/map.gallery.component.ts @@ -19,7 +19,8 @@ export class GalleryMapComponent implements OnChanges, IRenderable { //TODO: fix zooming ngOnChanges() { this.mapPhotos = this.photos.filter(p => { - return p.metadata && p.metadata.positionData && p.metadata.positionData.GPSData; + return p.metadata && p.metadata.positionData && p.metadata.positionData.GPSData && + p.metadata.positionData.GPSData.latitude && p.metadata.positionData.GPSData.longitude; }).map(p => { return { latitude: p.metadata.positionData.GPSData.latitude, @@ -31,7 +32,6 @@ export class GalleryMapComponent implements OnChanges, IRenderable { this.mapCenter = this.mapPhotos[0]; } - } click() { diff --git a/frontend/app/gallery/thumnailManager.service.ts b/frontend/app/gallery/thumnailManager.service.ts index 61edf880..fede073e 100644 --- a/frontend/app/gallery/thumnailManager.service.ts +++ b/frontend/app/gallery/thumnailManager.service.ts @@ -30,6 +30,7 @@ export abstract class ThumbnailBase { protected available: boolean = false; protected src: string = null; protected loading: boolean = false; + protected error: boolean = true; protected onLoad: Function = null; protected thumbnailTask: ThumbnailTaskEntity; @@ -70,6 +71,7 @@ export class IconThumbnail extends ThumbnailBase { constructor(private photo: IconPhoto, thumbnailService: ThumbnailLoaderService) { super(thumbnailService); this.src = ""; + this.error = false; if (this.photo.isIconAvailable()) { this.src = this.photo.getIconPath(); this.available = true; @@ -92,6 +94,8 @@ export class IconThumbnail extends ThumbnailBase { }, onError: (error) => {//onError this.thumbnailTask = null; + this.loading = false; + this.error = true; //TODO: handle error //TODO: not an error if its from cache console.error("something bad happened"); diff --git a/frontend/app/model/network/network.service.ts b/frontend/app/model/network/network.service.ts index b939e7c8..c842729d 100644 --- a/frontend/app/model/network/network.service.ts +++ b/frontend/app/model/network/network.service.ts @@ -3,12 +3,13 @@ import {Headers, Http, RequestOptions} from "@angular/http"; import {Message} from "../../../../common/entities/Message"; import "rxjs/Rx"; +import {SlimLoadingBarService} from "ng2-slim-loading-bar"; @Injectable() export class NetworkService { _baseUrl = "/api"; - constructor(protected _http: Http) { + constructor(protected _http: Http, private slimLoadingBarService: SlimLoadingBarService) { } private callJson(method: string, url: string, data: any = {}): Promise { @@ -16,17 +17,31 @@ export class NetworkService { let headers = new Headers({'Content-Type': 'application/json'}); let options = new RequestOptions({headers: headers}); + this.slimLoadingBarService.visible = true; + this.slimLoadingBarService.start(() => { + this.slimLoadingBarService.visible = false; + }); + + const process = (res: any) => { + this.slimLoadingBarService.complete(); + return > res.json(); + }; + + const err = (err) => { + NetworkService.handleError(err); + this.slimLoadingBarService.complete(); + }; + if (method == "get" || method == "delete") { return this._http[method](this._baseUrl + url, options) .toPromise() - .then(res => > res.json()) - .catch(NetworkService.handleError); + .then(process) + .catch(err); } - return this._http[method](this._baseUrl + url, body, options) .toPromise() - .then((res: any) => > res.json()) - .catch(NetworkService.handleError); + .then(process) + .catch(err); } public postJson(url: string, data: any = {}): Promise { diff --git a/frontend/app/style.css b/frontend/app/style.css new file mode 100644 index 00000000..045b3f8a --- /dev/null +++ b/frontend/app/style.css @@ -0,0 +1,34 @@ +/*! + * Copyright (C) 2016 Sergey Akopkokhyants + * This project is licensed under the terms of the MIT license. + * https://github.com/akserg/ng2-slim-loading-bar + */ + +/* Styling for the Slim Loading Progress Bar container */ +.slim-loading-bar { + position: fixed; + margin: 0; + padding: 0; + top: 0; + left: 0; + right: 0; + z-index: 99999; +} + +/* Styling for the Slim Loading Progress Bar itself */ +.slim-loading-bar-progress { + margin: 0; + padding: 0; + z-index: 99998; + background-color: green; + color: green; + box-shadow: 0 0 10px 0; /* Inherits the font color */ + height: 2px; + opacity: 0; + + /* Add CSS3 styles for transition smoothing */ + -webkit-transition: all 0.5s ease-in-out; + -moz-transition: all 0.5s ease-in-out; + -o-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; +} diff --git a/package.json b/package.json index 9ba94eaa..df1a89f2 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "mocha": "^3.4.2", "mysql": "^2.13.0", "ng2-cookies": "^1.0.12", + "ng2-slim-loading-bar": "^4.0.0", "node-iptc": "^1.0.4", "optimist": "^0.6.1", "reflect-metadata": "^0.1.10",