POST
|
Great thanks! I will try that out. But first... I did find another issue when updating my definitionExpression with this line: web_map_dict['operationalLayers'][0]['layerDefinition']['definitionExpression'] = "State = \'" + statesList[i] + "\'" This does not work for ArcGISMapServiceLayers because the JSON to get to the definitionExpression is slightly different. Any ideas on how I need to modify the above line to get "definitionExpression": "ST_ABBREV = 'MN'" to update on this layer? {
"operationalLayers": [
{
"id": "US_ReferenceGeography_points_2789",
"layerType": "ArcGISMapServiceLayer",
"url": "https://.../arcgis/rest/services/US_ReferenceGeography_points/MapServer",
"visibility": true,
"opacity": 1,
"title": "US_ReferenceGeography_points",
"itemId": "1304c6c5e95f4c36aab5d07838ec31cb",
"layers": [
{
"id": 1,
"layerDefinition": {
"definitionExpression": "ST_ABBREV = 'MN'"
}
}
]
}, I've tried this, but keep getting "TypeError: list indices must be integers, not str." web_map_dict['operationalLayers'][0]['layers']['layerDefinition']['definitionExpression'] = "ST_ABBREV = \'" + statesList[i] + "\'" This also opens the door to potentially adding logic to handle definition expressions on multiple layer types.
... View more
05-24-2017
02:49 PM
|
0
|
1
|
1168
|
POST
|
Hi Michael - Yup, that was the issue. This line was replacing all the drawing info with only the definitionExpression: web_map_dict['operationalLayers'][0]['layerDefinition'] = {'definitionExpression': "State = \'" + statesList[i] + "\'"} This resolved the symbology issue while still applying the expression: web_map_dict['operationalLayers'][0]['layerDefinition']['definitionExpression'] = "State = \'" + statesList[i] + "\'" So far this update seems to work properly, however I would still like to figure out how to automate this further by eliminating the need to manually change the layer index. Perhaps searching for the expression in a loop and replacing the specific value? Need to spend some more time on that one.
... View more
05-24-2017
10:02 AM
|
0
|
3
|
1168
|
POST
|
Thanks for the feedback! To provide some more details - I have partly figured out the update, but it isn't totally correct. The idea is that the dictionary from the master web map replaces the map's current dictionary, and then I update the definition expression, title, description, and extent to return the map back to it's pre-updated state with the same details and map id. The code below successfully updates the maps if there is a change to the master map's basemap. However, I tried changing the symbology (of the layer 0) in the master map and found that this method did not work. It seems like this line (trying to update the definition expression back to the state that map should show) is causing issues updating the symbology: web_map_dict['operationalLayers'][0]['layerDefinition'] = {'definitionExpression': "State = \'" + statesList[i] + "\'"}1 # Get the dictionary of the master_map_item
# It will replace the dictionary of the maps to update
master_map_dict = master_map_item.get_data(try_json=True)
for i in range(len(titleList)):
# Search here to get the maps that were created using a list of their titles
webmap_search = gis.content.search(titleList[i], item_type="Web Map")
web_map_item = webmap_search[0]
# Get and set the dictionary of the map to be updated
web_map_dict = web_map_item.get_data(try_json=True)
# Set the dictionary of the map to be updated equal to the master item's dictionary
web_map_dict = master_map_dict
# Change the web_map_dict back to reflect orig state: def expression, title, description, state extent
# Works by iterating through lists of states, titles, descriptions, and extents that correspond to the 50 states in ABC order
web_map_dict['operationalLayers'][0]['layerDefinition'] = {'definitionExpression': "State = \'" + statesList[i] + "\'"}
web_map_properties = {'title': titleList[i],
'snippet':descList[i],
'extent':stateExtentList[i],
'text':json.dumps(web_map_dict)}
# Update the item - giving it the "new" - aka original properties back
web_map_item.update(web_map_properties) This is probably pretty rough as I'm still learning the API and Python, but any suggestions are appreciated. Thanks!
... View more
05-18-2017
09:23 AM
|
1
|
5
|
1168
|
POST
|
Using the ArcGIS Python API and Jupyter Notebook, I've figured out how to automate the creation of multiple web maps in our portal based on copying a "master" web map. During this process, I update only a few things on the new maps (title, description, initial extent, definition expression on a layer). But with the automation of creating 50+ web maps, I am now trying to figure out how I could automate updating all these maps if there were a change in the "master" web map. I have a couple similar ideas, but not sure how to implement them, or if they are even possible. Or if there is a more efficient solution to this... 1) Deep copy of the "master" webmap dictionary (ignoring the keys that cannot change in the map to be updated - ex. id, created, title, extent, layer definition expression) and then using the copy to replace all the other keys in my "map-to-be-updated" 2) Comparing the dictionaries of the "master" and "map-to-be-updated", find any differences (again ignoring the keys that cannot change) and taking the differences found and applying them to the "map-to-be-updated" I'm also not entirely sure how to search for and work with multiple items based on the examples provided... if anyone has info on that as well. I've reviewed (and used) these examples the most: Publishing web maps and web scenes | ArcGIS for Developers Using and updating GIS content | ArcGIS for Developers I'm fairly new to Python as well, so any suggestions would be appreciated!
... View more
05-12-2017
01:23 PM
|
0
|
7
|
2021
|
IDEA
|
We have users that make maps using desktop software, which are then published to our portal (federated environment). Their publishing rights are controlled through publisher roles that are configured within the portal site. When they publish services, they have the ability to publish anywhere on server - which is explained in this server documentation: "If a role's type is set to either Administrator or Publisher, that role automatically gets implicit access permission to all GIS web services hosted on the ArcGIS Server site. This implicit permission cannot be overridden by changing the permissions on a service or folder." This is problematic as services get published all over the server, including in the root. Because this happens behind the scenes, users are often not aware of where their services ended up on the server - making maintenance, clean up, and troubleshooting of services difficult and time consuming. Our support team currently has to monitor each folder for any services that do not belong there, manually look up the owner in portal, reach out, help them publish again into the correct location, and then delete the original from the wrong location. We would like the ability to enforce publishing locations on the server so that we can eliminate these extra steps and keep everything "behind the scenes" clean and organized.
... View more
03-30-2017
03:18 PM
|
12
|
6
|
1841
|
POST
|
I am working off the latest version of this Time Aware template: GitHub - Esri/time-aware-template: Time Aware is a configurable application template that enables you to display time en… And need to modify the template to continuously use real-time data provided by a time-enabled weather service. It is essentially a live looping weather radar. Within _displayTime, the following has been modified to use a "real-time" timeExtent. Where endTime is the current time, and startTime is that time minus 2 hours. if (timeProperties.endTime > timeProperties.startTime) {
timeExtent = new TimeExtent(startTime = new Date(Date.now() - (7200000)), endTime = new Date(Date.now()));
} This works well, with the exception that _displayTime is only called once, and the time slider quickly becomes out of date as it continues to loop through the same (old) time extent elsewhere in the template. For now, the application refreshes entirely every 15 minutes to pull a current time extent. However, it ideally needs to update to the current endTime every 15 minutes without reloading the entire app. I believe this would be accomplished by shifting the slider forward by 15 minutes (after 15 minutes), and dropping the oldest 15 minute time segment. I've tried to leverage this example: javascript - How to programmatically change the timeExtent of a Map & update the timeSlider? - Geographic Information Sy… But I am unsure how to reset the timeExtent of the existing time slider in terms of the overall template. I've also tried different variations of timeout functions/setInterval but still unsure how this shift would be accomplished seamlessly. The template also has the following code on "time-extent-change" and I'm wondering if this is something I need to find a way to use? on(timeSlider, "time-extent-change", lang.hitch(this, function(e) {
if (!e.startTime && e.endTime) {
console.log("Missing start time");
}
this._formatTime(e);
// Are we at the end?
var slider = timeSlider._slider,
val;
if (lang.isArray(slider.value)) {
val = slider.value[1];
} else {
val = slider.value;
}
if (val == slider.maximum && timeSlider.loop !== true) {
// At slider end so set play buttton
this._updatePlayButton("icon-play", "icon-pause");
on.once(dom.byId("playSlider"), "click", function() {
if (val == slider.maximum) {
timeSlider.play();
if (timeSlider.thumbCount > 1) {
timeSlider.setThumbIndexes([0, 1]);
} else {
timeSlider.setThumbIndexes(0);
}
}
});
}
})); Does anyone familiar with this template know how this functionality could be added?
... View more
11-07-2016
09:24 AM
|
0
|
0
|
1020
|
POST
|
Thanks so much Robert, that worked! However, it caused some display issues with my other (coded value type) FilteringSelect widget. It was still filtering on the map, but it was no longer allowing text input and the selected value would not display in the box. I'm guessing something with the timeout? Not sure if this is the ideal solution/good code practice, but I duplicated the original _createDropdownList, renamed to _createDropdownListCodedVals, and changed the call within _createFilterField: _createDropdownListCodedVals: function(param, values) {
var container = domConstruct.create("div", {
className: "styled-select small"
});
// Modify select to utilize Dojo - Dijit FilteringSelect Widget
var select = domConstruct.create("select", {
dojotype: "dijit/form/FilteringSelect",
id: param.inputId
}, container);
array.forEach(values, function(val, index) {
domConstruct.create("option", {
value: val.code,
innerHTML: val.name,
selected: (val.name === param.defaultValue) ? true : false
}, select);
});
var node = container.outerHTML ? container.outerHTML : container.innerHTML;
console.log("node " + node);
return node;
}, _createFilterField: if (field && field.domain && field.domain.codedValues) {
paramInputs = this.__createDropdownListCodedVals(param, field.domain.codedValues);
deferred.resolve(paramInputs);
} This fixed the problem, but please let me know if there is a better way to resolve this. Thanks again!
... View more
10-31-2016
08:33 AM
|
0
|
1
|
974
|
POST
|
There is a new version of this template on GitHub that might help. It now has drop downs for coded value and string type layers. It replaced the static text box to a drop down menu for me after switching to the new version. GitHub - Esri/InteractiveFilter: Filter is a configurable application template that displays a map with an interactive f…
... View more
10-28-2016
01:23 PM
|
0
|
0
|
348
|
POST
|
I am currently working off of the latest version of the Interactive Filter template. (GitHub - Esri/InteractiveFilter: Filter is a configurable application template that displays a map with an interactive f… ) And I need to replace the default drop down with a Dijit FilteringSelect from the Dojo Toolkit (dijit.form.FilteringSelect — The Dojo Toolkit - Reference Guide) This will allow the user to provide input in addition to the drop down, with autocomplete functionality when typing. I prefer the FilteringSelect as it will give an error if their search field isn't found in the layer. I have been trying to do this in a way that works with the overall template structure, as to not completely blow up the map filtering functionality. Currently, I have found a way to replace the drop down for layers with coded values, but the string type layers are not drawing the Dijit at all. Here is the _createFilterField function, where filter fields are created based on the layer type (coded values, integer, string): _createFilterField: function(param, filterLayer, fields) {
var deferred = new Deferred();
var field = null,
paramInputs = null;
param.inputId = filterLayer.id + "." + param.parameterId + ".value";
array.some(fields, function(f) {
if (f.name === param.fieldName) {
field = f;
return true;
}
});
if (field && field.domain && field.domain.codedValues) {
paramInputs = this._createDropdownList(param, field.domain.codedValues);
deferred.resolve(paramInputs);
} else if (field && field.type === "esriFieldTypeInteger") { //the pattern forces the numeric keyboard on iOS. The numeric type works on webkit browsers only
paramInputs = lang.replace("<input class='param_inputs' type='number' id='{inputId}' pattern='[0-9]*' value='{defaultValue}' />", param);
deferred.resolve(paramInputs);
} else { //string
var capabilities = filterLayer.advancedQueryCapabilities;
if (capabilities.supportsDistinct && this.uniqueVals) {
var distinctQuery = new Query();
distinctQuery.where = "1=1";
distinctQuery.orderByFields = [field.name];
distinctQuery.returnGeometry = false;
distinctQuery.outFields = [field.name];
distinctQuery.returnDistinctValues = true;
var qt = new QueryTask(filterLayer.url);
qt.execute(distinctQuery, lang.hitch(this, function(results) {
var values = results.features.map(function(f, index) {
return {
name: f.attributes[field.name],
code: f.attributes[field.name]
};
});
var container = this._createDropdownList(param, values);
deferred.resolve(container);
}), function(error) {
deferred.resolve(error);
});
} else {
// string
paramInputs = lang.replace("<input class='param_inputs' type='text' id='{inputId}' value='{defaultValue}' />", param);
deferred.resolve(paramInputs);
}
}
return deferred.promise;
}, And here is my version of _createDropdownlist function, which sets up the drop down. _createDropdownList: function(param, values) {
var container = domConstruct.create("div", {
className: "styled-select small"
});
// Modify select to utilize Dojo - Dijit FilteringSelect Widget
var select = domConstruct.create("select", {
dojotype: "dijit/form/FilteringSelect",
id: param.inputId
}, container);
array.forEach(values, function(val, index) {
domConstruct.create("option", {
value: val.code,
innerHTML: val.name,
selected: (val.name === param.defaultValue) ? true : false
}, select);
});
var node = container.outerHTML ? container.outerHTML : container.innerHTML;
console.log("node " + node);
return node;
}, I have added line 10 above to manipulate the select element to become a FliteringSelect. dojotype: "dijit/form/FilteringSelect", To my surprise, this worked for the coded value layers. But not string type. Here's a screenshot of the filterable layers: The first (Admit by Diagnosis) is the Dijit with autocomplete. The Second (Plan Name) is just a simple drop down. Anyone familiar with this template - any ideas why this might be happening? And how I can leverage the existing template code for string types?
... View more
10-28-2016
01:14 PM
|
0
|
4
|
1958
|
Title | Kudos | Posted |
---|---|---|
1 | 05-18-2017 09:23 AM | |
12 | 03-30-2017 03:18 PM |
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:24 AM
|