From bb9fba996fe8873170e667f3b8fff3f09fff8440 Mon Sep 17 00:00:00 2001 From: Willem Dantuma Date: Mon, 4 Nov 2019 18:47:15 +0100 Subject: [PATCH] First functional version --- .../fm-map/components/map/map.component.html | 10 +- .../fm-map/components/map/map.component.ts | 12 +- .../fm-map/services/geolocation.service.ts | 1 - projects/common/package.json | 3 +- projects/common/src/fm/common.module.ts | 4 + .../src/fm/components/app/app.component.html | 14 ++ .../src/fm/components/app/app.component.scss | 72 ++++++++++ .../src/fm/components/app/app.component.ts | 129 ++++++++++++++++++ .../src/fm/reducers/app-common.reducer.ts | 34 ++++- .../common/src/fm/services/event.service.ts | 18 ++- src/app/app-content.component.ts | 8 -- src/app/app-routing.module.ts | 3 - src/app/app-side-panel-test.component.ts | 29 ---- src/app/app.component.html | 2 +- src/app/app.component.scss | 27 ---- src/app/app.component.ts | 2 +- src/app/app.module.ts | 13 +- src/configuration.json | 2 +- 18 files changed, 283 insertions(+), 100 deletions(-) create mode 100644 projects/common/src/fm/components/app/app.component.html create mode 100644 projects/common/src/fm/components/app/app.component.scss create mode 100644 projects/common/src/fm/components/app/app.component.ts delete mode 100644 src/app/app-content.component.ts delete mode 100644 src/app/app-side-panel-test.component.ts diff --git a/projects/common-map/src/fm-map/components/map/map.component.html b/projects/common-map/src/fm-map/components/map/map.component.html index 859283f..1c6009d 100644 --- a/projects/common-map/src/fm-map/components/map/map.component.html +++ b/projects/common-map/src/fm-map/components/map/map.component.html @@ -2,12 +2,10 @@
- - - - - - + + + + diff --git a/projects/common-map/src/fm-map/components/map/map.component.ts b/projects/common-map/src/fm-map/components/map/map.component.ts index 986a960..b400a5d 100644 --- a/projects/common-map/src/fm-map/components/map/map.component.ts +++ b/projects/common-map/src/fm-map/components/map/map.component.ts @@ -38,7 +38,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { title: string = 'Map'; public openedModalName: Observable; public itemTypes: Observable<{ [id: string]: IItemType }>; - public mapState$: Observable; + public mapState: Observable; public features: Observable>; public overlayLayers: Observable>; public selectedOverlayLayer: Observable; @@ -67,7 +67,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { public position: Observable; public baseLayersCollapsed:boolean = true; public overlayLayersCollapsed: boolean = true; - public extent$: Observable; + public extent: Observable; @ViewChild('map') map; constructor(private store: Store, private route: ActivatedRoute, private router: Router, private uploadService: ResumableFileUploadService, private serializeService: StateSerializerService, public itemTypeService: ItemTypeService, private location: Location, private geolocationService: GeolocationService ) { @@ -107,7 +107,7 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { ngOnInit() { this.store.dispatch(new mapActions.Init()); this.selectedFeatures.next({x:0,y:0,features:[]}); - this.mapState$ = this.store.select(mapReducers.selectGetMapState); + this.mapState = this.store.select(mapReducers.selectGetMapState); this.parentCode = this.store.select(mapReducers.selectGetParentCode); this.features = this.store.select(mapReducers.selectGetFeatures); this.overlayLayers = this.store.select(mapReducers.selectGetOverlayLayers); @@ -126,16 +126,16 @@ export class MapComponent implements OnInit, OnDestroy,AfterViewInit { this.menuVisible = this.store.select(mapReducers.selectGetMenuVisible); this.openedModalName = this.store.select(commonReducers.selectOpenedModalName); this.query = this.store.select(mapReducers.selectGetQuery); - this.extent$ = this.store.select(mapReducers.selectGetExtent); + this.extent = this.store.select(mapReducers.selectGetExtent); this.selectedFeatures.next(null); this.selectedItemLayer = this.store.select(mapReducers.selectGetSelectedItemLayer); this.period = this.store.select(mapReducers.selectGetPeriod); this.position = this.geolocationService.getCurrentPosition(); - this.mapState$.pipe(withLatestFrom(this.queryState)).subscribe((state) => { + this.mapState.pipe(withLatestFrom(this.queryState)).subscribe((state) => { this.replaceUrl(state[0], state[1], true); }); - this.query.pipe(withLatestFrom(this.mapState$)).subscribe((state) => { + this.query.pipe(withLatestFrom(this.mapState)).subscribe((state) => { this.replaceUrl(state[1], state[0],false); }); } diff --git a/projects/common-map/src/fm-map/services/geolocation.service.ts b/projects/common-map/src/fm-map/services/geolocation.service.ts index 973e590..f7732dd 100644 --- a/projects/common-map/src/fm-map/services/geolocation.service.ts +++ b/projects/common-map/src/fm-map/services/geolocation.service.ts @@ -22,7 +22,6 @@ export class GeolocationService { navigator.geolocation.watchPosition( (position: Position) => { observer.next(position); - observer.complete(); }, (error: PositionError) => { console.log('Geolocation service: ' + error.message); diff --git a/projects/common/package.json b/projects/common/package.json index feb5bdc..a413d68 100644 --- a/projects/common/package.json +++ b/projects/common/package.json @@ -18,6 +18,7 @@ "@ngrx/store": "^7.2", "tassign": "^1.0.0", "bootstrap": "^4.3.1", - "@aspnet/signalr": "^1.1.4" + "@aspnet/signalr": "^1.1.4", + "font-awesome": "^4.7.0" } } diff --git a/projects/common/src/fm/common.module.ts b/projects/common/src/fm/common.module.ts index 7d785eb..7da9a9c 100644 --- a/projects/common/src/fm/common.module.ts +++ b/projects/common/src/fm/common.module.ts @@ -32,6 +32,7 @@ import { AuthGuard } from './services/auth-guard.service'; import { NavBarGuard } from './services/nav-bar-guard.service'; import { FullScreenGuard } from './services/full-screen-guard.service'; import { SafePipe } from './shared/safe.pipe'; +import { AppComponent} from './components/app/app.component'; import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component'; import { AuthCallbackGuard } from './components/auth-callback/auth-callback.guard'; import { SessionClearedComponent } from './components/session-cleared/session-cleared.component'; @@ -70,6 +71,7 @@ export {FolderService, SafePipe, AuthCallbackComponent, AuthCallbackGuard, + AppComponent, SessionClearedComponent, ResumableFileUploadService, ResumableFileUploadComponent, @@ -108,6 +110,7 @@ export {FolderService, DatePipe ], declarations: [ + AppComponent, AuthCallbackComponent, SidePanelComponent, SafePipe, @@ -121,6 +124,7 @@ export {FolderService, NgbModule, UploadxModule, CommonModule, + AppComponent, ResumableFileUploadComponent, AuthCallbackComponent, SidePanelComponent, diff --git a/projects/common/src/fm/components/app/app.component.html b/projects/common/src/fm/components/app/app.component.html new file mode 100644 index 0000000..8667157 --- /dev/null +++ b/projects/common/src/fm/components/app/app.component.html @@ -0,0 +1,14 @@ +
+ +
+ +
+ +
diff --git a/projects/common/src/fm/components/app/app.component.scss b/projects/common/src/fm/components/app/app.component.scss new file mode 100644 index 0000000..d54f415 --- /dev/null +++ b/projects/common/src/fm/components/app/app.component.scss @@ -0,0 +1,72 @@ +//@import "theme.scss"; + +/* Import Bootstrap & Fonts */ + +@import "~bootstrap/scss/bootstrap.scss"; + + +// custom styles + +.btn:focus { + box-shadow:none; +} + +.input-group > .form-control:focus { + z-index: auto; +} + +.form-control:focus { + box-shadow: none; + border-color: $input-border-color; +} + + +/* *** Overall APP Styling can go here *** + -------------------------------------------- + Note: This Component has ViewEncapsulation.None so the styles will bleed out + +*/ + +body { background: #f1f1f1; line-height: 18px; user-select:none;} + +.navbar-brand { + padding-top: .5rem; + padding-bottom: .5rem; +} + +.app { + width:100vw; + height:100vh; +} + +.app > .navbar { + position: absolute; + transition: top 0.5s ease-out; + top:0; + left: 0; + right: 0; + height: 3.1rem; +} + +.app > .body { + position: absolute; + transition: top 0.5s ease-out; + top: 3.1rem; + bottom: 0; + left: 0; + right: 0; + overflow:hidden; +} + +.app.fullscreen > .navbar { + top: -3.1rem; +} + +.app.fullscreen > .body { + top:0; +} + +.btn-primary, .btn-primary:hover { + color: #ffffff; +} + diff --git a/projects/common/src/fm/components/app/app.component.ts b/projects/common/src/fm/components/app/app.component.ts new file mode 100644 index 0000000..cafc2e8 --- /dev/null +++ b/projects/common/src/fm/components/app/app.component.ts @@ -0,0 +1,129 @@ +import { Component, OnInit, OnDestroy, Inject, ViewEncapsulation, RendererFactory2, PLATFORM_ID, ChangeDetectionStrategy, HostListener } from '@angular/core'; +import { Router, NavigationEnd, RouteConfigLoadStart, RouteConfigLoadEnd, ActivatedRoute, PRIMARY_OUTLET } from '@angular/router'; +import { Meta, Title, DOCUMENT, MetaDefinition } from '@angular/platform-browser'; +import { Subscription , Observable } from 'rxjs'; +import { Store, Action } from '@ngrx/store'; + +//AppCommon +import { IEventMessage } from '../../models/event.message'; +import { IListItem} from '../../models/list.item'; +import { EventService } from '../../services/event.service'; +import * as commonActions from '../../actions/app-common.actions'; + +import * as appReducers from '../../reducers/app-common.reducer'; + +@Component({ + selector: 'fm-app', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AppComponent implements OnInit, OnDestroy { + + // This will go at the END of your title for example "Home - Angular Universal..." <-- after the dash (-) + private endPageTitle: string = 'Farmmaps'; + // If no Title is provided, we'll use a default one before the dash(-) + private defaultPageTitle: string = 'Farmmaps'; + + private routerSub$: Subscription; + private eventSub$: Subscription; + + public currentFolder: Observable; + public folderParents: Observable; + public browseFileElement: any; + public browseDirectoryElement: any; + public fileDroptarget: any; + public fullScreen: Observable; + public routeLoading: Observable; + + constructor( + private router: Router, + private activatedRoute: ActivatedRoute, + private title: Title, + private meta: Meta, + private store: Store, + private eventService: EventService, + ) { + } + + + + getActionFromEvent(event: IEventMessage): Action { + var action: Action = null; + console.log(`${event.eventType} Event received`); + switch (event.eventType) { + case "ItemChanged": { + action = new commonActions.ItemChangedEvent(event.itemCode, event.attributes); + break; + } + case "ItemAdded": { + action = new commonActions.ItemAddedEvent(event.itemCode, event.attributes); + break; + } + case "ItemDeleted": { + action = new commonActions.ItemDeletedEvent(event.itemCode, event.attributes); + break; + } + case "taskStart": { + action = new commonActions.TaskStartEvent(event.itemCode, event.attributes); + break; + } + case "taskEnd": { + action = new commonActions.TaskEndEvent(event.itemCode, event.attributes); + break; + } + case "taskError": { + action = new commonActions.TaskErrorEvent(event.itemCode, event.attributes); + break; + } + } + return action; + } + + ngOnInit() { + this.fullScreen = this.store.select(appReducers.selectGetFullScreen); + this.routeLoading = this.store.select(appReducers.selectGetRouteLoading); + this.InstallRouteEventHandler(); + this.InstallEventServiceEventHandler(); + } + + @HostListener('document:keyup', ['$event']) + keyUp(event: KeyboardEvent) { + let x = event.keyCode; + if (x === 27) { + this.store.dispatch(new commonActions.Escape(true,false)); + } + } + + ngOnDestroy() { + // Subscription clean-up + if(this.routerSub$) this.routerSub$.unsubscribe(); + if(this.eventSub$) this.eventSub$.unsubscribe(); + } + + private InstallRouteEventHandler() { + var other = this; + this.routerSub$ = this.router.events.subscribe(event => { + if (event instanceof RouteConfigLoadStart) { + other.store.dispatch(new commonActions.StartRouteLoading()); + } + if (event instanceof RouteConfigLoadEnd) { + other.store.dispatch(new commonActions.EndRouteLoading()); + } + }); + } + + private InstallEventServiceEventHandler() { + var other = this; + this.eventSub$ = this.eventService.event.subscribe(event => { + var action = other.getActionFromEvent(event); + if (action) other.store.dispatch(action); + }); + } + + handleClick(event: MouseEvent) { + this.store.dispatch(new commonActions.Escape(false,true)); + } +} + diff --git a/projects/common/src/fm/reducers/app-common.reducer.ts b/projects/common/src/fm/reducers/app-common.reducer.ts index 3605534..835a580 100644 --- a/projects/common/src/fm/reducers/app-common.reducer.ts +++ b/projects/common/src/fm/reducers/app-common.reducer.ts @@ -12,7 +12,9 @@ export interface State { initialized: boolean, rootItems: IListItem[], itemTypes: IItemTypes, - user:IUser + user:IUser, + fullScreen: boolean, + routeLoading:boolean } export const initialState: State = { @@ -20,7 +22,9 @@ export const initialState: State = { initialized: false, rootItems: [], itemTypes: {}, - user:null + user:null, + fullScreen: true, + routeLoading: false } export function reducer(state = initialState, action: appCommonActions.Actions ): State { @@ -46,6 +50,26 @@ export function reducer(state = initialState, action: appCommonActions.Actions ) let a = action as appCommonActions.LoadItemTypesSuccess; return tassign(state, { itemTypes: a.itemTypes }); } + case appCommonActions.FULLSCREEN: { + return tassign(state, { + fullScreen:true + }); + } + case appCommonActions.SHOWNAVBAR: { + return tassign(state, { + fullScreen: false + }); + } + case appCommonActions.STARTROUTELOADING: { + return tassign(state, { + routeLoading: true + }); + } + case appCommonActions.ENDROUTELOADING: { + return tassign(state, { + routeLoading: false + }); + } default: { return state; } @@ -56,6 +80,9 @@ export const getOpenedModalName = (state: State) => state.openedModalName; export const getInitialized = (state: State) => state.initialized; export const getItemTypes = (state: State) => state.itemTypes; export const getRootItems = (state: State) => state.rootItems; +export const getFullScreen = (state: State) => state.fullScreen; +export const getRouteLoading = (state: State) => state.routeLoading; + export const selectAppCommonState = createFeatureSelector(MODULE_NAME); @@ -63,3 +90,6 @@ export const selectOpenedModalName = createSelector(selectAppCommonState, getOpe export const selectGetInitialized = createSelector(selectAppCommonState, getInitialized); export const selectGetItemTypes = createSelector(selectAppCommonState, getItemTypes); export const selectGetRootItems = createSelector(selectAppCommonState, getRootItems); +export const selectGetFullScreen = createSelector(selectAppCommonState, getFullScreen); +export const selectGetRouteLoading = createSelector(selectAppCommonState, getRouteLoading); + diff --git a/projects/common/src/fm/services/event.service.ts b/projects/common/src/fm/services/event.service.ts index 41f5525..70755b7 100644 --- a/projects/common/src/fm/services/event.service.ts +++ b/projects/common/src/fm/services/event.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { IEventMessage } from '../models/event.message'; import { Subject } from 'rxjs'; import { OAuthService } from 'angular-oauth2-oidc'; -import { HubConnection, HubConnectionBuilder, LogLevel } from '@aspnet/signalr'; +import { HubConnection, HubConnectionBuilder, LogLevel ,HttpTransportType} from '@aspnet/signalr'; import { AppConfig } from "../shared/app.config"; @@ -15,15 +15,21 @@ export class EventService { constructor(private oauthService: OAuthService, private appConfig: AppConfig) { this._apiEndPoint = appConfig.getConfig("apiEndPoint"); - this._connection = new HubConnectionBuilder().withUrl(`${ this._apiEndPoint}/eventHub`).configureLogging(LogLevel.Information).build(); + this._connection = new HubConnectionBuilder().withUrl(`${ this._apiEndPoint}/eventHub`, + { transport: HttpTransportType.WebSockets, + // accessTokenFactory: () => { + // return oauthService.getAccessToken(); + // }, + skipNegotiation:true + }).configureLogging(LogLevel.Information).build(); + this._connection.on('event', eventMessage => { + this.event.next(eventMessage); + }); this._connection.start().then(() => { var accessToken = oauthService.getAccessToken(); if (accessToken) { this._connection.send('authenticate', oauthService.getAccessToken()); } - }); - this._connection.on('event', eventMessage => { - this.event.next(eventMessage); - }); + }); } } diff --git a/src/app/app-content.component.ts b/src/app/app-content.component.ts deleted file mode 100644 index 4f56d95..0000000 --- a/src/app/app-content.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-content', - template: '
Hello daar
' -}) -export class AppContentComponent { -} \ No newline at end of file diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index ad26c34..bc8eb9e 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -3,8 +3,6 @@ import { RouterModule } from '@angular/router'; import { AuthGuard,FullScreenGuard } from '@farmmaps/common'; import { MapComponent} from '@farmmaps/common-map'; -import { AppContentComponent} from './app-content.component'; -import { AppSidePanelTestComponent } from './app-side-panel-test.component'; const routes = [ { @@ -12,7 +10,6 @@ const routes = [ redirectTo: 'map', pathMatch: 'full' }, - { path: 'sidepanel', canLoad: [AuthGuard], component: AppSidePanelTestComponent}, { path: 'map', canActivateChild: [AuthGuard],canActivate:[FullScreenGuard], children: [ { path: '', diff --git a/src/app/app-side-panel-test.component.ts b/src/app/app-side-panel-test.component.ts deleted file mode 100644 index 3887d08..0000000 --- a/src/app/app-side-panel-test.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Component ,ChangeDetectorRef } from '@angular/core'; - - - -@Component({ - selector: 'app-side-panel-test', - template: '' -}) -export class AppSidePanelTestComponent { - - public show:boolean = false; - - constructor(public cr:ChangeDetectorRef ) { - - } - - handleClose(event:MouseEvent) { - event.preventDefault(); - this.show=false; - //this.cr.detectChanges(); - } - - handleOpen(event:MouseEvent) - { - event.preventDefault(); - this.show=true; - //this.cr.detectChanges(); - } -} \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html index b762168..506f70a 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,3 +1,3 @@ -
+ diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 30b5b91..e69de29 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,27 +0,0 @@ -@import "theme.scss"; - -$fa-font-path: "~font-awesome/fonts"; -@import "~bootstrap/scss/bootstrap.scss"; -@import "~font-awesome/scss/font-awesome.scss"; - -:host ::ng-deep .btn:focus { - box-shadow:none; -} - -:host ::ng-deep .input-group > .form-control:focus { - z-index: auto; -} - -:host ::ng-deep .form-control:focus { - box-shadow: none; - border-color: $input-border-color; -} - -:host ::ng-deep body { - background: #f1f1f1; - line-height: 18px; - user-select:none; -} - - - diff --git a/src/app/app.component.ts b/src/app/app.component.ts index eedc897..51a6f2d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -5,6 +5,6 @@ import { Component } from '@angular/core'; templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) -export class AppComponent { +export class AppRootComponent { title = 'farmmaps-lib-app'; } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 7712c5a..781f739 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -6,12 +6,11 @@ import { } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; -import { AppComponent } from './app.component'; -import { AppContentComponent } from './app-content.component'; -import { AppSidePanelTestComponent } from './app-side-panel-test.component'; -import { AppCommonModule } from '@farmmaps/common'; +import { AppCommonModule, } from '@farmmaps/common'; import { AppCommonMapModule} from '@farmmaps/common-map'; +import {AppRootComponent} from './app.component'; + import {StoreModule, Store} from '@ngrx/store'; import {EffectsModule, EffectSources} from '@ngrx/effects'; import { StoreRouterConnectingModule} from '@ngrx/router-store'; @@ -45,9 +44,7 @@ export function provideBootstrapEffects(effects: Type[]) { @NgModule({ declarations: [ - AppComponent, - AppContentComponent, - AppSidePanelTestComponent + AppRootComponent ], imports: [ AppRoutingModule, @@ -58,6 +55,6 @@ export function provideBootstrapEffects(effects: Type[]) { EffectsModule.forRoot([]) ], providers: [], - bootstrap: [AppComponent] + bootstrap: [AppRootComponent] }) export class AppModule { } diff --git a/src/configuration.json b/src/configuration.json index 341b778..bfe2910 100644 --- a/src/configuration.json +++ b/src/configuration.json @@ -1,7 +1,7 @@ { "issuer": "http://accounts.awtest.nl", "clientId": "v1t", - "audience": "http://farmmaps.awtest.nl/,http://awtest.nl/,http://aan.awtest.nl", + "audience": "http://farmmaps.awtest.nl/", "requireHttps": false, "apiEndPoint": "http://farmmaps.awtest.nl" }