Skip to content

Commit

Permalink
About and logout
Browse files Browse the repository at this point in the history
  • Loading branch information
newmanw committed Jun 27, 2024
1 parent 4606e76 commit 69b476d
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 66 deletions.
116 changes: 62 additions & 54 deletions web-app/src/app/about/about.component.html
Original file line number Diff line number Diff line change
@@ -1,59 +1,67 @@
<div class="content-flex about-content">
<h2>About MAGE Server {{mageVersion.major}}.{{mageVersion.minor}}.{{mageVersion.micro}}</h2>
<p>
MAGE is a dynamic, secure, mobile situational awareness and field data collection platform that supports
low-bandwidth and disconnected users. MAGE can integrate with existing command centers and common operating
pictures or stand alone as a complete, mission-ready solution. The MAGE mobile app on iOS and Android
allows agents in the field to create and share geo-tagged observations with attached photos, videos,
audio, and form data. MAGE's data collection forms are easily tailored to suit any team and mission with
custom form fields and map symbologies. In addition to data collection, the MAGE mobile app can optionally
report field agents' locations at regular intervals to the MAGE server. The MAGE server's web app provides
a common operating picture of field agents' observations and latest reported locations.
</p>
<h2 class="top-gap-l">Mobile Applications</h2>
<ul>
<li>Create and view observations with photos, video and voice.</li>
<li>Friendly Force Tracking.</li>
<li>Observation storage and synching for offline usage.</li>
<li>GeoPackage capable, view offline feature and raster data.</li>
</ul>
<div class="app-store-container" ng-if="action === 'signin' || !action">
<div class="app-store-badges">
<a class="app-store-badge" href="https://itunes.apple.com/us/app/m.a.g.e./id1032815042?mt=8"><img
src="/assets/images/ios_app_store_black.svg" height="49"></a>
<a class="app-store-badge" href="https://play.google.com/store/apps/details?id=mil.nga.giat.mage&hl=en"><img
src="/assets/images/google-play-badge.png" height="49"></a>
</div>
</div>
<h2 class="top-gap-l">API</h2>
<p>Browse and try the MAGE API live with <a href="#/swagger">Swagger UI.</a></p>
<p><strong>Important:</strong> Swagger interactive documentation will modify MAGE data via API calls; please be
careful with <strong>POST/PUT/DELETE</strong> operations.</p>
<div ng-if="nodeVersion && mongoVersion">
<h2>System</h2>
<ul>
<li>Node Version: {{nodeVersion}}</li>
<li>MongoDB Version: {{mongoVersion}}</li>
</ul>
<mat-toolbar color="primary">
<div class="container">
<button mat-icon-button (click)="onBack()">
<mat-icon>arrow_back</mat-icon>
</button>

<span class="title">About</span>
</div>
<h2 class="top-gap-l">Acknowledgements</h2>
<div class="row bottom-gap-l">
<div class="col-md-6">
<h4>Tech Stack</h4>
<p>The MAGE server is built on <a href="http://nodejs.org/" target="_blank">NodeJS</a>, with data stored in <a
href="http://www.mongodb.org/" target="_blank">MongoDB</a> via <a href="http://mongoosejs.com/"
target="_blank">mongoose</a>. Routing provided with <a href="http://expressjs.com/"
target="_blank">express</a>, and authentication with <a href="http://passportjs.org/"
target="_blank">passport</a>.</p>
<p>The front end maps are powered by <a href="http://leafletjs.com/" target="_blank">Leaflet</a>. The responsive
layouts and buttons are styled by a modified version of <a href="http://getbootstrap.com/"
target="_blank">Bootstrap</a>. The whole front end is tied together by <a href="http://angularjs.org/"
target="_blank">AngularJS</a>.</p>
</mat-toolbar>

<div class="content">
<div>
<div class="mat-h1">About</div>
<p>
MAGE is a dynamic, secure, mobile situational awareness and field data collection platform that supports
low-bandwidth and disconnected users. MAGE can integrate with existing command centers and common operating
pictures or stand alone as a complete, mission-ready solution. The MAGE mobile app on iOS and Android
allows agents in the field to create and share geo-tagged observations with attached photos, videos,
audio, and form data. MAGE's data collection forms are easily tailored to suit any team and mission with
custom form fields and map symbologies. In addition to data collection, the MAGE mobile app can optionally
report field agents' locations at regular intervals to the MAGE server. The MAGE server's web app provides
a common operating picture of field agents' observations and latest reported locations.
</p>

<div class="app-store">
<a href="https://itunes.apple.com/us/app/m.a.g.e./id1032815042?mt=8">
<img class="app-store-icon" src="/assets/images/ios_app_store_black.svg">
</a>
<a href="https://play.google.com/store/apps/details?id=mil.nga.giat.mage&hl=en">
<img class="app-store-icon" src="/assets/images/google-play-badge.png">
</a>
</div>
<div class="col-md-6">
<h4>Iconography</h4>
<p>The icons used throughout the app come from <a href="https://github.com/FortAwesome/Font-Awesome"
target="_blank">Font Awesome</a></p>
</div>

<div>
<div class="mat-h1">API</div>
<div>
Browse and try the MAGE API live with <a href="#/swagger">Swagger UI.</a> Swagger interactive documentation will modify MAGE data via API calls; please be careful with <strong>POST/PUT/DELETE</strong> operations.
</div>
</div>

<div>
<div class="mat-h1">System</div>
<div>Server Version {{mageVersion.major}}.{{mageVersion.minor}}.{{mageVersion.micro}}</div>
<div>Node Version {{nodeVersion}}</div>
<div>MongoDB Version {{mongoVersion}}</div>
</div>

<div>
<div class="mat-h1">Acknowledgements</div>
<div>The MAGE is built with the MEAN stack;
<a href="https://www.mongodb.org/" target="_blank">MongoDB</a>,
<a href="https://expressjs.com/" target="_blank">Express</a>,
<a href="https://angular.dev/" target="_blank">Angular</a> and
<a href="https://nodejs.org/" target="_blank">NodeJS</a>.
</div>

<div>Authentication is locked down by
<a href="https://passportjs.org/" target="_blank">Passport</a>
</div>

<div>Maps are powered by
<a href="https://leafletjs.com/" target="_blank">Leaflet</a>
</div>
</div>

</div>
37 changes: 37 additions & 0 deletions web-app/src/app/about/about.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@use '@angular/material' as mat;
@import "variables.scss";

.content {
width: 50vw;
margin: 0 auto;
padding: 32px 0;
display: flex;
flex-direction: column;
gap: 32px;
}

.mat-h1 {
color: mat.get-color-from-palette($app-primary);
}

.container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}

.title {
margin-left: 16px;
}

.app-store {
display: flex;
flex-direction: row;
gap: 16px;
align-items: center;
}

.app-store-icon {
height: 48px;
}
6 changes: 6 additions & 0 deletions web-app/src/app/about/about.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component, Inject, OnInit } from '@angular/core';
import { ApiService } from '../api/api.service';
import { Router } from '@angular/router';

@Component({
selector: 'about',
Expand All @@ -19,6 +20,7 @@ export class AboutComponent implements OnInit {
mongoVersion: string

constructor(
private router: Router,
@Inject(ApiService) public apiService: ApiService
) {}

Expand All @@ -31,4 +33,8 @@ export class AboutComponent implements OnInit {
this.mongoVersion = api.environment.mongodbVersion;
})
}

onBack(): void {
this.router.navigate(['map']);
}
}
2 changes: 2 additions & 0 deletions web-app/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,12 @@ import { PollingIntervalComponent } from './preferences/polling-interval/polling
import { TimeFormatComponent } from './preferences/time-format/time-format.component';
import { TimeZoneComponent } from './preferences/time-zone/time-zone.component';
import { CoordinateSystemComponent } from './preferences/coordinate-system/coordinate-system.component';
import { AboutComponent } from './about/about.component';

@NgModule({
declarations: [
AppComponent,
AboutComponent,
NavigationComponent,
ZoomComponent,
AddObservationComponent,
Expand Down
5 changes: 3 additions & 2 deletions web-app/src/app/event/event.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ export class EventService {
}

onEventChanged(event: any) {
event.added.forEach((added: any) => {
const { added = [], removed = [], foo = [] } = event
added.forEach((added: any) => {
if (!this.eventsById[added.id]) {
this.eventsById[added.id] = (JSON.parse(JSON.stringify(added)));

Expand All @@ -83,7 +84,7 @@ export class EventService {
this.fetchFeeds(added);
})

event.removed.forEach((removed: any) => {
removed.forEach((removed: any) => {
this.observationsChanged({ removed: Object.values(this.eventsById[removed.id].filteredObservationsById) });
this.usersChanged({ removed: Object.values(this.eventsById[removed.id].filteredUsersById) });
this.layersChanged({ removed: Object.values(this.eventsById[removed.id].layersById) }, removed);
Expand Down
4 changes: 2 additions & 2 deletions web-app/src/app/navigation/navigation.component.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<mat-toolbar color="primary">
<div class="container">
<div>
<button mat-icon-button class="navigation-options" (click)="openMenu()">
<div class="menu">
<button mat-icon-button class="navigation-options">
<mat-icon>more_vert</mat-icon>
</button>

Expand Down
8 changes: 8 additions & 0 deletions web-app/src/app/navigation/navigation.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}

.menu {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}

.title {
margin-left: 16px;
}
Expand Down
4 changes: 0 additions & 4 deletions web-app/src/app/navigation/navigation.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ export class NavigationComponent implements OnInit, OnDestroy {
this.eventService.destroy();
}

openMenu(): void {

}

toggleFeed(): void {
this.onFeedToggle.emit()
}
Expand Down
4 changes: 2 additions & 2 deletions web-app/src/app/preferences/preferences.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@

<mat-divider class="divider"></mat-divider>

<div matRipple class="preference-item">
<div matRipple class="preference-item" (click)="onAbout()">
<mat-icon class="material-icons-outlined">info</mat-icon>
<div>About</div>
</div>

<div matRipple class="preference-item">
<div matRipple class="preference-item" (click)="onLogout()">
<mat-icon>logout</mat-icon>
<div>Logout</div>
</div>
Expand Down
10 changes: 10 additions & 0 deletions web-app/src/app/preferences/preferences.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { UserService } from '../user/user.service';
import { Router } from '@angular/router';

@Component({
selector: 'preferences',
Expand All @@ -10,10 +11,19 @@ export class PreferencesComponent implements OnInit {
user: any

constructor(
private router: Router,
private userService: UserService
) {}

ngOnInit(): void {
this.user = this.userService.myself
}

onAbout(): void {
this.router.navigate(['about']);
}

onLogout(): void {
this.userService.logout()
}
}
4 changes: 4 additions & 0 deletions web-app/src/app/routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AuthorizeComponent } from './authentication/authorize.component';
import { MageComponent } from './mage/mage.component';
import { ApiResolver } from './api/api.resolver';
import { UserResolver } from './authentication/user.resolver';
import { AboutComponent } from './about/about.component';

const appRoutes: Routes = [{
path: '',
Expand Down Expand Up @@ -34,6 +35,9 @@ const appRoutes: Routes = [{
resolve: {
user: UserResolver
}
},{
path: 'about',
component: AboutComponent
}];

@NgModule({
Expand Down
27 changes: 25 additions & 2 deletions web-app/src/app/user/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { HttpClient } from '@angular/common/http'
import { HttpClient, HttpEvent, HttpResponse } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Router } from '@angular/router'
import { Observable, Subject } from 'rxjs'
import { LocalStorageService } from '../http/local-storage.service'

@Injectable({
providedIn: 'root'
Expand All @@ -10,7 +12,11 @@ export class UserService {
myself: any
amAdmin: boolean

constructor(private httpClient: HttpClient) { }
constructor(
private router: Router,
private httpClient: HttpClient,
private localStorageService: LocalStorageService
) { }

signin(username: string, password: string): Observable<any> {
const body = {
Expand Down Expand Up @@ -100,4 +106,21 @@ export class UserService {
var recentEventIds = this.myself.recentEventIds;
return recentEventIds.length > 0 ? recentEventIds[0] : null;
}

logout() {
const observable = this.httpClient.post('/api/logout', null, { responseType: 'text' })
observable.subscribe(() => {
console.log('logged out user')
this.clearUser();
this.router.navigate(['landing']);
})

return observable;
}

private clearUser() {
this.myself = null;
this.amAdmin = null;
this.localStorageService.removeToken();
}
}

0 comments on commit 69b476d

Please sign in to comment.