First functional version
All checks were successful
FarmMaps.Develop/FarmMapsLib/develop This commit looks good
All checks were successful
FarmMaps.Develop/FarmMapsLib/develop This commit looks good
This commit is contained in:
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
|
14
projects/common/src/fm/components/app/app.component.html
Normal file
14
projects/common/src/fm/components/app/app.component.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="app fullscreen" (click)="handleClick($event)" [ngClass]="{'fullscreen' :(fullScreen|async)}">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
||||
<a class="navbar-brand" [routerLink]="['/']">Farm Maps <span *ngIf="routeLoading|async"><i class="fa fa-spinner fa-spin"></i></span></a>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item py-0"><a [routerLinkActive]="['active']" [routerLink]="['/map']" class="nav-link"><span><i class="fa fa-globe" aria-hidden="true"></i> Map</span></a></li>
|
||||
<li class="nav-item py-0"><a [routerLinkActive]="['active']" [routerLink]="['/explorer']" class="nav-link"><span><i class="fa fa-folder" aria-hidden="true"></i> Explorer</span></a></li>
|
||||
</ul>
|
||||
<router-outlet name="menu"></router-outlet>
|
||||
</nav>
|
||||
<div class="body">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<fm-resumable-file-upload></fm-resumable-file-upload>
|
||||
</div>
|
72
projects/common/src/fm/components/app/app.component.scss
Normal file
72
projects/common/src/fm/components/app/app.component.scss
Normal file
@@ -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;
|
||||
}
|
||||
|
129
projects/common/src/fm/components/app/app.component.ts
Normal file
129
projects/common/src/fm/components/app/app.component.ts
Normal file
@@ -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<IListItem>;
|
||||
public folderParents: Observable<IListItem[]>;
|
||||
public browseFileElement: any;
|
||||
public browseDirectoryElement: any;
|
||||
public fileDroptarget: any;
|
||||
public fullScreen: Observable<boolean>;
|
||||
public routeLoading: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private title: Title,
|
||||
private meta: Meta,
|
||||
private store: Store<appReducers.State>,
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@@ -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<State>(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);
|
||||
|
||||
|
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user