From 52ae24b85ab002ac790ad7420173fb6a61862bde Mon Sep 17 00:00:00 2001 From: William Newman <3382274+newmanw@users.noreply.github.com> Date: Sun, 1 Sep 2024 12:37:13 -0600 Subject: [PATCH] Refactor navbar and map buttons --- web-app/admin/src/ng1/app.js | 3 ++ web-app/admin/src/ng1/mage/index.js | 5 +-- web-app/src/app/event/event.service.ts | 8 ++-- web-app/src/app/home/home.component.html | 26 +++++++------ web-app/src/app/home/home.component.scss | 13 +++++-- web-app/src/app/home/home.module.ts | 4 ++ .../controls/add-observation.component.html | 2 +- .../controls/add-observation.component.scss | 4 -- .../app/map/controls/export.component.html | 3 ++ .../app/map/controls/export.component.scss | 0 .../app/map/controls/export.component.spec.ts | 29 ++++++++++++++ .../src/app/map/controls/export.component.ts | 23 +++++++++++ .../app/map/controls/filter.component.html | 3 ++ .../app/map/controls/filter.component.scss | 0 .../app/map/controls/filter.component.spec.ts | 29 ++++++++++++++ .../src/app/map/controls/filter.component.ts | 23 +++++++++++ .../app/map/controls/search.component.scss | 1 - .../src/app/map/controls/zoom.component.html | 7 ++-- .../src/app/map/controls/zoom.component.scss | 3 +- web-app/src/app/map/map.component.html | 14 +++++-- web-app/src/app/map/map.component.scss | 38 ++++++++++++++----- web-app/src/app/map/map.component.ts | 18 +++++++++ .../app/navigation/navigation.component.html | 23 ++++++----- .../app/navigation/navigation.component.scss | 7 ++++ .../app/navigation/navigation.component.ts | 19 +--------- .../observation-edit.component.html | 2 +- .../preferences/preferences.component.html | 19 ---------- .../app/preferences/preferences.component.ts | 29 +------------- .../user-avatar/user-avatar.component.html | 2 +- .../user-avatar/user-avatar.component.scss | 5 ++- .../user/user-avatar/user-avatar.component.ts | 2 +- .../user/user-avatar/user-avatar.module.ts | 4 +- 32 files changed, 243 insertions(+), 125 deletions(-) create mode 100644 web-app/src/app/map/controls/export.component.html create mode 100644 web-app/src/app/map/controls/export.component.scss create mode 100644 web-app/src/app/map/controls/export.component.spec.ts create mode 100644 web-app/src/app/map/controls/export.component.ts create mode 100644 web-app/src/app/map/controls/filter.component.html create mode 100644 web-app/src/app/map/controls/filter.component.scss create mode 100644 web-app/src/app/map/controls/filter.component.spec.ts create mode 100644 web-app/src/app/map/controls/filter.component.ts diff --git a/web-app/admin/src/ng1/app.js b/web-app/admin/src/ng1/app.js index 5db51a046..3ea2191f6 100644 --- a/web-app/admin/src/ng1/app.js +++ b/web-app/admin/src/ng1/app.js @@ -1,5 +1,6 @@ import _ from 'underscore'; import angular from 'angular'; +import mage from './mage/mage.component'; import fileUpload from './file-upload/file.upload.component'; import fileBrowser from './file-upload/file.browser.component'; import uiRouter from "@uirouter/angularjs"; @@ -77,6 +78,7 @@ app .directive('adminEventFormPreview', downgradeComponent({ component: AdminEventFormPreviewComponent })); app + .component('mage', mage) .component('navbar', require('./navbar/navbar.component')) .component('filterPanel', require('./filter/filter')) .component('eventFilter', require('./filter/event.filter.component')) @@ -99,6 +101,7 @@ app .config(config) .run(run); +require('./mage'); require('./authentication') // for modal in admin pages if token expires require('./factories'); require('./filters'); diff --git a/web-app/admin/src/ng1/mage/index.js b/web-app/admin/src/ng1/mage/index.js index 22a738adf..f415ab88c 100644 --- a/web-app/admin/src/ng1/mage/index.js +++ b/web-app/admin/src/ng1/mage/index.js @@ -3,10 +3,7 @@ import banner from './banner.component'; import leaflet from './leaflet.component'; angular.module('mage') - .component('mageInfo', require('./mage-info.component.js')) .directive('colorPicker', require('./color.picker.directive')) .directive('equals', require('./equals.directive')) .component('banner', banner) - .component('leaflet', leaflet); - -require('./navbar'); \ No newline at end of file + .component('leaflet', leaflet); \ No newline at end of file diff --git a/web-app/src/app/event/event.service.ts b/web-app/src/app/event/event.service.ts index bedef58b8..03c9cc15e 100644 --- a/web-app/src/app/event/event.service.ts +++ b/web-app/src/app/event/event.service.ts @@ -97,10 +97,10 @@ export class EventService { }) 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); - this.feedItemsChanged({ removed: Object.values(this.eventsById[removed.id].feedsById).map((feed: any) => ({ feed })) }, removed); + 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); + this.feedItemsChanged({ removed: Object.values(this.eventsById[removed.id]?.feedsById || {}).map((feed: any) => ({ feed })) }, removed); delete this.eventsById[removed.id]; }) } diff --git a/web-app/src/app/home/home.component.html b/web-app/src/app/home/home.component.html index 64ce78bcb..80faf38fd 100644 --- a/web-app/src/app/home/home.component.html +++ b/web-app/src/app/home/home.component.html @@ -1,16 +1,18 @@
- - - - - - - - - - - - +
+ + + + + + + + + + + + +
\ No newline at end of file diff --git a/web-app/src/app/home/home.component.scss b/web-app/src/app/home/home.component.scss index 9d86d6cee..8c943fc2d 100644 --- a/web-app/src/app/home/home.component.scss +++ b/web-app/src/app/home/home.component.scss @@ -3,20 +3,25 @@ } .home { + height: 100%; display: flex; flex-direction: column; overflow: hidden; } +.home-content { + flex: 1; +} + +mat-sidenav-container { + height: 100%; +} + .preferences-toolbar { display: flex; align-items: end; } -.main-container { - height: 100vh; -} - .feed { background: #e1e2e1; order: 1; diff --git a/web-app/src/app/home/home.module.ts b/web-app/src/app/home/home.module.ts index 696a71406..93b484786 100644 --- a/web-app/src/app/home/home.module.ts +++ b/web-app/src/app/home/home.module.ts @@ -139,6 +139,8 @@ import { RouterModule, Routes } from '@angular/router'; import { UserResolver } from '../ingress/user.resolver'; import { UserAvatarModule } from '../user/user-avatar/user-avatar.module'; import { IngressModule } from '../ingress/ingress.module'; +import { FilterControlComponent } from '../map/controls/filter.component'; +import { ExportControlComponent } from '../map/controls/export.component'; const routes: Routes = [{ path: '', @@ -156,6 +158,8 @@ const routes: Routes = [{ AddObservationComponent, LocationComponent, SearchComponent, + FilterControlComponent, + ExportControlComponent, MapComponent, PasswordResetSuccessDialog, PreferencesComponent, diff --git a/web-app/src/app/map/controls/add-observation.component.html b/web-app/src/app/map/controls/add-observation.component.html index a7366a2f4..8701d7ee0 100644 --- a/web-app/src/app/map/controls/add-observation.component.html +++ b/web-app/src/app/map/controls/add-observation.component.html @@ -1,3 +1,3 @@ - diff --git a/web-app/src/app/map/controls/add-observation.component.scss b/web-app/src/app/map/controls/add-observation.component.scss index 18cc100d6..5f7be4392 100644 --- a/web-app/src/app/map/controls/add-observation.component.scss +++ b/web-app/src/app/map/controls/add-observation.component.scss @@ -1,7 +1,3 @@ -button { - margin-top: 32px; -} - mat-icon { color: white; } \ No newline at end of file diff --git a/web-app/src/app/map/controls/export.component.html b/web-app/src/app/map/controls/export.component.html new file mode 100644 index 000000000..e93e7bcec --- /dev/null +++ b/web-app/src/app/map/controls/export.component.html @@ -0,0 +1,3 @@ + diff --git a/web-app/src/app/map/controls/export.component.scss b/web-app/src/app/map/controls/export.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/web-app/src/app/map/controls/export.component.spec.ts b/web-app/src/app/map/controls/export.component.spec.ts new file mode 100644 index 000000000..4d6783336 --- /dev/null +++ b/web-app/src/app/map/controls/export.component.spec.ts @@ -0,0 +1,29 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; + +import { AddObservationComponent } from './add-observation.component'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { ExportControlComponent } from './export.component'; + +describe('Export Control Component', () => { + let component: ExportControlComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ MatIconModule, MatButtonModule ], + declarations: [ AddObservationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExportControlComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/web-app/src/app/map/controls/export.component.ts b/web-app/src/app/map/controls/export.component.ts new file mode 100644 index 000000000..303f609c6 --- /dev/null +++ b/web-app/src/app/map/controls/export.component.ts @@ -0,0 +1,23 @@ +import { Component, EventEmitter, Output, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; +import { MatButton } from '@angular/material/button'; +import { DomEvent } from 'leaflet'; + +@Component({ + selector: 'map-control-export', + templateUrl: './export.component.html', + styleUrls: ['./export.component.scss'] +}) +export class ExportControlComponent implements AfterViewInit { + @ViewChild(MatButton, { read: ElementRef }) button: ElementRef; + + @Output() click = new EventEmitter(); + + ngAfterViewInit(): void { + DomEvent.disableClickPropagation(this.button.nativeElement); + } + + onClick($event: MouseEvent): void { + $event.stopPropagation(); + this.click.emit(); + } +} diff --git a/web-app/src/app/map/controls/filter.component.html b/web-app/src/app/map/controls/filter.component.html new file mode 100644 index 000000000..6ead8af3d --- /dev/null +++ b/web-app/src/app/map/controls/filter.component.html @@ -0,0 +1,3 @@ + diff --git a/web-app/src/app/map/controls/filter.component.scss b/web-app/src/app/map/controls/filter.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/web-app/src/app/map/controls/filter.component.spec.ts b/web-app/src/app/map/controls/filter.component.spec.ts new file mode 100644 index 000000000..2afd8ed18 --- /dev/null +++ b/web-app/src/app/map/controls/filter.component.spec.ts @@ -0,0 +1,29 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; + +import { AddObservationComponent } from './add-observation.component'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { FilterControlComponent } from './filter.component'; + +describe('Filter Control Component', () => { + let component: FilterControlComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ MatIconModule, MatButtonModule ], + declarations: [ AddObservationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FilterControlComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/web-app/src/app/map/controls/filter.component.ts b/web-app/src/app/map/controls/filter.component.ts new file mode 100644 index 000000000..386de8974 --- /dev/null +++ b/web-app/src/app/map/controls/filter.component.ts @@ -0,0 +1,23 @@ +import { Component, EventEmitter, Output, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; +import { MatButton } from '@angular/material/button'; +import { DomEvent } from 'leaflet'; + +@Component({ + selector: 'map-control-filter', + templateUrl: './filter.component.html', + styleUrls: ['./filter.component.scss'] +}) +export class FilterControlComponent implements AfterViewInit { + @ViewChild(MatButton, { read: ElementRef }) button: ElementRef; + + @Output() click = new EventEmitter(); + + ngAfterViewInit(): void { + DomEvent.disableClickPropagation(this.button.nativeElement); + } + + onClick($event: MouseEvent): void { + $event.stopPropagation(); + this.click.emit(); + } +} diff --git a/web-app/src/app/map/controls/search.component.scss b/web-app/src/app/map/controls/search.component.scss index 22e54cea3..876a9391d 100644 --- a/web-app/src/app/map/controls/search.component.scss +++ b/web-app/src/app/map/controls/search.component.scss @@ -3,7 +3,6 @@ display: inline-flex; flex-direction: row; align-items: center; - margin-top: 32px; font-family: Roboto, "Helvetica Neue", sans-serif; font-size: 16px; } diff --git a/web-app/src/app/map/controls/zoom.component.html b/web-app/src/app/map/controls/zoom.component.html index 88daf9af2..53b332507 100644 --- a/web-app/src/app/map/controls/zoom.component.html +++ b/web-app/src/app/map/controls/zoom.component.html @@ -1,8 +1,9 @@
- + +
diff --git a/web-app/src/app/map/controls/zoom.component.scss b/web-app/src/app/map/controls/zoom.component.scss index ad4f47ed2..689adb370 100644 --- a/web-app/src/app/map/controls/zoom.component.scss +++ b/web-app/src/app/map/controls/zoom.component.scss @@ -1,6 +1,7 @@ .zoom { display: inline-flex; - flex-direction: column; + flex-direction: row; + gap: 8px; } button:not(:last-child) { diff --git a/web-app/src/app/map/map.component.html b/web-app/src/app/map/map.component.html index cb2977686..acf92ef7b 100644 --- a/web-app/src/app/map/map.component.html +++ b/web-app/src/app/map/map.component.html @@ -1,4 +1,4 @@ -
+
@@ -20,11 +20,17 @@
- - - +
+ + + +
+
+ + +
diff --git a/web-app/src/app/map/map.component.scss b/web-app/src/app/map/map.component.scss index e00ff9da9..06d8fc05e 100644 --- a/web-app/src/app/map/map.component.scss +++ b/web-app/src/app/map/map.component.scss @@ -8,30 +8,50 @@ } .map-container { - height: 100vh; + height: 100%; } .map-content { height: 100%; } +.map-controls-layers { + position: absolute; + right: 16px; + top: 16px; + display: flex; + flex-direction: column; + align-items: end; + justify-content: space-between; + z-index: 1000; +} + .map-controls-left { position: absolute; z-index: 1000; - display: inline-flex; + display: flex; flex-direction: column; - margin-top: 16px; - margin-left: 16px; + justify-content: space-between; + top: 16px; + left: 16px; + bottom: 16px; +} + +.map-controls-left__top { + display: flex; + flex-direction: column; + gap: 16px; } .map-controls-right { + display: flex; + flex-direction: column; + align-items: end; + gap: 16px; position: absolute; - right: 0; + right: 16px; + bottom: 16px; z-index: 1000; - display: inline-flex; - flex-direction: column; - margin-top: 16px; - margin-right: 16px; } mat-sidenav { diff --git a/web-app/src/app/map/map.component.ts b/web-app/src/app/map/map.component.ts index 8ccf42259..98c9a0bf1 100644 --- a/web-app/src/app/map/map.component.ts +++ b/web-app/src/app/map/map.component.ts @@ -25,6 +25,9 @@ import { FilterService } from '../filter/filter.service' import { GARSLayer } from './layers/gars/GARSLayer' import { MGRSLayer } from './layers/mgrs/MGRSLayer' import { UserService } from '../user/user.service' +import { FilterComponent } from '../filter/filter.component' +import { MatDialog } from '@angular/material/dialog' +import { ExportDialogComponent } from '../export/export-dialog.component' Icon.Default.imagePath = '/' @@ -90,6 +93,7 @@ export class MapComponent implements OnDestroy, AfterViewInit { pollListener: any constructor( + public dialog: MatDialog, private mapService: MapService, private userService: UserService, private layerService: MapLayerService, @@ -286,6 +290,20 @@ export class MapComponent implements OnDestroy, AfterViewInit { } } + onFilter() { + this.dialog.open(FilterComponent, { + height: '580px', + width: '675px' + }); + } + + onExport() { + this.dialog.open(ExportDialogComponent).afterClosed().subscribe(result => { + if (!result || result === 'closeAction') { + } + }); + } + onPoll() { this.adjustTemporalLayers() } diff --git a/web-app/src/app/navigation/navigation.component.html b/web-app/src/app/navigation/navigation.component.html index 4360ebc0b..0a2e6bbd2 100644 --- a/web-app/src/app/navigation/navigation.component.html +++ b/web-app/src/app/navigation/navigation.component.html @@ -14,27 +14,30 @@
{{filteredEvent.name}} - > {{filteredTeams}} + > {{filteredTeams}} {{filteredInterval}}
- - + + account_circle + + + + info + admin_panel_settings - - + + logout +
\ No newline at end of file diff --git a/web-app/src/app/navigation/navigation.component.scss b/web-app/src/app/navigation/navigation.component.scss index ad07672e0..f2570f2ed 100644 --- a/web-app/src/app/navigation/navigation.component.scss +++ b/web-app/src/app/navigation/navigation.component.scss @@ -21,6 +21,13 @@ margin-left: 16px; } +.profile-avatar { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + @media(min-width:900px) { .navigation-options { visibility: hidden; diff --git a/web-app/src/app/navigation/navigation.component.ts b/web-app/src/app/navigation/navigation.component.ts index b7ad12f48..65a40f69a 100644 --- a/web-app/src/app/navigation/navigation.component.ts +++ b/web-app/src/app/navigation/navigation.component.ts @@ -1,13 +1,10 @@ import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { FilterComponent } from '../filter/filter.component'; import { FilterService } from '../filter/filter.service'; import { MapService } from '../map/map.service'; import { UserService } from '../user/user.service'; import { EventService } from '../event/event.service'; import { PollingService } from '../event/polling.service'; import * as _ from 'underscore'; -import { ExportDialogComponent } from '../export/export-dialog.component'; @Component({ selector: 'navigation', @@ -25,7 +22,6 @@ export class NavigationComponent implements OnInit, OnDestroy { feedChangedUsers = {} constructor( - public dialog: MatDialog, private mapService: MapService, private userService: UserService, private eventService: EventService, @@ -74,11 +70,8 @@ export class NavigationComponent implements OnInit, OnDestroy { this.onPreferencesToggle.emit() } - onFilter(): void { - this.dialog.open(FilterComponent, { - height: '580px', - width: '675px' - }); + onLogout() { + } onFilterChanged(filter) { @@ -106,12 +99,4 @@ export class NavigationComponent implements OnInit, OnDestroy { } } } - - onExport(): void { - this.dialog.open(ExportDialogComponent).afterClosed().subscribe(result => { - if (!result || result === 'closeAction') { - } - }); - } - } diff --git a/web-app/src/app/observation/observation-edit/observation-edit.component.html b/web-app/src/app/observation/observation-edit/observation-edit.component.html index cb6de3fbb..2d973a7f1 100644 --- a/web-app/src/app/observation/observation-edit/observation-edit.component.html +++ b/web-app/src/app/observation/observation-edit/observation-edit.component.html @@ -64,7 +64,7 @@
- diff --git a/web-app/src/app/preferences/preferences.component.html b/web-app/src/app/preferences/preferences.component.html index 2cbb47be8..dd52d05a2 100644 --- a/web-app/src/app/preferences/preferences.component.html +++ b/web-app/src/app/preferences/preferences.component.html @@ -1,11 +1,4 @@
-
- -
{{user?.displayName}}
-
{{user?.email}}
-
{{user?.phone}}
-
-
Preferences
@@ -23,17 +16,5 @@
- - - -
- info -
About
-
- -
- logout -
Logout
-
diff --git a/web-app/src/app/preferences/preferences.component.ts b/web-app/src/app/preferences/preferences.component.ts index bb94b4e5d..4fd3270ab 100644 --- a/web-app/src/app/preferences/preferences.component.ts +++ b/web-app/src/app/preferences/preferences.component.ts @@ -1,33 +1,8 @@ -import { Component, OnInit } from '@angular/core'; -import { UserService } from '../user/user.service'; -import { Router } from '@angular/router'; +import { Component } from '@angular/core'; @Component({ selector: 'preferences', templateUrl: './preferences.component.html', styleUrls: ['./preferences.component.scss'] }) -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() - } - - onProfile(): void { - this.router.navigate(['profile']); - } -} \ No newline at end of file +export class PreferencesComponent {} \ No newline at end of file diff --git a/web-app/src/app/user/user-avatar/user-avatar.component.html b/web-app/src/app/user/user-avatar/user-avatar.component.html index 28f79ec0d..0b033e1f1 100644 --- a/web-app/src/app/user/user-avatar/user-avatar.component.html +++ b/web-app/src/app/user/user-avatar/user-avatar.component.html @@ -1,2 +1,2 @@ -account_circle \ No newline at end of file +account_circle \ No newline at end of file diff --git a/web-app/src/app/user/user-avatar/user-avatar.component.scss b/web-app/src/app/user/user-avatar/user-avatar.component.scss index d0fd3490f..8fa141d7d 100644 --- a/web-app/src/app/user/user-avatar/user-avatar.component.scss +++ b/web-app/src/app/user/user-avatar/user-avatar.component.scss @@ -2,8 +2,11 @@ border-radius: 50%; overflow: hidden; background: #FFFFFF; + vertical-align: middle; } .icon { + vertical-align: middle; color: rgba($color: #000000, $alpha: .4); -} \ No newline at end of file +} + diff --git a/web-app/src/app/user/user-avatar/user-avatar.component.ts b/web-app/src/app/user/user-avatar/user-avatar.component.ts index 36f1a00e8..388351fef 100644 --- a/web-app/src/app/user/user-avatar/user-avatar.component.ts +++ b/web-app/src/app/user/user-avatar/user-avatar.component.ts @@ -14,7 +14,7 @@ export class UserAvatarComponent implements OnChanges { @Input() avatarHeight = 40 data: string | ArrayBuffer - url: string | SafeUrl = '/assets/images/baseline-account_circle-24px.svg'; + url?: SafeUrl = null constructor( private httpClient: HttpClient, diff --git a/web-app/src/app/user/user-avatar/user-avatar.module.ts b/web-app/src/app/user/user-avatar/user-avatar.module.ts index 5ddbc94d2..da3f0b067 100644 --- a/web-app/src/app/user/user-avatar/user-avatar.module.ts +++ b/web-app/src/app/user/user-avatar/user-avatar.module.ts @@ -1,13 +1,15 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { UserAvatarComponent } from './user-avatar.component'; +import { MatIconModule } from '@angular/material/icon'; @NgModule({ declarations: [ UserAvatarComponent ], imports: [ - CommonModule + CommonModule, + MatIconModule ], exports: [ UserAvatarComponent ] })