Skip to content

Commit

Permalink
Merge pull request #349 from AuScope/AUS-4035
Browse files Browse the repository at this point in the history
AUS-4035 Added ROI(region of interest) for user.
  • Loading branch information
vjf authored May 2, 2024
2 parents d26582f + a575321 commit 58ae331
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 10 deletions.
6 changes: 5 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ import { CreatePermanentLinkModalComponent } from './modalwindow/permanentlink/c
import { AddRegistryModalComponent } from './modalwindow/registry/add-registry.modal.component';
import { ConfirmModalComponent } from './modalwindow/confirm/confirm.modal.component';

import { ROIModalComponent } from './modalwindow/roi/roi.modal.component';

// Services
import { AuscopeApiService } from './services/api/auscope-api.service';
import { FilterService } from './services/filter/filter.service';
Expand Down Expand Up @@ -120,6 +122,7 @@ import { AuthService } from './services/auth/auth.service';
import { LayerGroupComponent } from './menupanel/custompanel/layergroup.component';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthErrorHandlerInterceptor } from './interceptors/auth-error.interceptor';
import { ROIModule } from './modalwindow/roi/roi.modal.modules';

PlotlyModule.plotlyjs = PlotlyJS;

Expand Down Expand Up @@ -215,7 +218,8 @@ PlotlyModule.plotlyjs = PlotlyJS;
FormsModule,
ReactiveFormsModule,
BrowserModule,
DragDropModule
DragDropModule,
ROIModule
],
bootstrap: [
AppComponent
Expand Down
1 change: 1 addition & 0 deletions src/app/cesium-map/csmap.clipboard.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<input type="file" accept=".kml" class="file-input" (change)="onKmlFileSelected($event)" #KmlFileLoader>
<button (click)="KmlFileLoader.click()" type="button" title="Load polygon from KML file" [ngStyle]="{'background-color': isDrawingPolygon ? '#282572' : '#303336'}" class="cesium-button cesium-toolbar-button editor-button"><i class="fa fa-lg fa-file" aria-hidden="true"></i>Load</button>
<button (click)="onKmlFileSave()" type="button" title="Save polygon to KML file" [ngStyle]="{'background-color': isDrawingPolygon ? '#282572' : '#303336'}" class="cesium-button cesium-toolbar-button editor-button"><i class="fa fa-lg fa-floppy-o" aria-hidden="true"></i>Save</button>
<button (click)="onRoiSave()" type="button" title="Save to ROI" [ngStyle]="{'background-color': isDrawingPolygon ? '#282572' : '#303336'}" class="cesium-button cesium-toolbar-button editor-button" ><img src="extension/svg/polygon.svg" fill="#000000" width="24" height="24" style="color:#edffff;">ROI </button>
<button (click)='toggleFilterLayers()' type="button" title="Toggle applicable layers" class="cesium-button cesium-toolbar-button editor-button">
<i *ngIf="!isFilterLayerShown" class="fa fa-lg fa-toggle-off" aria-hidden="true"></i>
<i *ngIf="isFilterLayerShown" class="fa fa-lg fa-toggle-on" aria-hidden="true"></i>
Expand Down
15 changes: 12 additions & 3 deletions src/app/cesium-map/csmap.clipboard.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { animate, style, transition, trigger } from '@angular/animations';
import { CsClipboardService, DownloadWfsService, Polygon } from '@auscope/portal-core-ui';
import { Component, OnInit } from '@angular/core';
import { isNumber } from '@turf/helpers';
import { isNumber, polygon } from '@turf/helpers';
import { saveAs } from 'file-saver';
import { UserStateService } from 'app/services/user/user-state.service';

@Component({
selector: 'app-cs-clipboard',
Expand Down Expand Up @@ -30,7 +31,7 @@ export class CsMapClipboardComponent implements OnInit {
kmlFileName = '';


constructor(private csClipboardService: CsClipboardService, private downloadWfsService: DownloadWfsService) {
constructor(private csClipboardService: CsClipboardService, private userStateService: UserStateService, private downloadWfsService: DownloadWfsService) {
this.polygonBBox = null;
this.isFilterLayerShown = false;
this.csClipboardService.filterLayersBS.subscribe(filterLayerStatus => {
Expand All @@ -52,7 +53,15 @@ export class CsMapClipboardComponent implements OnInit {
this.polygonBBox = polygonBBox;
});
}

onRoiSave(event) {
if (this.polygonBBox === null) return;
let roiPolygon= this.polygonBBox;
let strToday=new Date();
let dt= new Date(strToday).toISOString();
roiPolygon.name = 'ROI-' + dt.slice(0,dt.lastIndexOf('.'));
this.userStateService.roiList.push(roiPolygon);
this.userStateService.saveROI();
}
onKmlFileSave(event) {
if (this.polygonBBox === null) return;

Expand Down
3 changes: 3 additions & 0 deletions src/app/menupanel/login/login-menu.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
</div>
</button>
<mat-menu #loginMenu="matMenu" style="margin-top:12px;">
<h5 *ngIf="userHasROI()" mat-menu-item (click)="manageROI()"><img src="extension/svg/polygon.svg" fill="#000000" width="24" height="24" style="color:#7E7CAA">
<span style="color:#7ECAA">&nbsp;&nbsp;Manage Region Of Interest</span>
</h5>
<h5 *ngIf="userHasStates()" mat-menu-item (click)="manageStates()">
<span style="color:#7E7CAA"><i class="ti-link"></i>&nbsp;&nbsp;Manage Permanent Links</span>
</h5>
Expand Down
22 changes: 20 additions & 2 deletions src/app/menupanel/login/login-menu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { PermanentLink } from 'app/models/permanentlink.model';
import { User } from 'app/models/user.model';
import { AuthService } from 'app/services/auth/auth.service';
import { UserStateService } from '../../services/user/user-state.service';

import { ROIModalComponent } from 'app/modalwindow/roi/roi.modal.component';
import { CsClipboardService } from '@auscope/portal-core-ui';
@Component({
selector: '[app-login-menu]',
templateUrl: './login-menu.component.html',
Expand All @@ -17,7 +18,7 @@ export class LoginMenuComponent {
user: User;
states: PermanentLink[];

constructor(private router: Router, private authService: AuthService, private userStateService: UserStateService, private modalService: NgbModal) {
constructor(private router: Router, private authService: AuthService, private userStateService: UserStateService, private csClipboardService: CsClipboardService, private modalService: NgbModal) {
this.userStateService.user.subscribe(user => {
this.user = user;
});
Expand All @@ -39,6 +40,23 @@ export class LoginMenuComponent {
logOut() {
this.authService.logout();
}
/**
* Manage user's ROI list
*/
manageROI() {
this.modalService.open(ROIModalComponent, {
size: 'sm',
backdrop: false
});
}
/**
* Test if user has ROI
*
* @returns true if user has saved ROI, false otherwise
*/
public userHasROI(): boolean {
return this.userStateService.roiList.length > 0;
}

/**
* Test if user has states
Expand Down
19 changes: 19 additions & 0 deletions src/app/modalwindow/roi/roi.modal.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<div class="modal-header">
<h4>Region Of Interest</h4><button class="btn btn-sm btn-outline pull-right" aria-label="Close" (click)="activeModal.close()"><i class="fa fa-times"></i></button>
</div>
<div class="modal-body">
<table>
<tbody>
<tr *ngFor = "let roi of userStateService.roiList">
<td>{{roi.name}}</td>
<td class="btn-col" style="white-space: nowrap">
<a class="btn btn-purple btn-xs" title="add to map" (click) = "onAddToPolyFilter(roi)"><i class="ti-map-alt"></i></a>
<a class="btn btn-light btn-xs" title="delete" (click)="onDelete(roi)"><i class="ti-trash"></i></a>
</td>
</tr>
</tbody>
</table>
<form class="text-left">
<button type="button" class="btn btn-primary" (click)="close()">Close</button>
</form>
</div>
69 changes: 69 additions & 0 deletions src/app/modalwindow/roi/roi.modal.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Component, ElementRef, NgModule, OnInit, QueryList, ViewChildren } from '@angular/core';
import { AbstractControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ConfirmModalComponent } from '../confirm/confirm.modal.component';
import { CsClipboardService } from '@auscope/portal-core-ui';
import { CommonModule } from '@angular/common';
import { UserStateService } from 'app/services/user/user-state.service';
import { User } from 'app/models/user.model';



/**
* Modal component used to display a user's ROI lists
*/
@Component({
selector: 'app-roi-form',
templateUrl: './roi.modal.component.html'
})


export class ROIModalComponent {
public user: User;
roiFormArray: UntypedFormArray;
editingROI: number = -1; // Keep track of ROI being edited (-1 = none)
constructor(public csClipboardService: CsClipboardService, public userStateService: UserStateService, private formBuilder: UntypedFormBuilder, private modalService: NgbModal, public activeModal: NgbActiveModal) {

}
/**
* Delete a ROI from user's ROI lists
* @param roi Polygon
*/
public onDelete(roi:any) {
let index = this.userStateService.roiList.indexOf(roi);
this.userStateService.roiList.splice(index,1);
}
/**
* Add a ROI to ClipboardService
* @param roi Polygon
*/
public onAddToPolyFilter(roi:any) {
this.csClipboardService.loadPolygonFromROI(roi);
}
/**
* Close the ROI component.
* Save the ROI to storage.
*/
public close() {
if (this.editingROI !== -1 && this.roiFormArray.controls[this.editingROI].dirty) {
const modalRef = this.modalService.open(ConfirmModalComponent, {
size: 'lg',
backdrop: false
});
modalRef.componentInstance.title = 'Unsaved Changes';
modalRef.componentInstance.modalContent = 'You have unsaved changes, do you wish to continue without saving?';
modalRef.componentInstance.cancelButtonText = 'Cancel';
modalRef.componentInstance.confirmButtonText = 'OK';
modalRef.result.then(result => {
if (result && result === 'OK') {
this.activeModal.close();
}
});
} else {
// Save the ROI to storage.
this.userStateService.saveROI();
this.activeModal.close();
}
}

}
13 changes: 13 additions & 0 deletions src/app/modalwindow/roi/roi.modal.modules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ROIModalComponent } from './roi.modal.component';

@NgModule({
imports: [
CommonModule,
],
declarations: [ ROIModalComponent ],
exports: [ ROIModalComponent ]
})

export class ROIModule { }
44 changes: 44 additions & 0 deletions src/app/services/api/auscope-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,50 @@ export class AuscopeApiService {
}

/**
* Get params for the currently logged in user
* @param key
* @returns string value
*/
public getUserParams(key: string) {
const options = {
params: {
key: key
}
};
return this.apiRequest<string>('secure/getUserParams.do', options);
}

/**
* Delete a user params
* @param key
* @returns true response on success, false otherwise
*/
public deleteUserParams(key: string) {
const options = {
params: {
key: key
}
};
return this.apiRequest<string>('secure/deleteUserParams.do', options);
}

/**
* Update user params
* @param key
* @param value
* @returns true response on success, false otherwise
*/
public saveUserParams(key: string, value: string) {
const options = {
params: {
key: key,
value: value
}
};
return this.apiRequest<string>('secure/saveUserParams.do', options);
}

/*
* Search Elasticsearch index for CSW records and KnownLayers
* @param queryText query string
* @param searchFields search fields
Expand Down
38 changes: 34 additions & 4 deletions src/app/services/user/user-state.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { Injectable } from '@angular/core';
import { Inject, Injectable } from '@angular/core';
import { Bookmark } from 'app/models/bookmark.model';
import { PermanentLink } from 'app/models/permanentlink.model';
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
import { catchError, map, take } from 'rxjs/operators';
import { User } from '../../models/user.model';
import { AuscopeApiService } from '../api/auscope-api.service';
import { CsMapService, ManageStateService } from '@auscope/portal-core-ui';
import { CsMapService, ManageStateService, Polygon, UtilitiesService } from '@auscope/portal-core-ui';
import { v4 as uuidv4 } from 'uuid';
import { HttpResponse } from '@angular/common/http';
import { environment } from 'environments/environment';
import { UILayerModelService } from '../ui/uilayer-model.service';


@Injectable()
export class UserStateService {

Expand All @@ -27,6 +26,10 @@ export class UserStateService {
private _states: BehaviorSubject<PermanentLink[]> = new BehaviorSubject([]);
public readonly states: Observable<PermanentLink[]> = this._states.asObservable();

//ROI for User
public roiList:Polygon[] = [];
public roiKey = '';

constructor(private apiService: AuscopeApiService, private manageStateService: ManageStateService, private csMapService: CsMapService, private uiLayerModelService: UILayerModelService) {}

/**
Expand All @@ -44,6 +47,8 @@ export class UserStateService {
// Update user's bookmarks and map states
this.updateBookmarks();
this.updateUserStates();
// Update user's ROI
this.updateUserROI(user);
}, () => {
// Failure to retrieve User means no User logged in
this.logoutUser();
Expand Down Expand Up @@ -208,5 +213,30 @@ export class UserStateService {
}),
);
}

/**
* Save the user's list of ROI
*/
public saveROI() {
if (UtilitiesService.isEmpty(this.roiKey))
return;

let strROIs = JSON.stringify(this.roiList);
this.apiService.saveUserParams(this.roiKey,strROIs).subscribe(response => {
});
}

/**
* Retrieve a list of ROI associated with the user
* @param user
*/
public updateUserROI(user:User){
let key = 'roiId.'+ user.email;
this.roiKey = key.replace(' ','-');
this.apiService.getUserParams(key).subscribe(strROIs => {
if (strROIs) {
this.roiList = JSON.parse(JSON.parse(JSON.stringify(strROIs)).value);
}
return undefined;
});
}
}
5 changes: 5 additions & 0 deletions src/extension/svg/polygon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 58ae331

Please sign in to comment.