Skip to content

Commit

Permalink
Merge pull request #419 from AuScope/Release-Custom-Layers-Fix
Browse files Browse the repository at this point in the history
AUS-4212 Fix Custom Layers (Release)
  • Loading branch information
PeterWarren authored Jul 18, 2024
2 parents 7783b1b + 7d3b709 commit 05a3d21
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 171 deletions.
2 changes: 0 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ import { AppRoutingModule } from './app-routing.module';
import { UserStateService } from './services/user/user-state.service';
import { AuthGuard } from './services/auth/auth.guard';
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';
Expand All @@ -139,7 +138,6 @@ PlotlyModule.plotlyjs = PlotlyJS;
CesiumMapPreviewComponent,
BrowsePanelComponent,
CustomPanelComponent,
LayerGroupComponent,
ActiveLayersPanelComponent,
FilterPanelComponent,
SearchPanelComponent,
Expand Down
44 changes: 42 additions & 2 deletions src/app/menupanel/custompanel/custompanel.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,27 @@
</span>
</div>
<!-- Once a URL has been selected and processed, its available layers are shown here -->
<layer-group *ngIf="urlLayerGroups.Results.length > 0" layerGroup [layerGroups]="urlLayerGroups" style="left:-5.2em;"></layer-group>
<table class="custom-table">
<tr *ngFor="let layer of urlLayers" class="custom-result-row">
<td>
<div>
<div class="text-truncate">{{layer.name}}</div>
<i *ngIf="getUILayerModel(layer.id)?.statusMap.getRenderStarted() && !getUILayerModel(layer.id)?.statusMap.getRenderComplete()" class="float-right light-blue fa fa-spin fa-spinner"></i>
<i *ngIf="getUILayerModel(layer.id)?.statusMap.getRenderStarted() && getUILayerModel(layer.id)?.statusMap.getContainsError()" class="fa fa-warning text-warning"></i>
</div>
</td>
<td>
<button *ngIf="!uiLayerModelService.isLayerAdded(layer.id)" class="btn-sm btn-success custom-btn" (click)="addLayer(layer)">Add&nbsp;<i class="fa fa-plus"></i></button>
<button *ngIf="uiLayerModelService.isLayerAdded(layer.id)" class="btn-sm btn-danger custom-btn" (click)="removeLayer(layer)">Remove&nbsp;<i class="fa fa-trash"></i></button>
<button *ngIf="layer.group !== 'kml-layer' && layer.group !== 'kmz-layer'" class="btn-sm btn-info custom-btn" (click)="displayRecordInfo(layer)">Info&nbsp;<i class="fa fa-info-circle"></i></button>
</td>
<!--
<div *ngIf="getUILayerModel(layer.id).statusMap.getRenderStarted()" class="progress progress-xs" style="height: 5px">
<div class="progress-bar bg-gradient-blue-purple" [style.width]="getUILayerModel(layer.id).statusMap.getCompletePercentage()" role="progressbar"></div>
</div>
-->
</tr>
</table>

<!-- Custom Layer KML File Input -->
<div class="form-group">
Expand All @@ -30,4 +50,24 @@
</div>
</div>
<!-- Once a file has been uploaded, its layer is shown here -->
<layer-group *ngIf="fileLayerGroups.Results.length > 0" [layerGroups]="fileLayerGroups"></layer-group>
<table class="custom-table">
<tr *ngFor="let layer of fileLayers" class="custom-result-row">
<td>
<div>
<div class="text-truncate">{{layer.name}}</div>
<i *ngIf="getUILayerModel(layer.id)?.statusMap.getRenderStarted() && !getUILayerModel(layer.id)?.statusMap.getRenderComplete()" class="float-right light-blue fa fa-spin fa-spinner"></i>
<i *ngIf="getUILayerModel(layer.id)?.statusMap.getRenderStarted() && getUILayerModel(layer.id)?.statusMap.getContainsError()" class="fa fa-warning text-warning"></i>
</div>
</td>
<td>
<button *ngIf="!uiLayerModelService.isLayerAdded(layer.id)" class="btn-sm btn-success custom-btn" (click)="addLayer(layer)">Add&nbsp;<i class="fa fa-plus"></i></button>
<button *ngIf="uiLayerModelService.isLayerAdded(layer.id)" class="btn-sm btn-danger custom-btn" (click)="removeLayer(layer)">Remove&nbsp;<i class="fa fa-trash"></i></button>
<button *ngIf="layer.group !== 'kml-layer' && layer.group !== 'kmz-layer'" class="btn-sm btn-info custom-btn" (click)="displayRecordInfo(layer)">Info&nbsp;<i class="fa fa-info-circle"></i></button>
</td>
<!--
<div *ngIf="getUILayerModel(layer.id).statusMap.getRenderStarted()" class="progress progress-xs" style="height: 5px">
<div class="progress-bar bg-gradient-blue-purple" [style.width]="getUILayerModel(layer.id).statusMap.getCompletePercentage()" role="progressbar"></div>
</div>
-->
</tr>
</table>
19 changes: 19 additions & 0 deletions src/app/menupanel/custompanel/custompanel.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.custom-table {
table-layout: fixed;
margin-bottom: 5px;
width: 100%;

.custom-result-row {
vertical-align: baseline;

.text-truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.custom-btn {
line-height: 0.8em;
}
}
}
116 changes: 75 additions & 41 deletions src/app/menupanel/custompanel/custompanel.component.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
import { Component, Output, Inject, EventEmitter } from '@angular/core';
import { LayerHandlerService, LayerModel, RenderStatusService, KMLDocService, ResourceType,
Constants } from '@auscope/portal-core-ui';
import { NgbdModalStatusReportComponent } from '../../toppanel/renderstatus/renderstatus.component';
import { BsModalService } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal';
Constants, CsMapService} from '@auscope/portal-core-ui';
import { UILayerModel } from '../common/model/ui/uilayer.model';
import { UILayerModelService } from 'app/services/ui/uilayer-model.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import * as JSZip from 'jszip';
import { HttpClient } from '@angular/common/http';
import { throwError as observableThrowError, Observable } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { HttpResponse } from '@angular/common/http';
import { LayerManagerService } from 'app/services/ui/layer-manager.service';
import { SidebarService } from 'app/portal/sidebar.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { InfoPanelComponent } from '../common/infopanel/infopanel.component';

type LayerGroups = { 'Results': LayerModel[] };

@Component({
selector: '[appCustomPanel]',
templateUrl: './custompanel.component.html',
styleUrls: ['../menupanel.scss']
styleUrls: ['../menupanel.scss', './custompanel.component.scss']
})


export class CustomPanelComponent {

// URL that the user types in
Expand All @@ -34,35 +31,35 @@ export class CustomPanelComponent {
statusMsg: string;

// Displays custom layers for URLs in sidebar
urlLayerGroups: LayerGroups = { 'Results': [] };
urlLayers: LayerModel[] = [];

// Displays custom layers for KML file in sidebar
fileLayerGroups: LayerGroups = { 'Results': [] };
fileLayers: LayerModel[] = [];

bsModalRef: BsModalRef;
@Output() expanded: EventEmitter<any> = new EventEmitter();

constructor(private http: HttpClient,
private layerHandlerService: LayerHandlerService,
private layerManagerService: LayerManagerService,
private renderStatusService: RenderStatusService,
private modalService: BsModalService,
private uiLayerModelService: UILayerModelService,
public activeModalService: NgbModal,
private kmlService: KMLDocService,
private sidebarService: SidebarService,
private csMapService: CsMapService,
public activeModalService: NgbModal,
@Inject('env') private env
) {
this.loading = false;
this.statusMsg = 'Enter your OGC WMS service endpoint</br>e.g. "https://server.gov.au/service/wms"</br>or KML/KMZ URL and hit <i class="fa fa-search"></i>.';
}

/**
* Makes a filter or download tab panel visible
*
* @param layerId layer id string
* @param panelType panel type string, either 'filterpanel' or 'downloadpanel'
* Get the UILayerModel for the layer
* @param layerId ID of layer
* @returns UILayerModel for layer
*/
public selectTabPanel(layerId: string, panelType: string) {
this.uiLayerModelService.getUILayerModel(layerId).tabpanel.setPanelOpen(panelType);
public getUILayerModel(layerId: string): UILayerModel {
return this.uiLayerModelService.getUILayerModel(layerId);
}

/**
Expand All @@ -87,7 +84,7 @@ export class CustomPanelComponent {
this.statusMsg = '';

// Clear the results from the previous search, start the loading spinner
this.urlLayerGroups = { 'Results': [] };
this.urlLayers = [];
this.loading = true;

// Check for empty URL
Expand Down Expand Up @@ -118,16 +115,16 @@ export class CustomPanelComponent {
const proxyUrl = this.env.portalBaseUrl + Constants.PROXY_API + "?usewhitelist=false&url=" + searchUrl;

this.getGoogleMapDoc(proxyUrl).subscribe(response => {
let kml = response;
const kml = response;

const reader = new FileReader();

// This fires after the blob has been read/loaded.
reader.addEventListener('loadend', (e) => {
var kmlTxt = e.target.result;
const kmlTxt = e.target.result;

// Remove unwanted characters and inject proxy for embedded URLs
let kmlStr = this.kmlService.cleanKML(kmlTxt.toString());
const kmlStr = this.kmlService.cleanKML(kmlTxt.toString());

const parser = new DOMParser();
let kmlDoc = parser.parseFromString(kmlStr, "text/xml");
Expand All @@ -140,10 +137,8 @@ export class CustomPanelComponent {

// Start reading the blob as text.
reader.readAsText(kml);

});


} else {
// If KMZ URL ...
if (searchUrl.toLowerCase().endsWith('.kmz')) {
Expand Down Expand Up @@ -173,16 +168,16 @@ export class CustomPanelComponent {

// This fires after the blob has been read/loaded.
reader.addEventListener('loadend', (e) => {
var kmzTxt = e.target.result;
const kmzTxt = e.target.result;

let getDom = xml => (new DOMParser()).parseFromString(xml, "text/xml")

const getExtension = fileName => fileName.split(".").pop().toLowerCase();

// unzip the kmz and iterate through the files
var zipKMZ = new JSZip(); // reassemble the kmz (files) in this object
const zipKMZ = new JSZip(); // reassemble the kmz (files) in this object
let getKmzDom = (kmzDoc) => {
var zip = new JSZip()
const zip = new JSZip()
return zip.loadAsync(kmzDoc)
.then(zip => {
let kmlDom = null
Expand All @@ -192,7 +187,7 @@ export class CustomPanelComponent {
kmlDom = file.async("string").then(x => {

// Remove unwanted characters and inject proxy for embedded URLs
let kmlStr = this.kmlService.cleanKMZ(x);
const kmlStr = this.kmlService.cleanKMZ(x);

const parser = new DOMParser();
let kmlDoc = parser.parseFromString(kmlStr, "text/xml");
Expand All @@ -208,24 +203,20 @@ export class CustomPanelComponent {
//zipKMZ.file(relPath, kmlStr);
zipKMZ.file(relPath, xmlStr);
})

} else {
// add the file (non kml) into the zip
file.async("blob").then(x => {
zipKMZ.file(relPath, x);
});
}
//})
})

return kmlDom || Promise.reject("No kmz file found")

}).catch(function (err) {
return console.log("ERROR [unzipping kmz]: " + err.msg + JSON.stringify(err));
})
};

getKmzDom(kmzTxt).then(kmzDom => {
getKmzDom(kmzTxt).then(() => {

let me = this;

Expand Down Expand Up @@ -264,7 +255,7 @@ export class CustomPanelComponent {
// Evaluate the layers and if found set up loadable map layers
for (const layerRec of layerRecs) {
// Make the layer group listing visible in the UI
this.urlLayerGroups['Results'].unshift(layerRec);
this.urlLayers.unshift(layerRec);
// Configure layers so they can be added to map
const uiLayerModel = new UILayerModel(layerRec.id, this.renderStatusService.getStatusBSubject(layerRec));
this.uiLayerModelService.setUILayerModel(layerRec.id, uiLayerModel);
Expand Down Expand Up @@ -293,12 +284,14 @@ export class CustomPanelComponent {
*
* @param uiLayerModel ui layer model object whose status will be displayed
*/
/*
public openStatusReport(uiLayerModel: UILayerModel) {
this.bsModalRef = this.modalService.show(NgbdModalStatusReportComponent, { class: 'modal-lg' });
uiLayerModel.statusMap.getStatusBSubject().subscribe((value) => {
this.bsModalRef.content.resourceMap = value.resourceMap;
});
}
*/

/**
* adds support so that kmlFeatureDatasupport will display a features attributes when they
Expand Down Expand Up @@ -376,7 +369,7 @@ export class CustomPanelComponent {
* @returns true if the layer is found within recordsList, false otherwise
*/
private recordsListContainsRecord(recordsList: any, name: string, url: string): boolean {
if (recordsList['Results'].findIndex(x => x.cswRecords[0].name === name && x.cswRecords[0].onlineResources[0].url === url) != -1) {
if (recordsList.findIndex(x => x.cswRecords[0].name === name && x.cswRecords[0].onlineResources[0].url === url) != -1) {
return true;
}
return false;
Expand All @@ -392,17 +385,19 @@ export class CustomPanelComponent {
// Make a layer model object
if (docType == ResourceType.KMZ) {
layerRec = me.layerHandlerService.makeCustomKMZLayerRecord(name, proxyUrl, kmzData);
layerRec.group = 'kmz-layer';
} else {
layerRec = me.layerHandlerService.makeCustomKMLLayerRecord(name, proxyUrl, kmzData);
layerRec.group = 'kml-layer';
}
// Configure layers so it can be added to map
const uiLayerModel = new UILayerModel(layerRec.id, me.renderStatusService.getStatusBSubject(layerRec));
me.uiLayerModelService.setUILayerModel(layerRec.id, uiLayerModel);
// Make the layer group listing visible in the UI
if (sourceType == "URL" && !this.recordsListContainsRecord(me.urlLayerGroups, name, proxyUrl)) {
me.urlLayerGroups['Results'].unshift(layerRec);
} else if (!this.recordsListContainsRecord(me.fileLayerGroups, name, proxyUrl)) {
me.fileLayerGroups['Results'].unshift(layerRec);
if (sourceType == "URL" && !this.recordsListContainsRecord(me.urlLayers, name, proxyUrl)) {
me.urlLayers.unshift(layerRec);
} else if (!this.recordsListContainsRecord(me.fileLayers, name, proxyUrl)) {
me.fileLayers.unshift(layerRec);
}
}

Expand Down Expand Up @@ -492,4 +487,43 @@ export class CustomPanelComponent {
}
}
}

/**
* Add a KML layer to the map
*
* @param layer the KML LayerModel
*/
public addLayer(layer: LayerModel) {
this.layerManagerService.addLayer(layer, [], null, null);
this.sidebarService.setOpenState(true);
}

/**
* Remove a KML layer from the map.
*
* @param layer the KML LayerModel
*/
public removeLayer(layer: LayerModel) {
this.layerManagerService.removeLayer(layer);
if (this.csMapService.getLayerModelList()?.length === 0) {
this.sidebarService.setOpenState(false);
}
}

/**
* Display layer information in modal
*
* @param layer the LayerModel
*/
public displayRecordInfo(layer: LayerModel) {
if (layer) {
const modelRef = this.activeModalService.open(InfoPanelComponent, {
size: "lg",
backdrop: false
});
modelRef.componentInstance.cswRecords = layer.cswRecords;
modelRef.componentInstance.layer = layer;
}
}

}
Loading

0 comments on commit 05a3d21

Please sign in to comment.