POST
|
Hello everyone, I've been working on a pet project to make a lightweight web GIS editing app leveraging on-premise feature service editing using the 4.18 ArcGIS JS API. I've got it pretty close to where I want it, but have ran into one small hitch. Essentially, I need to pass dynamic lat/lon or XY values to the app (will be coming from another application which has XY location date for our given data layers). The expected behavior would be for the app to launch in a new tab, zoom to the provided coordinates, and display the location where a user will either create a new record, or edit / delete an existing record through the app via the feature service. I found this older thread from 2012 which mentioned using the ?coords= paremater but this doesn't seem to be honored in my app when testing it out. Is this parameter supported at the 4.x JS API? http://localhost/ZoomCoords.html?coords=-117.13,32.82&zoomLevel=8 EDIT: I forgot to add a rather important piece of info. I've tried inserting the below JS into my working code, but I must be missing something as it's failing load with a "missing }" error... I'm no developer...so I'm guessing this is a simply syntax error on my part somewhere: //if there are url params zoom to location
var coords, zoomLevel;
var urlObject = esri.urlToObject(document.location.href);
if(urlObject.query && urlObject.query.coords && urlObject.query.zoomLevel){
var coords = urlObject.query.coords.split(',');
var lon = parseFloat(coords[0]);
var lat = parseFloat(coords[1]);
var zoomLevel = parseInt(urlObject.query.zoomLevel);
var point = esri.geometry.geographicToWebMercator(new esri.geometry.Point(lon,lat));
map.centerAndZoom(point,zoomLevel);
} I've provided my current (working) JS/html code (sans the urlObject snippet above) for the app below in case anyone is interested. Simple insert the feature service url of your choice, and update the popup info with your fields (line 31) and outFields value/s (line 37) and it should be plug and play. For my testing, I tried removing the map center and zoom details (line 50 and 51) and still had no luck with the url parameters. Thanks for any ideas you can provide! <html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>DEQ GIS Spatial Data Editor</title>
<style>
html, body, #viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.18/esri/themes/light/main.css">
<script src="https://js.arcgis.com/4.18/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/Search",
"esri/layers/FeatureLayer",
"esri/widgets/Editor",
"esri/widgets/BasemapToggle",
"esri/widgets/BasemapGallery"
], function(Map, MapView, Search, FeatureLayer, Editor, BasemapToggle, BasemapGallery) {
var popup1 = {
"title": "Feature Information",
"content": "<b>PC Num:</b> {PCNUM}"
}
var PetroleumReleases = new FeatureLayer({
//*** Replace with your URL ***//
url: "yourfeatureserviceurlgoeshere",
outFields: ["PCNUM"],
popupTemplate: popup1
});
var map = new Map({
basemap: "topo-vector",
//*** ADD ***//
layers: [PetroleumReleases]
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [-78.214, 37.59], // longitude, latitude
zoom: 8
});
// Search widget
var search = new Search({
view: view
});
view.ui.add(search, "top-right");
var editorWidget = new Editor({
view: view
});
view.ui.add(editorWidget, "top-left");
function showCoordinates(pt) {
var coords = "Lat/Lon " + pt.latitude.toFixed(3) + " " + pt.longitude.toFixed(3) +
" | Scale 1:" + Math.round(view.scale * 1) / 1 +
" | Zoom " + view.zoom;
coordsWidget.innerHTML = coords;
}
view.watch("stationary", function(isStationary) {
showCoordinates(view.center);
});
view.on("pointer-move", function(evt) {
showCoordinates(view.toMap({ x: evt.x, y: evt.y }));
});
var coordsWidget = document.createElement("div");
coordsWidget.id = "coordsWidget";
coordsWidget.className = "esri-widget esri-component";
coordsWidget.style.padding = "7px 15px 5px";
view.ui.add(coordsWidget, "bottom-right");
var basemapToggle = new BasemapToggle({
view: view,
nextBasemap: "satellite"
});
view.ui.add(basemapToggle, "bottom-left");
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
... View more
12-30-2020
08:59 AM
|
0
|
4
|
2274
|
POST
|
Hey Robert, Yep I have. First browser tested was Firefox, then Chrome. Behavior is reproducible in both. I just tested IE and it's the same there as well.
... View more
12-30-2020
07:28 AM
|
1
|
2
|
1893
|
POST
|
Well now I'm a little stumped and scratching my head on this one. I've checked the PopupMenuInfo.js file, and sure enough, for both apps where we are seeing the url forward vs new tab behavior, I see the code that (I was not expecting to see). Here's an extract from the file. Very strange. Any ideas? Thanks again for the help! _getATagLabel: function() {
var url;
var label;
var itemLayerId = this._layerInfo._isItemLayer && this._layerInfo._isItemLayer();
var layerUrl = this._layerInfo.getUrl();
if (itemLayerId) {
url = portalUrlUtils.getItemDetailsPageUrl(
portalUrlUtils.getStandardPortalUrl(this.layerListWidget.appConfig.portalUrl),
itemLayerId);
label = this.nls.itemShowItemDetails;
} else if (layerUrl &&
(this._layerType === "CSVLayer" || this._layerType === "KMLLayer")) {
url = layerUrl;
label = this.nls.itemDownload;
} else if (layerUrl && this._layerType === "WMSLayer") {
url = layerUrl + (layerUrl.indexOf("?") > -1 ? "&" : "?") + "SERVICE=WMS&REQUEST=GetCapabilities";
label = this.nls.itemDesc;
} else if (layerUrl && this._layerType === "WFSLayer") {
url = layerUrl + (layerUrl.indexOf("?") > -1 ? "&" : "?") + "SERVICE=WFS&REQUEST=GetCapabilities";
label = this.nls.itemDesc;
} else if (layerUrl) {
url = layerUrl;
label = this.nls.itemDesc;
} else {
url = '';
label = this.nls.itemDesc;
}
return '<a class="menu-item-description" target="_blank" href="' +
url + '">' + label + '</a>';
},
... View more
12-30-2020
06:42 AM
|
1
|
4
|
1895
|
POST
|
Thanks Robert! Great question... I'm actually running 2.17, however IIRC the app in question was actually created in 2.15, and manually copied / imported into 2.17 so I'm betting that might be the issue. I'll peep into this code today and verify. Thanks again for your help and insight as always!
... View more
12-30-2020
06:23 AM
|
1
|
0
|
1897
|
POST
|
This is great information- thank you again for your help with this @ThomasHervey1 !
... View more
12-23-2020
12:07 PM
|
0
|
0
|
3343
|
POST
|
Thank you for the response Graham! I'll try to reply in line: That's great to hear. Do you (or does anyone) have any starter-scripts I could use as a basis to further customize? I found a few online but I believe they are outdated from before the Hub / Open Data integration. If not, now worries, I just didn't want to reinvent the wheel if there is already a documented Hub / Open Data api-based script out there for use. This may be what we are encountering but I think I need to understand the "private items" aspect more. All of our Open Data Portal items are shared publicly and available via anonymous REST access. In the AGOL items, they are shared publicly as well. Folks can enter the site without logging in to download any dataset they need- so I'm not sure if that would come into play with our data or not. Sure- my ESS case is #02704584. The local caching issue was reproduced by several of my data editors / data owners as well on various browsers (Mozilla and Chrome at least). Once we cleared the local browser cache and cookies (not sure if cookies were related), the updated or current download pulled successfully. I noticed this because I had a thought to try on my personal laptop which had never accessed the dataset before and voila! It worked, while simultaneously, my work PC pulled an outdated download. Thanks again for the assistance!
... View more
12-23-2020
10:39 AM
|
1
|
0
|
3354
|
POST
|
Hello Hubbers, We recently built and launched a new Hub and Open Data Portal site for our agency (https://geohub-vadeq.hub.arcgis.com/) and so far have really enjoyed both the user and administrative experience it's offered. We have encountered some strange behavior regarding the Open Data Portal and Data Downloads however. I have a case open with Esri Support Services who are assisting, but thought I'd post here to take another approach as well. Our basic deployment / environment is: Open Data Content is pointing to AGOL Feature Layers, that are created from on-premise ArcGIS Server 10.7.1 web services (actually all come from individual layers within this service: https://apps.deq.virginia.gov/arcgis/rest/services/public/EDMA/MapServer) The underlying data source for the web service are a set of file geodatabases that are update nightly via python scripts (primarily truncate and join/appends from Oracle 12c enterprise geodatabases). The weird behavior we have seen lately is: 1) The underlying file geodatabase data and REST service data is updated at night, and we don't see updates at the Open Data Downloads page, more than 8hrs after the underlying data has updated (one such example where we noticed this): https://geohub-vadeq.hub.arcgis.com/datasets/e00ca5e58a8b4c9e9c47e61348d2f040 I resolved this issue by manually updating the AGOL feature layer item tag, which seems to have caused Hub to search for item updates. From speaking with Esri Support, it looks like you can also force Hub to look for updates on all content through the Content Library (upper right < Check for Content Updates)- which seems to send a harvest call to opendata.arcgis.com: https://opendata.arcgis.com/api/v3/jobs/site/53f0be9030ac4298814b66f4a8c7faa8/harvest Would it be possible to script this harvest call using the python api and schedule this to run say 1-2 times daily, so that we know Hub / Open Data pages are always pretty much current with our REST data? 2) Even after the Open Data Page updated, the data downloads (shapefile) were still stale / outdated. I tried clearing local browser cache, incognito, etc., and nothing worked. This behavior was still seen 24hrs after the underlying data updated. In speaking with Esri Support, we found that at the dataset level, you can go in and choose to manually "Recreate Download Files". However, we have ~55 layers that change either daily, weekly, or adhoc (and I'm a shop of 1) so I can't go in daily and manually run this update for all of our data. It looks like when I choose to Recreate the Download Files, I get a "File creation failed" error but I have a feeling it maybe a false flag, and it's actually working...as only the Delete call is getting a 403 server error (screenshot). Would it be possible to script this "Recreate Download Files" and run daily via the Python API to ensure our data downloads are fresh / current as well? 3) Even after we refreshed the Data Download Files, until I went in and cleared out my browser cache and cookies, I was pulling the outdated downloads. So there appears to be a client-side level of caching that is causing issues. Is there a workaround to prevent local browser caching of data downloads so that users aren't unexpectedly pulling outdated data unknowingly? Sorry for the heap of questions...as a recap- it appears there are at least three levels of complexity/issue here: Open Data Item Update caching / frequency Open Data Download Updates caching / frequency Client-side local browser caching. Thanks for any help and information anyone can provide! -Rex
... View more
12-23-2020
06:37 AM
|
1
|
12
|
3753
|
POST
|
Hello WABD gurus, I have what I think is a fairly simple question that I'm hoping someone might be able to help with. Is it possible to force the layer list widget to open the "Description" of a layer (the REST endpoint of a given layer) in a new browser tab, rather than forcing the current browser window (where the web app is) to direct to the REST page? This behavior is a little jarring for users of our app, and they then have to hit "back" to return and reload the web app. I've poked around in some of the Layer List widget config files but don't right off see where I could use something like window.open() method to force the new url to be opened in a new tab instead. Thank you as always for any help you can offer!
... View more
12-23-2020
06:03 AM
|
1
|
7
|
1956
|
POST
|
Hey @RobertScheitlin__GISP - this is great! (sorry for bringing up an old post by the way). This really helped make our grouped layer lists more user friendly in our new app. I did encounter one issue...admittedly, I didn't test this before the code change so I'll go back and verify... however after the change, if/when I choose to "Turn All Layers On", nothing happens. Similarly, if I opt to "Turn All Layers Off" only the parent / root parent turns off now. Have you experience this? We are using the Foldable theme in WABD 2.17. Thanks for any help you can provide!
... View more
11-19-2020
11:59 AM
|
0
|
1
|
940
|
DOC
|
Hello Michelle, Unfortunately, I was unable to find a workaround or fix for this before getting drawn into other work so this has been on my backburner for a while. What I think I narrowed the issue down to was one of two things with most of our apps (or the services / web maps feeding the apps): We currently use a mix of internal map services, combined with some external map services and feature services. The tool seems to pick up the first feature service in the web map / app and ignore the rest. This might or might not contribute to the behavior. The other possible cause is we use a mix of non-grouped and grouped layers in the web map feeding our app. It seems like it picks up the first layer (which is non-grouped) and then can't detect anything after that (starting with the next grouped layer). I'll let you know if I can figure anything else out and best of luck on your side as well! -Rex
... View more
09-25-2020
07:06 AM
|
0
|
0
|
10986
|
POST
|
We are also experiencing this issue at on our Prod SQL 2012 R2 server. Since this seems to be an issue that's popping up, I'm wondering if there's been a recent Windows update that's causing issues or something similar. We are troubleshooting the issue now and will post if we find a resolution.
... View more
08-03-2020
01:34 PM
|
0
|
0
|
5865
|
IDEA
|
Thanks Robert- This would seem to work but i've had a couple of issues with this type of query. The first is it seems to return inconsistent results. I've shown an example below where the first record "Eastern Shore Solar LLC" is not removed as I'd expect...maybe it's my query or syntax but as many other records are removed (131 vs 79) I'm not very confident. The second issue is more of a user / use case of the application. Most of our (200-300 users of these applications) aren't familiar with SQL or creating custom queries so we want to keep the pre-defined user queries / experience as simple as we can. I think you feedback shows how it shouldn't be too difficult for this functionality to be added as predefined query criteria in the Query Widget and Filter tool in the Attribute Table Widget.
... View more
07-24-2020
08:59 AM
|
0
|
0
|
1594
|
IDEA
|
Hello Esri, We have built out a variety of apps using Web Appbuilder and WABD for our agency. Our users have identified a business need to query a variety of layers and fields from the query widget (and filter within the attribute table) via "does not start with" and/or "does not end with" criteria. Currently, the widget offers a variety of query criteria (attached) including "starts with" and "ends with". We'd like to request the additional criteria be added to a future release of WAB / WABD for enhanced query capabilities on text fields. Thanks for your consideration!
... View more
07-24-2020
06:01 AM
|
3
|
4
|
1684
|
POST
|
Sometimes... a little sleep and fresh eyes is all it takes to have an obvious "ah-ha" moment. Turns out dataframe content can be inserted into an email text by simply passing in the variable for the dataframe you want to include. Duh... and it doesn't look great- but not terrible either. Final script is: import numpy as np
import pandas as pd
import requests
import json
import smtplib
# In case of AQM Alert notification, this script will email the identified DEQ recipients. These configuration
# variables can be altered as needed.
scriptname = "AirJSONCalls.py"
primary_email = "Rex xxxxx <xxxxxx@xxxx.virginia.gov>"
backup_email = "xxxx xxxxx <xxxxxx@xxxx.virginia.gov>"
from_email = "xxx-xxx-xxx <xxx-xxx-xxx@xxxx.virginia.gov>"
SMTP_server = "xxxx.xxxx.virginia.gov"
def pyMailer (alert):
SERVER = SMTP_server
FROM = from_email
TO = [primary_email, backup_email]
SUBJECT = "AIR Quality Alert Notification"
MSG = (f"This is an automated message. \n\rThere are Virginia AQM sites reporting concerning levels of AQI data. There are {alert} stations currently exceeding established thresholds. Please invesitage further here: https://www.purpleair.com/map?opt=1/i/mAQI/a10/cC0&select=38835#6.09/38.171/-79.871 \n\rStation Details can be found below:\n\r{df2}")
# Building the message
print ("Building the message...")
MESSAGE = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, TO, SUBJECT, MSG)
# Send the email
print ("Sending the email...")
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, MESSAGE)
server.quit()
#get VA Station Data and organize json into python dictionary to function as pandas dataframe:
r = requests.get('http://www.purpleair.com/json?show=39183|31221|31179|31185|2827|12785|35779|15947|46911|3095|35885|10286|33089|38627|34099|27405|21109|27825|34579|34109|27401|21111|27873|34747|26961|38253|34153|27807|27833|27863|22355|9930|2221|8244|8248|4427|2944|2514|15019|28651|47173|25361|36607|37575|4591|6612|36139|30739|5512|3157|34933|38835|48625|34951|2239|12016|34803|14687|26249|35693|36965|34847|34797|44553|39593|46293|48047|30169')
dictionary = json.loads(r.text)
results = dictionary["results"]
#Set options for dataframe:
pd.options.display.max_columns = None
pd.set_option('display.max_rows', None)
#View results and convert appropriate field (pm2_5_atm) from string to float for quantitative analysis:
df = pd.DataFrame(results)
df.pm2_5_atm = df.pm2_5_atm.astype(float)
#Return / retain only values that exceed threshold (set at 26 to represent close to 100 AQI- need to confirm this number)
df2 = df[df.pm2_5_atm > 10]
#df.sort_values('pm2_5_atm', ascending=False)
df2
total_rows=len(df2.axes[0])
print("Number of Rows: "+str(total_rows))
total_rows=len(df2.axes[0])
print("Number of Rows: "+str(total_rows))
rowcount=(total_rows)
#print (rowcount)
alert = rowcount
#Check to see if any offending values are found for stations and if they are, send notification email. If not, script concludes.
if rowcount > 0:
pyMailer (alert)
else:
print ("Concluded AQM script, no exceedingly high AQI records were found.")
... View more
04-03-2020
06:13 AM
|
1
|
0
|
1414
|
Title | Kudos | Posted |
---|---|---|
1 | 12-08-2022 10:18 AM | |
1 | 12-08-2022 10:29 AM | |
2 | 11-03-2022 08:27 AM | |
2 | 11-10-2022 11:50 AM | |
1 | 11-16-2022 09:24 AM |
Online Status |
Offline
|
Date Last Visited |
12-29-2023
02:56 PM
|